diff --git a/.gitignore b/.gitignore index 750cd37ddd2..283b278079d 100644 --- a/.gitignore +++ b/.gitignore @@ -100,3 +100,8 @@ nbproject/ !thriveversion.ver # Temporary/backup files *~ + + +# Cscope files +/cscope.files +/RunCodeIndexing.rb \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index f29d6b26156..a680cdbe3c6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "contrib/googletest"] path = contrib/googletest url = git://github.com/liquid-mirror/googletest.git -[submodule "contrib/luabind"] - path = contrib/luabind - url = git://github.com/rpavlik/luabind.git +[submodule "contrib/lua/luajit"] + path = contrib/lua/luajit + url = http://luajit.org/git/luajit-2.0.git diff --git a/CMakeLists.txt b/CMakeLists.txt index ce5bd2f3c55..5e37271fa12 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,7 +88,7 @@ set(OGRE_PLUGINS # Plugin_OctreeSceneManager # Plugin_OctreeZone Plugin_ParticleFX - Plugin_CgProgramManager + # Plugin_CgProgramManager # Plugin_PCZSceneManager RenderSystem_GL ) @@ -137,21 +137,36 @@ find_package(Bullet REQUIRED QUIET) include_directories(SYSTEM ${BULLET_INCLUDE_DIRS}) -########## -# TinyXML # -########## - -find_package(TinyXML REQUIRED QUIET) - ####### # Lua # ####### +option(LUA_CHECKS "when ON enables additional Lua safety + checks. Lowers performance so only use while debugging" + OFF) + +if(LUA_CHECKS) + + add_definitions(-DSOL_CHECK_ARGUMENTS) + +endif() + include_directories( - SYSTEM - "${CMAKE_CURRENT_SOURCE_DIR}/contrib/lua/lua/src" - "${CMAKE_CURRENT_SOURCE_DIR}/contrib/luabind/" -) + "${CMAKE_CURRENT_SOURCE_DIR}/contrib/lua" + ) + +link_directories( + "${CMAKE_CURRENT_SOURCE_DIR}/contrib/lua/luajit/src" + ) + +set(LUA_FOUND TRUE) + +if(WIN32) + set(LUA_LIBRARIES lua51.dll) +else() + set(LUA_LIBRARIES luajit.a dl) +endif() + ####### # CEGUI # @@ -177,26 +192,6 @@ find_package(TinyXML REQUIRED QUIET) include_directories(SYSTEM ${TINYXML_INCLUDE_DIR}) -if(WIN32) - add_definitions(-DLUA_BUILD_AS_DLL) -endif() - -add_subdirectory( - "${CMAKE_CURRENT_SOURCE_DIR}/contrib/lua/" -) - -set(LUA_FOUND TRUE) -set(LUA_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/lua/lua/src") -set(LUA_LIBRARIES lua) -#set(BUILD_SHARED_LUABIND ON) -#set(INSTALL_LUABIND ON) -set(LIB_DIR bin) -add_definitions(-DLUABIND_CPLUSPLUS_LUA) - -add_subdirectory( - "${CMAKE_CURRENT_SOURCE_DIR}/contrib/luabind/" -) - ################ # cAudio # ################ @@ -230,7 +225,10 @@ include_directories( # Compile using c++11 and using sse2 #no-unused-variable is necessary to supress werror while compiling cAudio -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y -msse2 -Wno-unused-function") +# SOL uses a bunch of recursive templates so unless all lua bindings are written to be +# less efficient runtime dynamic bindings we need to have bigger template depth. +# though this may kill compile times +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y -msse2 -Wno-unused-function -Wno-error=redundant-decls -ftemplate-depth=1500" ) find_package(Threads) @@ -265,7 +263,7 @@ target_link_libraries(ThriveLib ${CEGUI_LIBRARY} ${TINYXML_LIBRARIES} ${OpenAL_LIBRARIES} - luabind + ${LUA_LIBRARIES} ) target_link_libraries(ThriveLib @@ -331,7 +329,7 @@ set_source_files_properties( ) add_executable(RunTests ${TEST_SOURCE_FILES}) -target_link_libraries(RunTests ThriveLib gtest_main) +target_link_libraries(RunTests ThriveLib gtest_main ${LUA_LIBRARIES}) ################# # Documentation # @@ -367,10 +365,6 @@ install(TARGETS Thrive LIBRARY DESTINATION bin ) -install(EXPORT lua - DESTINATION bin -) - # Version file install(FILES @@ -581,6 +575,8 @@ if(WIN32) "${MINGW_ENV}/install/bin/avutil-55.dll" "${MINGW_ENV}/install/bin/swscale-4.dll" "${MINGW_ENV}/install/bin/swresample-2.dll" + "${CMAKE_SOURCE_DIR}/contrib/lua/luajit/src/lua51.dll" + "${CMAKE_SOURCE_DIR}/contrib/lua/luajit/src/luajit.exe" DESTINATION bin CONFIGURATIONS Debug ) @@ -640,6 +636,12 @@ elseif(UNIX) OGRE_PLUGIN_LIB_DBG OGRE_PLUGIN_LIB_REL ) + + if(NOT EXISTS "${OGRE_PLUGIN_LIB_REL}" OR NOT EXISTS "${OGRE_PLUGIN_LIB_DBG}") + message(SEND_ERROR "Ogre plugin file doesn't exist: ${OGRE_PLUGIN} . Did you build " + "all the required Ogre plugins?") + endif() + # Release InstallFollowingSymlink( ${OGRE_PLUGIN_LIB_REL} @@ -688,12 +690,24 @@ if(UNIX) "${CMAKE_CURRENT_BINARY_DIR}/CMakeLibraryList.xml" @ONLY ) - add_custom_target(linuxrelease - COMMAND "${CMAKE_SOURCE_DIR}/cpack/PackageProject.rb" "${CMAKE_CURRENT_BINARY_DIR}" - WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/cpack" - DEPENDS ThriveLib doc - ) - # The name of the Thrive target somehow breaks in the above command - add_dependencies(linuxrelease Thrive) + if(LUA_CHECKS) + + # creating debug releases is bad + add_custom_target(linuxrelease + # Please don't touch this really complex command output format + COMMAND "ruby" "-e" \"puts \\\"\\033[31m\\\"\; puts 'ERROR: LUA_CHECKS is on. release build is disabled. Please run \\'cmake .. -DLUA_CHECKS=OFF\\' and try again'\; puts \\\"\\033[0m\\\"\; exit(3) \" + ) + + else() + + add_custom_target(linuxrelease + COMMAND "${CMAKE_SOURCE_DIR}/cpack/PackageProject.rb" "${CMAKE_CURRENT_BINARY_DIR}" + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/cpack" + DEPENDS ThriveLib doc + ) + # The name of the Thrive target somehow breaks in the above command + add_dependencies(linuxrelease Thrive) + + endif() endif() diff --git a/SetupThrive.rb b/SetupThrive.rb index 3bd16fe5e7f..7c3f68261d9 100755 --- a/SetupThrive.rb +++ b/SetupThrive.rb @@ -25,6 +25,12 @@ def checkRunFolder(suggestedfolder) end end +def projectFolder(baseDir) + + return File.join baseDir, "thrive" + +end + ThriveBranch = "master" #ThriveBranch = "ruby_setup" SkipPackageManager = false @@ -46,7 +52,7 @@ def checkRunFolder(suggestedfolder) PackagesToInstall = "bullet-devel boost gcc-c++ libXaw-devel freetype-devel " + "freeimage-devel zziplib-devel boost-devel ois-devel tinyxml-devel " + - "glm-devel ffmpeg-devel ffmpeg-libs openal-soft-devel libatomic Cg" + "glm-devel ffmpeg-devel ffmpeg-libs openal-soft-devel libatomic" elsif LinuxOS.casecmp("Ubuntu") == 0 @@ -124,12 +130,22 @@ def checkRunFolder(suggestedfolder) Dir.chdir(File.join(CurrentDir, "thrive")) do - systemChecked "git checkout #{ThriveBranch}" - systemChecked "git pull --recurse-submodules origin #{ThriveBranch}" + system "git checkout #{ThriveBranch}" + + if $?.exitstatus > 0 + + warning "Failed to checkout target thrive branch" + + else + + systemChecked "git pull --recurse-submodules origin #{ThriveBranch}" + + end + systemChecked "git submodule update --recursive" # submodule init check - if not File.exists? File.join(CurrentDir, "thrive", "contrib/luabind/luabind", "object.hpp") + if not File.exists? File.join(CurrentDir, "thrive", "contrib/lua/luajit/src", "lua.hpp") warning "Submodules haven't been initialized, initializing now" @@ -162,6 +178,26 @@ def checkRunFolder(suggestedfolder) end success "Assets are good to go" + + info "Building luajit" + + Dir.chdir(File.join(CurrentDir, "thrive", "contrib/lua/luajit/src")) do + + # Make sure XCFLAGS+= -DLUAJIT_ENABLE_LUA52COMPAT is uncommented + outdata = File.read("Makefile").gsub(/#XCFLAGS\+= -DLUAJIT_ENABLE_LUA52COMPAT/, + "XCFLAGS+= -DLUAJIT_ENABLE_LUA52COMPAT") + + File.open("Makefile", 'w') do |out| + out << outdata + end + + runCompiler CompileThreads + + onError "Failed to compile luajit" if $?.exitstatus > 0 + + end + + success "luajit is ok" FileUtils.mkdir_p "build" FileUtils.mkdir_p "build/dist" @@ -169,7 +205,7 @@ def checkRunFolder(suggestedfolder) info "Making links" - # It seems that if the link is created when it already exists a llink is created into + # It seems that if the link is created when it already exists a link is created into # the target folder for some reason createLinkIfDoesntExist "assets/cegui_examples", "cegui_examples" createLinkIfDoesntExist "assets/fonts", "fonts" @@ -216,14 +252,6 @@ def checkRunFolder(suggestedfolder) success "Done compiling thrive" -# Create a link from liblua.so to fix undefined symbol: _Z13luaL_newstatev -Dir.chdir(File.join(CurrentDir, "thrive", "build")) do - - FileUtils.ln_sf "contrib/lua/liblua.so", "liblua.so" - -end - - info "run the game with '#{CurrentDir}/thrive/build/Thrive'" success "Done" diff --git a/contrib/lua/CMakeLists.txt b/contrib/lua/CMakeLists.txt deleted file mode 100644 index 5b631bb0618..00000000000 --- a/contrib/lua/CMakeLists.txt +++ /dev/null @@ -1,86 +0,0 @@ -cmake_minimum_required(VERSION 2.8) - -project(lua CXX) - -set(SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/lua/src) - -set(LIB_SOURCES - ${SOURCE_DIR}/lapi.c - ${SOURCE_DIR}/lauxlib.c - ${SOURCE_DIR}/lbaselib.c - ${SOURCE_DIR}/lbitlib.c - ${SOURCE_DIR}/lcode.c - ${SOURCE_DIR}/lcorolib.c - ${SOURCE_DIR}/lctype.c - ${SOURCE_DIR}/ldblib.c - ${SOURCE_DIR}/ldebug.c - ${SOURCE_DIR}/ldo.c - ${SOURCE_DIR}/ldump.c - ${SOURCE_DIR}/lfunc.c - ${SOURCE_DIR}/lgc.c - ${SOURCE_DIR}/linit.c - ${SOURCE_DIR}/liolib.c - ${SOURCE_DIR}/llex.c - ${SOURCE_DIR}/lmathlib.c - ${SOURCE_DIR}/lmem.c - ${SOURCE_DIR}/loadlib.c - ${SOURCE_DIR}/lobject.c - ${SOURCE_DIR}/lopcodes.c - ${SOURCE_DIR}/loslib.c - ${SOURCE_DIR}/lparser.c - ${SOURCE_DIR}/lstate.c - ${SOURCE_DIR}/lstring.c - ${SOURCE_DIR}/lstrlib.c - ${SOURCE_DIR}/ltable.c - ${SOURCE_DIR}/ltablib.c - ${SOURCE_DIR}/ltm.c - ${SOURCE_DIR}/lundump.c - ${SOURCE_DIR}/lvm.c - ${SOURCE_DIR}/lzio.c -) - -set(LIB_HEADERS - ${SOURCE_DIR}/lapi.h - ${SOURCE_DIR}/lauxlib.h - ${SOURCE_DIR}/lcode.h - ${SOURCE_DIR}/lctype.h - ${SOURCE_DIR}/ldebug.h - ${SOURCE_DIR}/ldo.h - ${SOURCE_DIR}/lfunc.h - ${SOURCE_DIR}/lgc.h - ${SOURCE_DIR}/llex.h - ${SOURCE_DIR}/llimits.h - ${SOURCE_DIR}/lmem.h - ${SOURCE_DIR}/lobject.h - ${SOURCE_DIR}/lopcodes.h - ${SOURCE_DIR}/lparser.h - ${SOURCE_DIR}/lstate.h - ${SOURCE_DIR}/lstring.h - ${SOURCE_DIR}/ltable.h - ${SOURCE_DIR}/ltm.h - ${SOURCE_DIR}/luaconf.h - ${SOURCE_DIR}/lualib.h - ${SOURCE_DIR}/lundump.h - ${SOURCE_DIR}/lvm.h - ${SOURCE_DIR}/lzio.h -) - -set_source_files_properties( - ${LIB_SOURCES} - PROPERTIES LANGUAGE CXX -) - -include_directories( - ${SOURCE_DIR} -) - -add_library(lua SHARED - ${LIB_SOURCES} - ${LIB_HEADERS} -) - -install(TARGETS lua - EXPORT lua - RUNTIME DESTINATION bin - LIBRARY DESTINATION bin -) diff --git a/contrib/lua/building.txt b/contrib/lua/building.txt new file mode 100644 index 00000000000..61c7dd79f54 --- /dev/null +++ b/contrib/lua/building.txt @@ -0,0 +1,6 @@ +LuaJIT has a really complex makefile so go into the luajit/src folder +and run make + +Unfortunately there are some lua 5.2 features that need to be +explicitly enabled. So before running make uncomment this line in +`luajit/src/Makefile`: `#XCFLAGS+= -DLUAJIT_ENABLE_LUA52COMPAT` diff --git a/contrib/lua/lua/README b/contrib/lua/lua/README deleted file mode 100644 index 6e2aee6ce3e..00000000000 --- a/contrib/lua/lua/README +++ /dev/null @@ -1,6 +0,0 @@ - -This is Lua 5.2.2, released on 21 Mar 2013. - -For installation instructions, license details, and -further information about Lua, see doc/readme.html. - diff --git a/contrib/lua/lua/doc/contents.html b/contrib/lua/lua/doc/contents.html deleted file mode 100644 index 0ce297da19c..00000000000 --- a/contrib/lua/lua/doc/contents.html +++ /dev/null @@ -1,533 +0,0 @@ - - - -Lua 5.2 Reference Manual - contents - - - - - - - -
-

- -Lua 5.2 Reference Manual -

- -

-The reference manual is the official definition of the Lua language. -For a complete introduction to Lua programming, see the book -Programming in Lua. - -

-start -· -contents -· -index -


- -Copyright © 2011–2013 Lua.org, PUC-Rio. -Freely available under the terms of the -Lua license. - - -

Contents

- - -

Index

- - - - - - - -
-

Lua functions

-

-_G
-_VERSION
- -

-assert
-collectgarbage
-dofile
-error
-getmetatable
-ipairs
-load
-loadfile
-next
-pairs
-pcall
-print
-rawequal
-rawget
-rawlen
-rawset
-require
-select
-setmetatable
-tonumber
-tostring
-type
-xpcall
- -

-bit32.arshift
-bit32.band
-bit32.bnot
-bit32.bor
-bit32.btest
-bit32.bxor
-bit32.extract
-bit32.lrotate
-bit32.lshift
-bit32.replace
-bit32.rrotate
-bit32.rshift
- -

-coroutine.create
-coroutine.resume
-coroutine.running
-coroutine.status
-coroutine.wrap
-coroutine.yield
- -

-debug.debug
-debug.getuservalue
-debug.gethook
-debug.getinfo
-debug.getlocal
-debug.getmetatable
-debug.getregistry
-debug.getupvalue
-debug.setuservalue
-debug.sethook
-debug.setlocal
-debug.setmetatable
-debug.setupvalue
-debug.traceback
-debug.upvalueid
-debug.upvaluejoin
- -

-file:close
-file:flush
-file:lines
-file:read
-file:seek
-file:setvbuf
-file:write
- -

-io.close
-io.flush
-io.input
-io.lines
-io.open
-io.output
-io.popen
-io.read
-io.stderr
-io.stdin
-io.stdout
-io.tmpfile
-io.type
-io.write
- -

-

 

-

-math.abs
-math.acos
-math.asin
-math.atan
-math.atan2
-math.ceil
-math.cos
-math.cosh
-math.deg
-math.exp
-math.floor
-math.fmod
-math.frexp
-math.huge
-math.ldexp
-math.log
-math.max
-math.min
-math.modf
-math.pi
-math.pow
-math.rad
-math.random
-math.randomseed
-math.sin
-math.sinh
-math.sqrt
-math.tan
-math.tanh
- -

-os.clock
-os.date
-os.difftime
-os.execute
-os.exit
-os.getenv
-os.remove
-os.rename
-os.setlocale
-os.time
-os.tmpname
- -

-package.config
-package.cpath
-package.loaded
-package.loadlib
-package.path
-package.preload
-package.searchers
-package.searchpath
- -

-string.byte
-string.char
-string.dump
-string.find
-string.format
-string.gmatch
-string.gsub
-string.len
-string.lower
-string.match
-string.rep
-string.reverse
-string.sub
-string.upper
- -

-table.concat
-table.insert
-table.pack
-table.remove
-table.sort
-table.unpack
- -

-

C API

-

-lua_Alloc
-lua_CFunction
-lua_Debug
-lua_Hook
-lua_Integer
-lua_Number
-lua_Reader
-lua_State
-lua_Unsigned
-lua_Writer
- -

-lua_absindex
-lua_arith
-lua_atpanic
-lua_call
-lua_callk
-lua_checkstack
-lua_close
-lua_compare
-lua_concat
-lua_copy
-lua_createtable
-lua_dump
-lua_error
-lua_gc
-lua_getallocf
-lua_getctx
-lua_getfield
-lua_getglobal
-lua_gethook
-lua_gethookcount
-lua_gethookmask
-lua_getinfo
-lua_getlocal
-lua_getmetatable
-lua_getstack
-lua_gettable
-lua_gettop
-lua_getupvalue
-lua_getuservalue
-lua_insert
-lua_isboolean
-lua_iscfunction
-lua_isfunction
-lua_islightuserdata
-lua_isnil
-lua_isnone
-lua_isnoneornil
-lua_isnumber
-lua_isstring
-lua_istable
-lua_isthread
-lua_isuserdata
-lua_len
-lua_load
-lua_newstate
-lua_newtable
-lua_newthread
-lua_newuserdata
-lua_next
-lua_pcall
-lua_pcallk
-lua_pop
-lua_pushboolean
-lua_pushcclosure
-lua_pushcfunction
-lua_pushfstring
-lua_pushglobaltable
-lua_pushinteger
-lua_pushlightuserdata
-lua_pushliteral
-lua_pushlstring
-lua_pushnil
-lua_pushnumber
-lua_pushstring
-lua_pushthread
-lua_pushunsigned
-lua_pushvalue
-lua_pushvfstring
-lua_rawequal
-lua_rawget
-lua_rawgeti
-lua_rawgetp
-lua_rawlen
-lua_rawset
-lua_rawseti
-lua_rawsetp
-lua_register
-lua_remove
-lua_replace
-lua_resume
-lua_setallocf
-lua_setfield
-lua_setglobal
-lua_sethook
-lua_setlocal
-lua_setmetatable
-lua_settable
-lua_settop
-lua_setupvalue
-lua_setuservalue
-lua_status
-lua_toboolean
-lua_tocfunction
-lua_tointeger
-lua_tointegerx
-lua_tolstring
-lua_tonumber
-lua_tonumberx
-lua_topointer
-lua_tostring
-lua_tothread
-lua_tounsigned
-lua_tounsignedx
-lua_touserdata
-lua_type
-lua_typename
-lua_upvalueid
-lua_upvalueindex
-lua_upvaluejoin
-lua_version
-lua_xmove
-lua_yield
-lua_yieldk
- -

-

auxiliary library

-

-luaL_Buffer
-luaL_Reg
- -

-luaL_addchar
-luaL_addlstring
-luaL_addsize
-luaL_addstring
-luaL_addvalue
-luaL_argcheck
-luaL_argerror
-luaL_buffinit
-luaL_buffinitsize
-luaL_callmeta
-luaL_checkany
-luaL_checkint
-luaL_checkinteger
-luaL_checklong
-luaL_checklstring
-luaL_checknumber
-luaL_checkoption
-luaL_checkstack
-luaL_checkstring
-luaL_checktype
-luaL_checkudata
-luaL_checkunsigned
-luaL_checkversion
-luaL_dofile
-luaL_dostring
-luaL_error
-luaL_execresult
-luaL_fileresult
-luaL_getmetafield
-luaL_getmetatable
-luaL_getsubtable
-luaL_gsub
-luaL_len
-luaL_loadbuffer
-luaL_loadbufferx
-luaL_loadfile
-luaL_loadfilex
-luaL_loadstring
-luaL_newlib
-luaL_newlibtable
-luaL_newmetatable
-luaL_newstate
-luaL_openlibs
-luaL_optint
-luaL_optinteger
-luaL_optlong
-luaL_optlstring
-luaL_optnumber
-luaL_optstring
-luaL_optunsigned
-luaL_prepbuffer
-luaL_prepbuffsize
-luaL_pushresult
-luaL_pushresultsize
-luaL_ref
-luaL_requiref
-luaL_setfuncs
-luaL_setmetatable
-luaL_testudata
-luaL_tolstring
-luaL_traceback
-luaL_typename
-luaL_unref
-luaL_where
- -

- -
- -Last update: -Tue Mar 12 11:22:18 BRT 2013 - - - - - diff --git a/contrib/lua/lua/doc/logo.gif b/contrib/lua/lua/doc/logo.gif deleted file mode 100644 index 2f5e4ac2e74..00000000000 Binary files a/contrib/lua/lua/doc/logo.gif and /dev/null differ diff --git a/contrib/lua/lua/doc/lua.1 b/contrib/lua/lua/doc/lua.1 deleted file mode 100644 index 1dbf04366ce..00000000000 --- a/contrib/lua/lua/doc/lua.1 +++ /dev/null @@ -1,116 +0,0 @@ -.\" $Id: lua.man,v 1.13 2011/11/16 17:16:53 lhf Exp $ -.TH LUA 1 "$Date: 2011/11/16 17:16:53 $" -.SH NAME -lua \- Lua interpreter -.SH SYNOPSIS -.B lua -[ -.I options -] -[ -.I script -[ -.I args -] -] -.SH DESCRIPTION -.B lua -is the standalone Lua interpreter. -It loads and executes Lua programs, -either in textual source form or -in precompiled binary form. -(Precompiled binaries are output by -.BR luac , -the Lua compiler.) -.B lua -can be used as a batch interpreter and also interactively. -.LP -The given -.I options -are handled in order and then -the Lua program in file -.I script -is loaded and executed. -The given -.I args -are available to -.I script -as strings in a global table named -.BR arg . -If no options or arguments are given, -then -.B "\-v \-i" -is assumed when the standard input is a terminal; -otherwise, -.B "\-" -is assumed. -.LP -In interactive mode, -.B lua -prompts the user, -reads lines from the standard input, -and executes them as they are read. -If a line does not contain a complete statement, -then a secondary prompt is displayed and -lines are read until a complete statement is formed or -a syntax error is found. -If a line starts with -.BR '=' , -then -.B lua -evaluates and displays -the values of the expressions in the remainder of the line. -.LP -At the very start, -before even handling the command line, -.B lua -checks the contents of the environment variables -.B LUA_INIT_5_2 -or -.BR LUA_INIT , -in that order. -If the contents is of the form -.RI '@ filename ', -then -.I filename -is executed. -Otherwise, the string is assumed to be a Lua statement and is executed. -.SH OPTIONS -.TP -.BI \-e " stat" -execute statement -.IR stat . -.TP -.B \-i -enter interactive mode after executing -.IR script . -.TP -.BI \-l " name" -execute the equivalent of -.IB name =require(' name ') -before executing -.IR script . -.TP -.B \-v -show version information. -.TP -.B \-E -ignore environment variables. -.TP -.B \-\- -stop handling options. -.TP -.B \- -stop handling options and execute the standard input as a file. -.SH "SEE ALSO" -.BR luac (1) -.br -The documentation at lua.org, -especially section 7 of the reference manual. -.SH DIAGNOSTICS -Error messages should be self explanatory. -.SH AUTHORS -R. Ierusalimschy, -L. H. de Figueiredo, -W. Celes -.\" EOF diff --git a/contrib/lua/lua/doc/lua.css b/contrib/lua/lua/doc/lua.css deleted file mode 100644 index 240e85eb8b0..00000000000 --- a/contrib/lua/lua/doc/lua.css +++ /dev/null @@ -1,83 +0,0 @@ -body { - color: #000000 ; - background-color: #FFFFFF ; - font-family: Helvetica, Arial, sans-serif ; - text-align: justify ; - margin-right: 30px ; - margin-left: 30px ; -} - -h1, h2, h3, h4 { - font-family: Verdana, Geneva, sans-serif ; - font-weight: normal ; - font-style: italic ; -} - -h2 { - padding-top: 0.4em ; - padding-bottom: 0.4em ; - padding-left: 1em ; - padding-right: 1em ; - background-color: #E0E0FF ; - border-radius: 8px ; -} - -h3 { - padding-left: 0.5em ; - border-left: solid #E0E0FF 1em ; -} - -table h3 { - padding-left: 0px ; - border-left: none ; -} - -a:link { - color: #000080 ; - background-color: inherit ; - text-decoration: none ; -} - -a:visited { - background-color: inherit ; - text-decoration: none ; -} - -a:link:hover, a:visited:hover { - color: #000080 ; - background-color: #E0E0FF ; -} - -a:link:active, a:visited:active { - color: #FF0000 ; -} - -hr { - border: 0 ; - height: 1px ; - color: #a0a0a0 ; - background-color: #a0a0a0 ; -} - -:target { - background-color: #F8F8F8 ; - padding: 8px ; - border: solid #a0a0a0 2px ; -} - -.footer { - color: gray ; - font-size: small ; -} - -input[type=text] { - border: solid #a0a0a0 2px ; - border-radius: 2em ; - -moz-border-radius: 2em ; - background-image: url('images/search.png') ; - background-repeat: no-repeat; - background-position: 4px center ; - padding-left: 20px ; - height: 2em ; -} - diff --git a/contrib/lua/lua/doc/luac.1 b/contrib/lua/lua/doc/luac.1 deleted file mode 100644 index 33a4ed00ace..00000000000 --- a/contrib/lua/lua/doc/luac.1 +++ /dev/null @@ -1,118 +0,0 @@ -.\" $Id: luac.man,v 1.29 2011/11/16 13:53:40 lhf Exp $ -.TH LUAC 1 "$Date: 2011/11/16 13:53:40 $" -.SH NAME -luac \- Lua compiler -.SH SYNOPSIS -.B luac -[ -.I options -] [ -.I filenames -] -.SH DESCRIPTION -.B luac -is the Lua compiler. -It translates programs written in the Lua programming language -into binary files containing precompiled chunks -that can be later loaded and executed. -.LP -The main advantages of precompiling chunks are: -faster loading, -protecting source code from accidental user changes, -and -off-line syntax checking. -Precompiling does not imply faster execution -because in Lua chunks are always compiled into bytecodes before being executed. -.B luac -simply allows those bytecodes to be saved in a file for later execution. -Precompiled chunks are not necessarily smaller than the corresponding source. -The main goal in precompiling is faster loading. -.LP -In the command line, -you can mix -text files containing Lua source and -binary files containing precompiled chunks. -.B luac -produces a single output file containing the combined bytecodes -for all files given. -Executing the combined file is equivalent to executing the given files. -By default, -the output file is named -.BR luac.out , -but you can change this with the -.B \-o -option. -.LP -Precompiled chunks are -.I not -portable across different architectures. -Moreover, -the internal format of precompiled chunks -is likely to change when a new version of Lua is released. -Make sure you save the source files of all Lua programs that you precompile. -.LP -.SH OPTIONS -.TP -.B \-l -produce a listing of the compiled bytecode for Lua's virtual machine. -Listing bytecodes is useful to learn about Lua's virtual machine. -If no files are given, then -.B luac -loads -.B luac.out -and lists its contents. -Use -.B \-l \-l -for a full listing. -.TP -.BI \-o " file" -output to -.IR file , -instead of the default -.BR luac.out . -(You can use -.B "'\-'" -for standard output, -but not on platforms that open standard output in text mode.) -The output file may be one of the given files because -all files are loaded before the output file is written. -Be careful not to overwrite precious files. -.TP -.B \-p -load files but do not generate any output file. -Used mainly for syntax checking and for testing precompiled chunks: -corrupted files will probably generate errors when loaded. -If no files are given, then -.B luac -loads -.B luac.out -and tests its contents. -No messages are displayed if the file loads without errors. -.TP -.B \-s -strip debug information before writing the output file. -This saves some space in very large chunks, -but if errors occur when running a stripped chunk, -then the error messages may not contain the full information they usually do. -In particular, -line numbers and names of local variables are lost. -.TP -.B \-v -show version information. -.TP -.B \-\- -stop handling options. -.TP -.B \- -stop handling options and process standard input. -.SH "SEE ALSO" -.BR lua (1) -.br -The documentation at lua.org. -.SH DIAGNOSTICS -Error messages should be self explanatory. -.SH AUTHORS -R. Ierusalimschy, -L. H. de Figueiredo, -W. Celes -.\" EOF diff --git a/contrib/lua/lua/doc/manual.css b/contrib/lua/lua/doc/manual.css deleted file mode 100644 index 269bd4358e6..00000000000 --- a/contrib/lua/lua/doc/manual.css +++ /dev/null @@ -1,26 +0,0 @@ -h3 code { - font-family: inherit ; - font-size: inherit ; -} - -pre, code { - font-size: 12pt ; -} - -span.apii { - float: right ; - font-family: inherit ; - font-style: normal ; - font-size: small ; - color: gray ; -} - -p+h1, ul+h1 { - padding-top: 0.4em ; - padding-bottom: 0.4em ; - padding-left: 24px ; - margin-left: -24px ; - background-color: #E0E0FF ; - border-radius: 8px ; -} - diff --git a/contrib/lua/lua/doc/manual.html b/contrib/lua/lua/doc/manual.html deleted file mode 100644 index 85365363fb3..00000000000 --- a/contrib/lua/lua/doc/manual.html +++ /dev/null @@ -1,10507 +0,0 @@ - - - - -Lua 5.2 Reference Manual - - - - - - - -
-

- -Lua 5.2 Reference Manual -

- -by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes -

- -Copyright © 2011–2013 Lua.org, PUC-Rio. -Freely available under the terms of the -Lua license. - -


-

- -contents -· -index - - -

- - - - - - -

1 – Introduction

- -

-Lua is an extension programming language designed to support -general procedural programming with data description -facilities. -It also offers good support for object-oriented programming, -functional programming, and data-driven programming. -Lua is intended to be used as a powerful, lightweight, -embeddable scripting language for any program that needs one. -Lua is implemented as a library, written in clean C, -the common subset of Standard C and C++. - - -

-Being an extension language, Lua has no notion of a "main" program: -it only works embedded in a host client, -called the embedding program or simply the host. -The host program can invoke functions to execute a piece of Lua code, -can write and read Lua variables, -and can register C functions to be called by Lua code. -Through the use of C functions, Lua can be augmented to cope with -a wide range of different domains, -thus creating customized programming languages sharing a syntactical framework. -The Lua distribution includes a sample host program called lua, -which uses the Lua library to offer a complete, standalone Lua interpreter, -for interactive or batch use. - - -

-Lua is free software, -and is provided as usual with no guarantees, -as stated in its license. -The implementation described in this manual is available -at Lua's official web site, www.lua.org. - - -

-Like any other reference manual, -this document is dry in places. -For a discussion of the decisions behind the design of Lua, -see the technical papers available at Lua's web site. -For a detailed introduction to programming in Lua, -see Roberto's book, Programming in Lua. - - - -

2 – Basic Concepts

- -

-This section describes the basic concepts of the language. - - - -

2.1 – Values and Types

- -

-Lua is a dynamically typed language. -This means that -variables do not have types; only values do. -There are no type definitions in the language. -All values carry their own type. - - -

-All values in Lua are first-class values. -This means that all values can be stored in variables, -passed as arguments to other functions, and returned as results. - - -

-There are eight basic types in Lua: -nil, boolean, number, -string, function, userdata, -thread, and table. -Nil is the type of the value nil, -whose main property is to be different from any other value; -it usually represents the absence of a useful value. -Boolean is the type of the values false and true. -Both nil and false make a condition false; -any other value makes it true. -Number represents real (double-precision floating-point) numbers. -Operations on numbers follow the same rules of -the underlying C implementation, -which, in turn, usually follows the IEEE 754 standard. -(It is easy to build Lua interpreters that use other -internal representations for numbers, -such as single-precision floats or long integers; -see file luaconf.h.) -String represents immutable sequences of bytes. - -Lua is 8-bit clean: -strings can contain any 8-bit value, -including embedded zeros ('\0'). - - -

-Lua can call (and manipulate) functions written in Lua and -functions written in C -(see §3.4.9). - - -

-The type userdata is provided to allow arbitrary C data to -be stored in Lua variables. -A userdata value is a pointer to a block of raw memory. -There are two kinds of userdata: -full userdata, where the block of memory is managed by Lua, -and light userdata, where the block of memory is managed by the host. -Userdata has no predefined operations in Lua, -except assignment and identity test. -By using metatables, -the programmer can define operations for full userdata values -(see §2.4). -Userdata values cannot be created or modified in Lua, -only through the C API. -This guarantees the integrity of data owned by the host program. - - -

-The type thread represents independent threads of execution -and it is used to implement coroutines (see §2.6). -Do not confuse Lua threads with operating-system threads. -Lua supports coroutines on all systems, -even those that do not support threads. - - -

-The type table implements associative arrays, -that is, arrays that can be indexed not only with numbers, -but with any Lua value except nil and NaN -(Not a Number, a special numeric value used to represent -undefined or unrepresentable results, such as 0/0). -Tables can be heterogeneous; -that is, they can contain values of all types (except nil). -Any key with value nil is not considered part of the table. -Conversely, any key that is not part of a table has -an associated value nil. - - -

-Tables are the sole data structuring mechanism in Lua; -they can be used to represent ordinary arrays, sequences, -symbol tables, sets, records, graphs, trees, etc. -To represent records, Lua uses the field name as an index. -The language supports this representation by -providing a.name as syntactic sugar for a["name"]. -There are several convenient ways to create tables in Lua -(see §3.4.8). - - -

-We use the term sequence to denote a table where -the set of all positive numeric keys is equal to {1..n} -for some integer n, -which is called the length of the sequence (see §3.4.6). - - -

-Like indices, -the values of table fields can be of any type. -In particular, -because functions are first-class values, -table fields can contain functions. -Thus tables can also carry methods (see §3.4.10). - - -

-The indexing of tables follows -the definition of raw equality in the language. -The expressions a[i] and a[j] -denote the same table element -if and only if i and j are raw equal -(that is, equal without metamethods). - - -

-Tables, functions, threads, and (full) userdata values are objects: -variables do not actually contain these values, -only references to them. -Assignment, parameter passing, and function returns -always manipulate references to such values; -these operations do not imply any kind of copy. - - -

-The library function type returns a string describing the type -of a given value (see §6.1). - - - - - -

2.2 – Environments and the Global Environment

- -

-As will be discussed in §3.2 and §3.3.3, -any reference to a global name var is syntactically translated -to _ENV.var. -Moreover, every chunk is compiled in the scope of -an external local variable called _ENV (see §3.3.2), -so _ENV itself is never a global name in a chunk. - - -

-Despite the existence of this external _ENV variable and -the translation of global names, -_ENV is a completely regular name. -In particular, -you can define new variables and parameters with that name. -Each reference to a global name uses the _ENV that is -visible at that point in the program, -following the usual visibility rules of Lua (see §3.5). - - -

-Any table used as the value of _ENV is called an environment. - - -

-Lua keeps a distinguished environment called the global environment. -This value is kept at a special index in the C registry (see §4.5). -In Lua, the variable _G is initialized with this same value. - - -

-When Lua compiles a chunk, -it initializes the value of its _ENV upvalue -with the global environment (see load). -Therefore, by default, -global variables in Lua code refer to entries in the global environment. -Moreover, all standard libraries are loaded in the global environment -and several functions there operate on that environment. -You can use load (or loadfile) -to load a chunk with a different environment. -(In C, you have to load the chunk and then change the value -of its first upvalue.) - - -

-If you change the global environment in the registry -(through C code or the debug library), -all chunks loaded after the change will get the new environment. -Previously loaded chunks are not affected, however, -as each has its own reference to the environment in its _ENV variable. -Moreover, the variable _G -(which is stored in the original global environment) -is never updated by Lua. - - - - - -

2.3 – Error Handling

- -

-Because Lua is an embedded extension language, -all Lua actions start from C code in the host program -calling a function from the Lua library (see lua_pcall). -Whenever an error occurs during -the compilation or execution of a Lua chunk, -control returns to the host, -which can take appropriate measures -(such as printing an error message). - - -

-Lua code can explicitly generate an error by calling the -error function. -If you need to catch errors in Lua, -you can use pcall or xpcall -to call a given function in protected mode. - - -

-Whenever there is an error, -an error object (also called an error message) -is propagated with information about the error. -Lua itself only generates errors where the error object is a string, -but programs may generate errors with -any value for the error object. - - -

-When you use xpcall or lua_pcall, -you may give a message handler -to be called in case of errors. -This function is called with the original error message -and returns a new error message. -It is called before the error unwinds the stack, -so that it can gather more information about the error, -for instance by inspecting the stack and creating a stack traceback. -This message handler is still protected by the protected call; -so, an error inside the message handler -will call the message handler again. -If this loop goes on, Lua breaks it and returns an appropriate message. - - - - - -

2.4 – Metatables and Metamethods

- -

-Every value in Lua can have a metatable. -This metatable is an ordinary Lua table -that defines the behavior of the original value -under certain special operations. -You can change several aspects of the behavior -of operations over a value by setting specific fields in its metatable. -For instance, when a non-numeric value is the operand of an addition, -Lua checks for a function in the field "__add" of the value's metatable. -If it finds one, -Lua calls this function to perform the addition. - - -

-The keys in a metatable are derived from the event names; -the corresponding values are called metamethods. -In the previous example, the event is "add" -and the metamethod is the function that performs the addition. - - -

-You can query the metatable of any value -using the getmetatable function. - - -

-You can replace the metatable of tables -using the setmetatable function. -You cannot change the metatable of other types from Lua -(except by using the debug library); -you must use the C API for that. - - -

-Tables and full userdata have individual metatables -(although multiple tables and userdata can share their metatables). -Values of all other types share one single metatable per type; -that is, there is one single metatable for all numbers, -one for all strings, etc. -By default, a value has no metatable, -but the string library sets a metatable for the string type (see §6.4). - - -

-A metatable controls how an object behaves in arithmetic operations, -order comparisons, concatenation, length operation, and indexing. -A metatable also can define a function to be called -when a userdata or a table is garbage collected. -When Lua performs one of these operations over a value, -it checks whether this value has a metatable with the corresponding event. -If so, the value associated with that key (the metamethod) -controls how Lua will perform the operation. - - -

-Metatables control the operations listed next. -Each operation is identified by its corresponding name. -The key for each operation is a string with its name prefixed by -two underscores, '__'; -for instance, the key for operation "add" is the -string "__add". - - -

-The semantics of these operations is better explained by a Lua function -describing how the interpreter executes the operation. -The code shown here in Lua is only illustrative; -the real behavior is hard coded in the interpreter -and it is much more efficient than this simulation. -All functions used in these descriptions -(rawget, tonumber, etc.) -are described in §6.1. -In particular, to retrieve the metamethod of a given object, -we use the expression - -

-     metatable(obj)[event]
-

-This should be read as - -

-     rawget(getmetatable(obj) or {}, event)
-

-This means that the access to a metamethod does not invoke other metamethods, -and access to objects with no metatables does not fail -(it simply results in nil). - - -

-For the unary - and # operators, -the metamethod is called with a dummy second argument. -This extra argument is only to simplify Lua's internals; -it may be removed in future versions and therefore it is not present -in the following code. -(For most uses this extra argument is irrelevant.) - - - -

- - - - -

2.5 – Garbage Collection

- -

-Lua performs automatic memory management. -This means that -you have to worry neither about allocating memory for new objects -nor about freeing it when the objects are no longer needed. -Lua manages memory automatically by running -a garbage collector to collect all dead objects -(that is, objects that are no longer accessible from Lua). -All memory used by Lua is subject to automatic management: -strings, tables, userdata, functions, threads, internal structures, etc. - - -

-Lua implements an incremental mark-and-sweep collector. -It uses two numbers to control its garbage-collection cycles: -the garbage-collector pause and -the garbage-collector step multiplier. -Both use percentage points as units -(e.g., a value of 100 means an internal value of 1). - - -

-The garbage-collector pause -controls how long the collector waits before starting a new cycle. -Larger values make the collector less aggressive. -Values smaller than 100 mean the collector will not wait to -start a new cycle. -A value of 200 means that the collector waits for the total memory in use -to double before starting a new cycle. - - -

-The garbage-collector step multiplier -controls the relative speed of the collector relative to -memory allocation. -Larger values make the collector more aggressive but also increase -the size of each incremental step. -Values smaller than 100 make the collector too slow and -can result in the collector never finishing a cycle. -The default is 200, -which means that the collector runs at "twice" -the speed of memory allocation. - - -

-If you set the step multiplier to a very large number -(larger than 10% of the maximum number of -bytes that the program may use), -the collector behaves like a stop-the-world collector. -If you then set the pause to 200, -the collector behaves as in old Lua versions, -doing a complete collection every time Lua doubles its -memory usage. - - -

-You can change these numbers by calling lua_gc in C -or collectgarbage in Lua. -You can also use these functions to control -the collector directly (e.g., stop and restart it). - - -

-As an experimental feature in Lua 5.2, -you can change the collector's operation mode -from incremental to generational. -A generational collector assumes that most objects die young, -and therefore it traverses only young (recently created) objects. -This behavior can reduce the time used by the collector, -but also increases memory usage (as old dead objects may accumulate). -To mitigate this second problem, -from time to time the generational collector performs a full collection. -Remember that this is an experimental feature; -you are welcome to try it, -but check your gains. - - - -

2.5.1 – Garbage-Collection Metamethods

- -

-You can set garbage-collector metamethods for tables -and, using the C API, -for full userdata (see §2.4). -These metamethods are also called finalizers. -Finalizers allow you to coordinate Lua's garbage collection -with external resource management -(such as closing files, network or database connections, -or freeing your own memory). - - -

-For an object (table or userdata) to be finalized when collected, -you must mark it for finalization. - -You mark an object for finalization when you set its metatable -and the metatable has a field indexed by the string "__gc". -Note that if you set a metatable without a __gc field -and later create that field in the metatable, -the object will not be marked for finalization. -However, after an object is marked, -you can freely change the __gc field of its metatable. - - -

-When a marked object becomes garbage, -it is not collected immediately by the garbage collector. -Instead, Lua puts it in a list. -After the collection, -Lua does the equivalent of the following function -for each object in that list: - -

-     function gc_event (obj)
-       local h = metatable(obj).__gc
-       if type(h) == "function" then
-         h(obj)
-       end
-     end
-
- -

-At the end of each garbage-collection cycle, -the finalizers for objects are called in -the reverse order that they were marked for collection, -among those collected in that cycle; -that is, the first finalizer to be called is the one associated -with the object marked last in the program. -The execution of each finalizer may occur at any point during -the execution of the regular code. - - -

-Because the object being collected must still be used by the finalizer, -it (and other objects accessible only through it) -must be resurrected by Lua. -Usually, this resurrection is transient, -and the object memory is freed in the next garbage-collection cycle. -However, if the finalizer stores the object in some global place -(e.g., a global variable), -then there is a permanent resurrection. -In any case, -the object memory is freed only when it becomes completely inaccessible; -its finalizer will never be called twice. - - -

-When you close a state (see lua_close), -Lua calls the finalizers of all objects marked for finalization, -following the reverse order that they were marked. -If any finalizer marks new objects for collection during that phase, -these new objects will not be finalized. - - - - - -

2.5.2 – Weak Tables

- -

-A weak table is a table whose elements are -weak references. -A weak reference is ignored by the garbage collector. -In other words, -if the only references to an object are weak references, -then the garbage collector will collect that object. - - -

-A weak table can have weak keys, weak values, or both. -A table with weak keys allows the collection of its keys, -but prevents the collection of its values. -A table with both weak keys and weak values allows the collection of -both keys and values. -In any case, if either the key or the value is collected, -the whole pair is removed from the table. -The weakness of a table is controlled by the -__mode field of its metatable. -If the __mode field is a string containing the character 'k', -the keys in the table are weak. -If __mode contains 'v', -the values in the table are weak. - - -

-A table with weak keys and strong values -is also called an ephemeron table. -In an ephemeron table, -a value is considered reachable only if its key is reachable. -In particular, -if the only reference to a key comes through its value, -the pair is removed. - - -

-Any change in the weakness of a table may take effect only -at the next collect cycle. -In particular, if you change the weakness to a stronger mode, -Lua may still collect some items from that table -before the change takes effect. - - -

-Only objects that have an explicit construction -are removed from weak tables. -Values, such as numbers and light C functions, -are not subject to garbage collection, -and therefore are not removed from weak tables -(unless its associated value is collected). -Although strings are subject to garbage collection, -they do not have an explicit construction, -and therefore are not removed from weak tables. - - -

-Resurrected objects -(that is, objects being finalized -and objects accessible only through objects being finalized) -have a special behavior in weak tables. -They are removed from weak values before running their finalizers, -but are removed from weak keys only in the next collection -after running their finalizers, when such objects are actually freed. -This behavior allows the finalizer to access properties -associated with the object through weak tables. - - -

-If a weak table is among the resurrected objects in a collection cycle, -it may not be properly cleared until the next cycle. - - - - - - - -

2.6 – Coroutines

- -

-Lua supports coroutines, -also called collaborative multithreading. -A coroutine in Lua represents an independent thread of execution. -Unlike threads in multithread systems, however, -a coroutine only suspends its execution by explicitly calling -a yield function. - - -

-You create a coroutine by calling coroutine.create. -Its sole argument is a function -that is the main function of the coroutine. -The create function only creates a new coroutine and -returns a handle to it (an object of type thread); -it does not start the coroutine. - - -

-You execute a coroutine by calling coroutine.resume. -When you first call coroutine.resume, -passing as its first argument -a thread returned by coroutine.create, -the coroutine starts its execution, -at the first line of its main function. -Extra arguments passed to coroutine.resume are passed on -to the coroutine main function. -After the coroutine starts running, -it runs until it terminates or yields. - - -

-A coroutine can terminate its execution in two ways: -normally, when its main function returns -(explicitly or implicitly, after the last instruction); -and abnormally, if there is an unprotected error. -In the first case, coroutine.resume returns true, -plus any values returned by the coroutine main function. -In case of errors, coroutine.resume returns false -plus an error message. - - -

-A coroutine yields by calling coroutine.yield. -When a coroutine yields, -the corresponding coroutine.resume returns immediately, -even if the yield happens inside nested function calls -(that is, not in the main function, -but in a function directly or indirectly called by the main function). -In the case of a yield, coroutine.resume also returns true, -plus any values passed to coroutine.yield. -The next time you resume the same coroutine, -it continues its execution from the point where it yielded, -with the call to coroutine.yield returning any extra -arguments passed to coroutine.resume. - - -

-Like coroutine.create, -the coroutine.wrap function also creates a coroutine, -but instead of returning the coroutine itself, -it returns a function that, when called, resumes the coroutine. -Any arguments passed to this function -go as extra arguments to coroutine.resume. -coroutine.wrap returns all the values returned by coroutine.resume, -except the first one (the boolean error code). -Unlike coroutine.resume, -coroutine.wrap does not catch errors; -any error is propagated to the caller. - - -

-As an example of how coroutines work, -consider the following code: - -

-     function foo (a)
-       print("foo", a)
-       return coroutine.yield(2*a)
-     end
-     
-     co = coroutine.create(function (a,b)
-           print("co-body", a, b)
-           local r = foo(a+1)
-           print("co-body", r)
-           local r, s = coroutine.yield(a+b, a-b)
-           print("co-body", r, s)
-           return b, "end"
-     end)
-     
-     print("main", coroutine.resume(co, 1, 10))
-     print("main", coroutine.resume(co, "r"))
-     print("main", coroutine.resume(co, "x", "y"))
-     print("main", coroutine.resume(co, "x", "y"))
-

-When you run it, it produces the following output: - -

-     co-body 1       10
-     foo     2
-     main    true    4
-     co-body r
-     main    true    11      -9
-     co-body x       y
-     main    true    10      end
-     main    false   cannot resume dead coroutine
-
- -

-You can also create and manipulate coroutines through the C API: -see functions lua_newthread, lua_resume, -and lua_yield. - - - - - -

3 – The Language

- -

-This section describes the lexis, the syntax, and the semantics of Lua. -In other words, -this section describes -which tokens are valid, -how they can be combined, -and what their combinations mean. - - -

-Language constructs will be explained using the usual extended BNF notation, -in which -{a} means 0 or more a's, and -[a] means an optional a. -Non-terminals are shown like non-terminal, -keywords are shown like kword, -and other terminal symbols are shown like ‘=’. -The complete syntax of Lua can be found in §9 -at the end of this manual. - - - -

3.1 – Lexical Conventions

- -

-Lua is a free-form language. -It ignores spaces (including new lines) and comments -between lexical elements (tokens), -except as delimiters between names and keywords. - - -

-Names -(also called identifiers) -in Lua can be any string of letters, -digits, and underscores, -not beginning with a digit. -Identifiers are used to name variables, table fields, and labels. - - -

-The following keywords are reserved -and cannot be used as names: - - -

-     and       break     do        else      elseif    end
-     false     for       function  goto      if        in
-     local     nil       not       or        repeat    return
-     then      true      until     while
-
- -

-Lua is a case-sensitive language: -and is a reserved word, but And and AND -are two different, valid names. -As a convention, names starting with an underscore followed by -uppercase letters (such as _VERSION) -are reserved for variables used by Lua. - - -

-The following strings denote other tokens: - -

-     +     -     *     /     %     ^     #
-     ==    ~=    <=    >=    <     >     =
-     (     )     {     }     [     ]     ::
-     ;     :     ,     .     ..    ...
-
- -

-Literal strings -can be delimited by matching single or double quotes, -and can contain the following C-like escape sequences: -'\a' (bell), -'\b' (backspace), -'\f' (form feed), -'\n' (newline), -'\r' (carriage return), -'\t' (horizontal tab), -'\v' (vertical tab), -'\\' (backslash), -'\"' (quotation mark [double quote]), -and '\'' (apostrophe [single quote]). -A backslash followed by a real newline -results in a newline in the string. -The escape sequence '\z' skips the following span -of white-space characters, -including line breaks; -it is particularly useful to break and indent a long literal string -into multiple lines without adding the newlines and spaces -into the string contents. - - -

-A byte in a literal string can also be specified by its numerical value. -This can be done with the escape sequence \xXX, -where XX is a sequence of exactly two hexadecimal digits, -or with the escape sequence \ddd, -where ddd is a sequence of up to three decimal digits. -(Note that if a decimal escape is to be followed by a digit, -it must be expressed using exactly three digits.) -Strings in Lua can contain any 8-bit value, including embedded zeros, -which can be specified as '\0'. - - -

-Literal strings can also be defined using a long format -enclosed by long brackets. -We define an opening long bracket of level n as an opening -square bracket followed by n equal signs followed by another -opening square bracket. -So, an opening long bracket of level 0 is written as [[, -an opening long bracket of level 1 is written as [=[, -and so on. -A closing long bracket is defined similarly; -for instance, a closing long bracket of level 4 is written as ]====]. -A long literal starts with an opening long bracket of any level and -ends at the first closing long bracket of the same level. -It can contain any text except a closing bracket of the proper level. -Literals in this bracketed form can run for several lines, -do not interpret any escape sequences, -and ignore long brackets of any other level. -Any kind of end-of-line sequence -(carriage return, newline, carriage return followed by newline, -or newline followed by carriage return) -is converted to a simple newline. - - -

-Any byte in a literal string not -explicitly affected by the previous rules represents itself. -However, Lua opens files for parsing in text mode, -and the system file functions may have problems with -some control characters. -So, it is safer to represent -non-text data as a quoted literal with -explicit escape sequences for non-text characters. - - -

-For convenience, -when the opening long bracket is immediately followed by a newline, -the newline is not included in the string. -As an example, in a system using ASCII -(in which 'a' is coded as 97, -newline is coded as 10, and '1' is coded as 49), -the five literal strings below denote the same string: - -

-     a = 'alo\n123"'
-     a = "alo\n123\""
-     a = '\97lo\10\04923"'
-     a = [[alo
-     123"]]
-     a = [==[
-     alo
-     123"]==]
-
- -

-A numerical constant can be written with an optional fractional part -and an optional decimal exponent, -marked by a letter 'e' or 'E'. -Lua also accepts hexadecimal constants, -which start with 0x or 0X. -Hexadecimal constants also accept an optional fractional part -plus an optional binary exponent, -marked by a letter 'p' or 'P'. -Examples of valid numerical constants are - -

-     3     3.0     3.1416     314.16e-2     0.31416E1
-     0xff  0x0.1E  0xA23p-4   0X1.921FB54442D18P+1
-
- -

-A comment starts with a double hyphen (--) -anywhere outside a string. -If the text immediately after -- is not an opening long bracket, -the comment is a short comment, -which runs until the end of the line. -Otherwise, it is a long comment, -which runs until the corresponding closing long bracket. -Long comments are frequently used to disable code temporarily. - - - - - -

3.2 – Variables

- -

-Variables are places that store values. -There are three kinds of variables in Lua: -global variables, local variables, and table fields. - - -

-A single name can denote a global variable or a local variable -(or a function's formal parameter, -which is a particular kind of local variable): - -

-	var ::= Name
-

-Name denotes identifiers, as defined in §3.1. - - -

-Any variable name is assumed to be global unless explicitly declared -as a local (see §3.3.7). -Local variables are lexically scoped: -local variables can be freely accessed by functions -defined inside their scope (see §3.5). - - -

-Before the first assignment to a variable, its value is nil. - - -

-Square brackets are used to index a table: - -

-	var ::= prefixexp ‘[’ exp ‘]’
-

-The meaning of accesses to table fields can be changed via metatables. -An access to an indexed variable t[i] is equivalent to -a call gettable_event(t,i). -(See §2.4 for a complete description of the -gettable_event function. -This function is not defined or callable in Lua. -We use it here only for explanatory purposes.) - - -

-The syntax var.Name is just syntactic sugar for -var["Name"]: - -

-	var ::= prefixexp ‘.’ Name
-
- -

-An access to a global variable x -is equivalent to _ENV.x. -Due to the way that chunks are compiled, -_ENV is never a global name (see §2.2). - - - - - -

3.3 – Statements

- -

-Lua supports an almost conventional set of statements, -similar to those in Pascal or C. -This set includes -assignments, control structures, function calls, -and variable declarations. - - - -

3.3.1 – Blocks

- -

-A block is a list of statements, -which are executed sequentially: - -

-	block ::= {stat}
-

-Lua has empty statements -that allow you to separate statements with semicolons, -start a block with a semicolon -or write two semicolons in sequence: - -

-	stat ::= ‘;’
-
- -

-Function calls and assignments -can start with an open parenthesis. -This possibility leads to an ambiguity in Lua's grammar. -Consider the following fragment: - -

-     a = b + c
-     (print or io.write)('done')
-

-The grammar could see it in two ways: - -

-     a = b + c(print or io.write)('done')
-     
-     a = b + c; (print or io.write)('done')
-

-The current parser always sees such constructions -in the first way, -interpreting the open parenthesis -as the start of the arguments to a call. -To avoid this ambiguity, -it is a good practice to always precede with a semicolon -statements that start with a parenthesis: - -

-     ;(print or io.write)('done')
-
- -

-A block can be explicitly delimited to produce a single statement: - -

-	stat ::= do block end
-

-Explicit blocks are useful -to control the scope of variable declarations. -Explicit blocks are also sometimes used to -add a return statement in the middle -of another block (see §3.3.4). - - - - - -

3.3.2 – Chunks

- -

-The unit of compilation of Lua is called a chunk. -Syntactically, -a chunk is simply a block: - -

-	chunk ::= block
-
- -

-Lua handles a chunk as the body of an anonymous function -with a variable number of arguments -(see §3.4.10). -As such, chunks can define local variables, -receive arguments, and return values. -Moreover, such anonymous function is compiled as in the -scope of an external local variable called _ENV (see §2.2). -The resulting function always has _ENV as its only upvalue, -even if it does not use that variable. - - -

-A chunk can be stored in a file or in a string inside the host program. -To execute a chunk, -Lua first precompiles the chunk into instructions for a virtual machine, -and then it executes the compiled code -with an interpreter for the virtual machine. - - -

-Chunks can also be precompiled into binary form; -see program luac for details. -Programs in source and compiled forms are interchangeable; -Lua automatically detects the file type and acts accordingly. - - - - - - -

3.3.3 – Assignment

- -

-Lua allows multiple assignments. -Therefore, the syntax for assignment -defines a list of variables on the left side -and a list of expressions on the right side. -The elements in both lists are separated by commas: - -

-	stat ::= varlist ‘=’ explist
-	varlist ::= var {‘,’ var}
-	explist ::= exp {‘,’ exp}
-

-Expressions are discussed in §3.4. - - -

-Before the assignment, -the list of values is adjusted to the length of -the list of variables. -If there are more values than needed, -the excess values are thrown away. -If there are fewer values than needed, -the list is extended with as many nil's as needed. -If the list of expressions ends with a function call, -then all values returned by that call enter the list of values, -before the adjustment -(except when the call is enclosed in parentheses; see §3.4). - - -

-The assignment statement first evaluates all its expressions -and only then are the assignments performed. -Thus the code - -

-     i = 3
-     i, a[i] = i+1, 20
-

-sets a[3] to 20, without affecting a[4] -because the i in a[i] is evaluated (to 3) -before it is assigned 4. -Similarly, the line - -

-     x, y = y, x
-

-exchanges the values of x and y, -and - -

-     x, y, z = y, z, x
-

-cyclically permutes the values of x, y, and z. - - -

-The meaning of assignments to global variables -and table fields can be changed via metatables. -An assignment to an indexed variable t[i] = val is equivalent to -settable_event(t,i,val). -(See §2.4 for a complete description of the -settable_event function. -This function is not defined or callable in Lua. -We use it here only for explanatory purposes.) - - -

-An assignment to a global variable x = val -is equivalent to the assignment -_ENV.x = val (see §2.2). - - - - - -

3.3.4 – Control Structures

-The control structures -if, while, and repeat have the usual meaning and -familiar syntax: - - - - -

-	stat ::= while exp do block end
-	stat ::= repeat block until exp
-	stat ::= if exp then block {elseif exp then block} [else block] end
-

-Lua also has a for statement, in two flavors (see §3.3.5). - - -

-The condition expression of a -control structure can return any value. -Both false and nil are considered false. -All values different from nil and false are considered true -(in particular, the number 0 and the empty string are also true). - - -

-In the repeatuntil loop, -the inner block does not end at the until keyword, -but only after the condition. -So, the condition can refer to local variables -declared inside the loop block. - - -

-The goto statement transfers the program control to a label. -For syntactical reasons, -labels in Lua are considered statements too: - - - -

-	stat ::= goto Name
-	stat ::= label
-	label ::= ‘::’ Name ‘::’
-
- -

-A label is visible in the entire block where it is defined, -except -inside nested blocks where a label with the same name is defined and -inside nested functions. -A goto may jump to any visible label as long as it does not -enter into the scope of a local variable. - - -

-Labels and empty statements are called void statements, -as they perform no actions. - - -

-The break statement terminates the execution of a -while, repeat, or for loop, -skipping to the next statement after the loop: - - -

-	stat ::= break
-

-A break ends the innermost enclosing loop. - - -

-The return statement is used to return values -from a function or a chunk (which is a function in disguise). - -Functions can return more than one value, -so the syntax for the return statement is - -

-	stat ::= return [explist] [‘;’]
-
- -

-The return statement can only be written -as the last statement of a block. -If it is really necessary to return in the middle of a block, -then an explicit inner block can be used, -as in the idiom do return end, -because now return is the last statement in its (inner) block. - - - - - -

3.3.5 – For Statement

- -

- -The for statement has two forms: -one numeric and one generic. - - -

-The numeric for loop repeats a block of code while a -control variable runs through an arithmetic progression. -It has the following syntax: - -

-	stat ::= for Name ‘=’ exp ‘,’ exp [‘,’ exp] do block end
-

-The block is repeated for name starting at the value of -the first exp, until it passes the second exp by steps of the -third exp. -More precisely, a for statement like - -

-     for v = e1, e2, e3 do block end
-

-is equivalent to the code: - -

-     do
-       local var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3)
-       if not (var and limit and step) then error() end
-       while (step > 0 and var <= limit) or (step <= 0 and var >= limit) do
-         local v = var
-         block
-         var = var + step
-       end
-     end
-

-Note the following: - -

- -

-The generic for statement works over functions, -called iterators. -On each iteration, the iterator function is called to produce a new value, -stopping when this new value is nil. -The generic for loop has the following syntax: - -

-	stat ::= for namelist in explist do block end
-	namelist ::= Name {‘,’ Name}
-

-A for statement like - -

-     for var_1, ···, var_n in explist do block end
-

-is equivalent to the code: - -

-     do
-       local f, s, var = explist
-       while true do
-         local var_1, ···, var_n = f(s, var)
-         if var_1 == nil then break end
-         var = var_1
-         block
-       end
-     end
-

-Note the following: - -

- - - - -

3.3.6 – Function Calls as Statements

-To allow possible side-effects, -function calls can be executed as statements: - -

-	stat ::= functioncall
-

-In this case, all returned values are thrown away. -Function calls are explained in §3.4.9. - - - - - -

3.3.7 – Local Declarations

-Local variables can be declared anywhere inside a block. -The declaration can include an initial assignment: - -

-	stat ::= local namelist [‘=’ explist]
-

-If present, an initial assignment has the same semantics -of a multiple assignment (see §3.3.3). -Otherwise, all variables are initialized with nil. - - -

-A chunk is also a block (see §3.3.2), -and so local variables can be declared in a chunk outside any explicit block. - - -

-The visibility rules for local variables are explained in §3.5. - - - - - - - -

3.4 – Expressions

- -

-The basic expressions in Lua are the following: - -

-	exp ::= prefixexp
-	exp ::= nil | false | true
-	exp ::= Number
-	exp ::= String
-	exp ::= functiondef
-	exp ::= tableconstructor
-	exp ::= ‘...’
-	exp ::= exp binop exp
-	exp ::= unop exp
-	prefixexp ::= var | functioncall | ‘(’ exp ‘)’
-
- -

-Numbers and literal strings are explained in §3.1; -variables are explained in §3.2; -function definitions are explained in §3.4.10; -function calls are explained in §3.4.9; -table constructors are explained in §3.4.8. -Vararg expressions, -denoted by three dots ('...'), can only be used when -directly inside a vararg function; -they are explained in §3.4.10. - - -

-Binary operators comprise arithmetic operators (see §3.4.1), -relational operators (see §3.4.3), logical operators (see §3.4.4), -and the concatenation operator (see §3.4.5). -Unary operators comprise the unary minus (see §3.4.1), -the unary not (see §3.4.4), -and the unary length operator (see §3.4.6). - - -

-Both function calls and vararg expressions can result in multiple values. -If a function call is used as a statement (see §3.3.6), -then its return list is adjusted to zero elements, -thus discarding all returned values. -If an expression is used as the last (or the only) element -of a list of expressions, -then no adjustment is made -(unless the expression is enclosed in parentheses). -In all other contexts, -Lua adjusts the result list to one element, -either discarding all values except the first one -or adding a single nil if there are no values. - - -

-Here are some examples: - -

-     f()                -- adjusted to 0 results
-     g(f(), x)          -- f() is adjusted to 1 result
-     g(x, f())          -- g gets x plus all results from f()
-     a,b,c = f(), x     -- f() is adjusted to 1 result (c gets nil)
-     a,b = ...          -- a gets the first vararg parameter, b gets
-                        -- the second (both a and b can get nil if there
-                        -- is no corresponding vararg parameter)
-     
-     a,b,c = x, f()     -- f() is adjusted to 2 results
-     a,b,c = f()        -- f() is adjusted to 3 results
-     return f()         -- returns all results from f()
-     return ...         -- returns all received vararg parameters
-     return x,y,f()     -- returns x, y, and all results from f()
-     {f()}              -- creates a list with all results from f()
-     {...}              -- creates a list with all vararg parameters
-     {f(), nil}         -- f() is adjusted to 1 result
-
- -

-Any expression enclosed in parentheses always results in only one value. -Thus, -(f(x,y,z)) is always a single value, -even if f returns several values. -(The value of (f(x,y,z)) is the first value returned by f -or nil if f does not return any values.) - - - -

3.4.1 – Arithmetic Operators

-Lua supports the usual arithmetic operators: -the binary + (addition), -- (subtraction), * (multiplication), -/ (division), % (modulo), and ^ (exponentiation); -and unary - (mathematical negation). -If the operands are numbers, or strings that can be converted to -numbers (see §3.4.2), -then all operations have the usual meaning. -Exponentiation works for any exponent. -For instance, x^(-0.5) computes the inverse of the square root of x. -Modulo is defined as - -

-     a % b == a - math.floor(a/b)*b
-

-That is, it is the remainder of a division that rounds -the quotient towards minus infinity. - - - - - -

3.4.2 – Coercion

- -

-Lua provides automatic conversion between -string and number values at run time. -Any arithmetic operation applied to a string tries to convert -this string to a number, following the rules of the Lua lexer. -(The string may have leading and trailing spaces and a sign.) -Conversely, whenever a number is used where a string is expected, -the number is converted to a string, in a reasonable format. -For complete control over how numbers are converted to strings, -use the format function from the string library -(see string.format). - - - - - -

3.4.3 – Relational Operators

-The relational operators in Lua are - -

-     ==    ~=    <     >     <=    >=
-

-These operators always result in false or true. - - -

-Equality (==) first compares the type of its operands. -If the types are different, then the result is false. -Otherwise, the values of the operands are compared. -Numbers and strings are compared in the usual way. -Tables, userdata, and threads -are compared by reference: -two objects are considered equal only if they are the same object. -Every time you create a new object -(a table, userdata, or thread), -this new object is different from any previously existing object. -Closures with the same reference are always equal. -Closures with any detectable difference -(different behavior, different definition) are always different. - - -

-You can change the way that Lua compares tables and userdata -by using the "eq" metamethod (see §2.4). - - -

-The conversion rules of §3.4.2 -do not apply to equality comparisons. -Thus, "0"==0 evaluates to false, -and t[0] and t["0"] denote different -entries in a table. - - -

-The operator ~= is exactly the negation of equality (==). - - -

-The order operators work as follows. -If both arguments are numbers, then they are compared as such. -Otherwise, if both arguments are strings, -then their values are compared according to the current locale. -Otherwise, Lua tries to call the "lt" or the "le" -metamethod (see §2.4). -A comparison a > b is translated to b < a -and a >= b is translated to b <= a. - - - - - -

3.4.4 – Logical Operators

-The logical operators in Lua are -and, or, and not. -Like the control structures (see §3.3.4), -all logical operators consider both false and nil as false -and anything else as true. - - -

-The negation operator not always returns false or true. -The conjunction operator and returns its first argument -if this value is false or nil; -otherwise, and returns its second argument. -The disjunction operator or returns its first argument -if this value is different from nil and false; -otherwise, or returns its second argument. -Both and and or use short-cut evaluation; -that is, -the second operand is evaluated only if necessary. -Here are some examples: - -

-     10 or 20            --> 10
-     10 or error()       --> 10
-     nil or "a"          --> "a"
-     nil and 10          --> nil
-     false and error()   --> false
-     false and nil       --> false
-     false or nil        --> nil
-     10 and 20           --> 20
-

-(In this manual, ---> indicates the result of the preceding expression.) - - - - - -

3.4.5 – Concatenation

-The string concatenation operator in Lua is -denoted by two dots ('..'). -If both operands are strings or numbers, then they are converted to -strings according to the rules mentioned in §3.4.2. -Otherwise, the __concat metamethod is called (see §2.4). - - - - - -

3.4.6 – The Length Operator

- -

-The length operator is denoted by the unary prefix operator #. -The length of a string is its number of bytes -(that is, the usual meaning of string length when each -character is one byte). - - -

-A program can modify the behavior of the length operator for -any value but strings through the __len metamethod (see §2.4). - - -

-Unless a __len metamethod is given, -the length of a table t is only defined if the -table is a sequence, -that is, -the set of its positive numeric keys is equal to {1..n} -for some integer n. -In that case, n is its length. -Note that a table like - -

-     {10, 20, nil, 40}
-

-is not a sequence, because it has the key 4 -but does not have the key 3. -(So, there is no n such that the set {1..n} is equal -to the set of positive numeric keys of that table.) -Note, however, that non-numeric keys do not interfere -with whether a table is a sequence. - - - - - -

3.4.7 – Precedence

-Operator precedence in Lua follows the table below, -from lower to higher priority: - -

-     or
-     and
-     <     >     <=    >=    ~=    ==
-     ..
-     +     -
-     *     /     %
-     not   #     - (unary)
-     ^
-

-As usual, -you can use parentheses to change the precedences of an expression. -The concatenation ('..') and exponentiation ('^') -operators are right associative. -All other binary operators are left associative. - - - - - -

3.4.8 – Table Constructors

-Table constructors are expressions that create tables. -Every time a constructor is evaluated, a new table is created. -A constructor can be used to create an empty table -or to create a table and initialize some of its fields. -The general syntax for constructors is - -

-	tableconstructor ::= ‘{’ [fieldlist] ‘}’
-	fieldlist ::= field {fieldsep field} [fieldsep]
-	field ::= ‘[’ exp ‘]’ ‘=’ exp | Name ‘=’ exp | exp
-	fieldsep ::= ‘,’ | ‘;’
-
- -

-Each field of the form [exp1] = exp2 adds to the new table an entry -with key exp1 and value exp2. -A field of the form name = exp is equivalent to -["name"] = exp. -Finally, fields of the form exp are equivalent to -[i] = exp, where i are consecutive numerical integers, -starting with 1. -Fields in the other formats do not affect this counting. -For example, - -

-     a = { [f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45 }
-

-is equivalent to - -

-     do
-       local t = {}
-       t[f(1)] = g
-       t[1] = "x"         -- 1st exp
-       t[2] = "y"         -- 2nd exp
-       t.x = 1            -- t["x"] = 1
-       t[3] = f(x)        -- 3rd exp
-       t[30] = 23
-       t[4] = 45          -- 4th exp
-       a = t
-     end
-
- -

-If the last field in the list has the form exp -and the expression is a function call or a vararg expression, -then all values returned by this expression enter the list consecutively -(see §3.4.9). - - -

-The field list can have an optional trailing separator, -as a convenience for machine-generated code. - - - - - -

3.4.9 – Function Calls

-A function call in Lua has the following syntax: - -

-	functioncall ::= prefixexp args
-

-In a function call, -first prefixexp and args are evaluated. -If the value of prefixexp has type function, -then this function is called -with the given arguments. -Otherwise, the prefixexp "call" metamethod is called, -having as first parameter the value of prefixexp, -followed by the original call arguments -(see §2.4). - - -

-The form - -

-	functioncall ::= prefixexp ‘:’ Name args
-

-can be used to call "methods". -A call v:name(args) -is syntactic sugar for v.name(v,args), -except that v is evaluated only once. - - -

-Arguments have the following syntax: - -

-	args ::= ‘(’ [explist] ‘)’
-	args ::= tableconstructor
-	args ::= String
-

-All argument expressions are evaluated before the call. -A call of the form f{fields} is -syntactic sugar for f({fields}); -that is, the argument list is a single new table. -A call of the form f'string' -(or f"string" or f[[string]]) -is syntactic sugar for f('string'); -that is, the argument list is a single literal string. - - -

-A call of the form return functioncall is called -a tail call. -Lua implements proper tail calls -(or proper tail recursion): -in a tail call, -the called function reuses the stack entry of the calling function. -Therefore, there is no limit on the number of nested tail calls that -a program can execute. -However, a tail call erases any debug information about the -calling function. -Note that a tail call only happens with a particular syntax, -where the return has one single function call as argument; -this syntax makes the calling function return exactly -the returns of the called function. -So, none of the following examples are tail calls: - -

-     return (f(x))        -- results adjusted to 1
-     return 2 * f(x)
-     return x, f(x)       -- additional results
-     f(x); return         -- results discarded
-     return x or f(x)     -- results adjusted to 1
-
- - - - -

3.4.10 – Function Definitions

- -

-The syntax for function definition is - -

-	functiondef ::= function funcbody
-	funcbody ::= ‘(’ [parlist] ‘)’ block end
-
- -

-The following syntactic sugar simplifies function definitions: - -

-	stat ::= function funcname funcbody
-	stat ::= local function Name funcbody
-	funcname ::= Name {‘.’ Name} [‘:’ Name]
-

-The statement - -

-     function f () body end
-

-translates to - -

-     f = function () body end
-

-The statement - -

-     function t.a.b.c.f () body end
-

-translates to - -

-     t.a.b.c.f = function () body end
-

-The statement - -

-     local function f () body end
-

-translates to - -

-     local f; f = function () body end
-

-not to - -

-     local f = function () body end
-

-(This only makes a difference when the body of the function -contains references to f.) - - -

-A function definition is an executable expression, -whose value has type function. -When Lua precompiles a chunk, -all its function bodies are precompiled too. -Then, whenever Lua executes the function definition, -the function is instantiated (or closed). -This function instance (or closure) -is the final value of the expression. - - -

-Parameters act as local variables that are -initialized with the argument values: - -

-	parlist ::= namelist [‘,’ ‘...’] | ‘...’
-

-When a function is called, -the list of arguments is adjusted to -the length of the list of parameters, -unless the function is a vararg function, -which is indicated by three dots ('...') -at the end of its parameter list. -A vararg function does not adjust its argument list; -instead, it collects all extra arguments and supplies them -to the function through a vararg expression, -which is also written as three dots. -The value of this expression is a list of all actual extra arguments, -similar to a function with multiple results. -If a vararg expression is used inside another expression -or in the middle of a list of expressions, -then its return list is adjusted to one element. -If the expression is used as the last element of a list of expressions, -then no adjustment is made -(unless that last expression is enclosed in parentheses). - - -

-As an example, consider the following definitions: - -

-     function f(a, b) end
-     function g(a, b, ...) end
-     function r() return 1,2,3 end
-

-Then, we have the following mapping from arguments to parameters and -to the vararg expression: - -

-     CALL            PARAMETERS
-     
-     f(3)             a=3, b=nil
-     f(3, 4)          a=3, b=4
-     f(3, 4, 5)       a=3, b=4
-     f(r(), 10)       a=1, b=10
-     f(r())           a=1, b=2
-     
-     g(3)             a=3, b=nil, ... -->  (nothing)
-     g(3, 4)          a=3, b=4,   ... -->  (nothing)
-     g(3, 4, 5, 8)    a=3, b=4,   ... -->  5  8
-     g(5, r())        a=5, b=1,   ... -->  2  3
-
- -

-Results are returned using the return statement (see §3.3.4). -If control reaches the end of a function -without encountering a return statement, -then the function returns with no results. - - -

- -There is a system-dependent limit on the number of values -that a function may return. -This limit is guaranteed to be larger than 1000. - - -

-The colon syntax -is used for defining methods, -that is, functions that have an implicit extra parameter self. -Thus, the statement - -

-     function t.a.b.c:f (params) body end
-

-is syntactic sugar for - -

-     t.a.b.c.f = function (self, params) body end
-
- - - - - - -

3.5 – Visibility Rules

- -

- -Lua is a lexically scoped language. -The scope of a local variable begins at the first statement after -its declaration and lasts until the last non-void statement -of the innermost block that includes the declaration. -Consider the following example: - -

-     x = 10                -- global variable
-     do                    -- new block
-       local x = x         -- new 'x', with value 10
-       print(x)            --> 10
-       x = x+1
-       do                  -- another block
-         local x = x+1     -- another 'x'
-         print(x)          --> 12
-       end
-       print(x)            --> 11
-     end
-     print(x)              --> 10  (the global one)
-
- -

-Notice that, in a declaration like local x = x, -the new x being declared is not in scope yet, -and so the second x refers to the outside variable. - - -

-Because of the lexical scoping rules, -local variables can be freely accessed by functions -defined inside their scope. -A local variable used by an inner function is called -an upvalue, or external local variable, -inside the inner function. - - -

-Notice that each execution of a local statement -defines new local variables. -Consider the following example: - -

-     a = {}
-     local x = 20
-     for i=1,10 do
-       local y = 0
-       a[i] = function () y=y+1; return x+y end
-     end
-

-The loop creates ten closures -(that is, ten instances of the anonymous function). -Each of these closures uses a different y variable, -while all of them share the same x. - - - - - -

4 – The Application Program Interface

- -

- -This section describes the C API for Lua, that is, -the set of C functions available to the host program to communicate -with Lua. -All API functions and related types and constants -are declared in the header file lua.h. - - -

-Even when we use the term "function", -any facility in the API may be provided as a macro instead. -Except where stated otherwise, -all such macros use each of their arguments exactly once -(except for the first argument, which is always a Lua state), -and so do not generate any hidden side-effects. - - -

-As in most C libraries, -the Lua API functions do not check their arguments for validity or consistency. -However, you can change this behavior by compiling Lua -with the macro LUA_USE_APICHECK defined. - - - -

4.1 – The Stack

- -

-Lua uses a virtual stack to pass values to and from C. -Each element in this stack represents a Lua value -(nil, number, string, etc.). - - -

-Whenever Lua calls C, the called function gets a new stack, -which is independent of previous stacks and of stacks of -C functions that are still active. -This stack initially contains any arguments to the C function -and it is where the C function pushes its results -to be returned to the caller (see lua_CFunction). - - -

-For convenience, -most query operations in the API do not follow a strict stack discipline. -Instead, they can refer to any element in the stack -by using an index: -A positive index represents an absolute stack position -(starting at 1); -a negative index represents an offset relative to the top of the stack. -More specifically, if the stack has n elements, -then index 1 represents the first element -(that is, the element that was pushed onto the stack first) -and -index n represents the last element; -index -1 also represents the last element -(that is, the element at the top) -and index -n represents the first element. - - - - - -

4.2 – Stack Size

- -

-When you interact with the Lua API, -you are responsible for ensuring consistency. -In particular, -you are responsible for controlling stack overflow. -You can use the function lua_checkstack -to ensure that the stack has extra slots when pushing new elements. - - -

-Whenever Lua calls C, -it ensures that the stack has at least LUA_MINSTACK extra slots. -LUA_MINSTACK is defined as 20, -so that usually you do not have to worry about stack space -unless your code has loops pushing elements onto the stack. - - -

-When you call a Lua function -without a fixed number of results (see lua_call), -Lua ensures that the stack has enough size for all results, -but it does not ensure any extra space. -So, before pushing anything in the stack after such a call -you should use lua_checkstack. - - - - - -

4.3 – Valid and Acceptable Indices

- -

-Any function in the API that receives stack indices -works only with valid indices or acceptable indices. - - -

-A valid index is an index that refers to a -real position within the stack, that is, -its position lies between 1 and the stack top -(1 ≤ abs(index) ≤ top). - -Usually, functions that can modify the value at an index -require valid indices. - - -

-Unless otherwise noted, -any function that accepts valid indices also accepts pseudo-indices, -which represent some Lua values that are accessible to C code -but which are not in the stack. -Pseudo-indices are used to access the registry -and the upvalues of a C function (see §4.4). - - -

-Functions that do not need a specific stack position, -but only a value in the stack (e.g., query functions), -can be called with acceptable indices. -An acceptable index can be any valid index, -including the pseudo-indices, -but it also can be any positive index after the stack top -within the space allocated for the stack, -that is, indices up to the stack size. -(Note that 0 is never an acceptable index.) -Except when noted otherwise, -functions in the API work with acceptable indices. - - -

-Acceptable indices serve to avoid extra tests -against the stack top when querying the stack. -For instance, a C function can query its third argument -without the need to first check whether there is a third argument, -that is, without the need to check whether 3 is a valid index. - - -

-For functions that can be called with acceptable indices, -any non-valid index is treated as if it -contains a value of a virtual type LUA_TNONE, -which behaves like a nil value. - - - - - -

4.4 – C Closures

- -

-When a C function is created, -it is possible to associate some values with it, -thus creating a C closure -(see lua_pushcclosure); -these values are called upvalues and are -accessible to the function whenever it is called. - - -

-Whenever a C function is called, -its upvalues are located at specific pseudo-indices. -These pseudo-indices are produced by the macro -lua_upvalueindex. -The first value associated with a function is at position -lua_upvalueindex(1), and so on. -Any access to lua_upvalueindex(n), -where n is greater than the number of upvalues of the -current function (but not greater than 256), -produces an acceptable but invalid index. - - - - - -

4.5 – Registry

- -

-Lua provides a registry, -a predefined table that can be used by any C code to -store whatever Lua values it needs to store. -The registry table is always located at pseudo-index -LUA_REGISTRYINDEX, -which is a valid index. -Any C library can store data into this table, -but it should take care to choose keys -that are different from those used -by other libraries, to avoid collisions. -Typically, you should use as key a string containing your library name, -or a light userdata with the address of a C object in your code, -or any Lua object created by your code. -As with global names, -string keys starting with an underscore followed by -uppercase letters are reserved for Lua. - - -

-The integer keys in the registry are used by the reference mechanism, -implemented by the auxiliary library, -and by some predefined values. -Therefore, integer keys should not be used for other purposes. - - -

-When you create a new Lua state, -its registry comes with some predefined values. -These predefined values are indexed with integer keys -defined as constants in lua.h. -The following constants are defined: - -

- - - - -

4.6 – Error Handling in C

- -

-Internally, Lua uses the C longjmp facility to handle errors. -(You can also choose to use exceptions if you compile Lua as C++; -search for LUAI_THROW in the source code.) -When Lua faces any error -(such as a memory allocation error, type errors, syntax errors, -and runtime errors) -it raises an error; -that is, it does a long jump. -A protected environment uses setjmp -to set a recovery point; -any error jumps to the most recent active recovery point. - - -

-If an error happens outside any protected environment, -Lua calls a panic function (see lua_atpanic) -and then calls abort, -thus exiting the host application. -Your panic function can avoid this exit by -never returning -(e.g., doing a long jump to your own recovery point outside Lua). - - -

-The panic function runs as if it were a message handler (see §2.3); -in particular, the error message is at the top of the stack. -However, there is no guarantees about stack space. -To push anything on the stack, -the panic function should first check the available space (see §4.2). - - -

-Most functions in the API can throw an error, -for instance due to a memory allocation error. -The documentation for each function indicates whether -it can throw errors. - - -

-Inside a C function you can throw an error by calling lua_error. - - - - - -

4.7 – Handling Yields in C

- -

-Internally, Lua uses the C longjmp facility to yield a coroutine. -Therefore, if a function foo calls an API function -and this API function yields -(directly or indirectly by calling another function that yields), -Lua cannot return to foo any more, -because the longjmp removes its frame from the C stack. - - -

-To avoid this kind of problem, -Lua raises an error whenever it tries to yield across an API call, -except for three functions: -lua_yieldk, lua_callk, and lua_pcallk. -All those functions receive a continuation function -(as a parameter called k) to continue execution after a yield. - - -

-We need to set some terminology to explain continuations. -We have a C function called from Lua which we will call -the original function. -This original function then calls one of those three functions in the C API, -which we will call the callee function, -that then yields the current thread. -(This can happen when the callee function is lua_yieldk, -or when the callee function is either lua_callk or lua_pcallk -and the function called by them yields.) - - -

-Suppose the running thread yields while executing the callee function. -After the thread resumes, -it eventually will finish running the callee function. -However, -the callee function cannot return to the original function, -because its frame in the C stack was destroyed by the yield. -Instead, Lua calls a continuation function, -which was given as an argument to the callee function. -As the name implies, -the continuation function should continue the task -of the original function. - - -

-Lua treats the continuation function as if it were the original function. -The continuation function receives the same Lua stack -from the original function, -in the same state it would be if the callee function had returned. -(For instance, -after a lua_callk the function and its arguments are -removed from the stack and replaced by the results from the call.) -It also has the same upvalues. -Whatever it returns is handled by Lua as if it were the return -of the original function. - - -

-The only difference in the Lua state between the original function -and its continuation is the result of a call to lua_getctx. - - - - - -

4.8 – Functions and Types

- -

-Here we list all functions and types from the C API in -alphabetical order. -Each function has an indicator like this: -[-o, +p, x] - - -

-The first field, o, -is how many elements the function pops from the stack. -The second field, p, -is how many elements the function pushes onto the stack. -(Any function always pushes its results after popping its arguments.) -A field in the form x|y means the function can push (or pop) -x or y elements, -depending on the situation; -an interrogation mark '?' means that -we cannot know how many elements the function pops/pushes -by looking only at its arguments -(e.g., they may depend on what is on the stack). -The third field, x, -tells whether the function may throw errors: -'-' means the function never throws any error; -'e' means the function may throw errors; -'v' means the function may throw an error on purpose. - - - -


lua_absindex

-[-0, +0, –] -

int lua_absindex (lua_State *L, int idx);
- -

-Converts the acceptable index idx into an absolute index -(that is, one that does not depend on the stack top). - - - - - -


lua_Alloc

-
typedef void * (*lua_Alloc) (void *ud,
-                             void *ptr,
-                             size_t osize,
-                             size_t nsize);
- -

-The type of the memory-allocation function used by Lua states. -The allocator function must provide a -functionality similar to realloc, -but not exactly the same. -Its arguments are -ud, an opaque pointer passed to lua_newstate; -ptr, a pointer to the block being allocated/reallocated/freed; -osize, the original size of the block or some code about what -is being allocated; -nsize, the new size of the block. - - -

-When ptr is not NULL, -osize is the size of the block pointed by ptr, -that is, the size given when it was allocated or reallocated. - - -

-When ptr is NULL, -osize encodes the kind of object that Lua is allocating. -osize is any of -LUA_TSTRING, LUA_TTABLE, LUA_TFUNCTION, -LUA_TUSERDATA, or LUA_TTHREAD when (and only when) -Lua is creating a new object of that type. -When osize is some other value, -Lua is allocating memory for something else. - - -

-Lua assumes the following behavior from the allocator function: - - -

-When nsize is zero, -the allocator should behave like free -and return NULL. - - -

-When nsize is not zero, -the allocator should behave like realloc. -The allocator returns NULL -if and only if it cannot fulfill the request. -Lua assumes that the allocator never fails when -osize >= nsize. - - -

-Here is a simple implementation for the allocator function. -It is used in the auxiliary library by luaL_newstate. - -

-     static void *l_alloc (void *ud, void *ptr, size_t osize,
-                                                size_t nsize) {
-       (void)ud;  (void)osize;  /* not used */
-       if (nsize == 0) {
-         free(ptr);
-         return NULL;
-       }
-       else
-         return realloc(ptr, nsize);
-     }
-

-Note that Standard C ensures -that free(NULL) has no effect and that -realloc(NULL, size) is equivalent to malloc(size). -This code assumes that realloc does not fail when shrinking a block. -(Although Standard C does not ensure this behavior, -it seems to be a safe assumption.) - - - - - -


lua_arith

-[-(2|1), +1, e] -

void lua_arith (lua_State *L, int op);
- -

-Performs an arithmetic operation over the two values -(or one, in the case of negation) -at the top of the stack, -with the value at the top being the second operand, -pops these values, and pushes the result of the operation. -The function follows the semantics of the corresponding Lua operator -(that is, it may call metamethods). - - -

-The value of op must be one of the following constants: - -

- - - - -

lua_atpanic

-[-0, +0, –] -

lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf);
- -

-Sets a new panic function and returns the old one (see §4.6). - - - - - -


lua_call

-[-(nargs+1), +nresults, e] -

void lua_call (lua_State *L, int nargs, int nresults);
- -

-Calls a function. - - -

-To call a function you must use the following protocol: -first, the function to be called is pushed onto the stack; -then, the arguments to the function are pushed -in direct order; -that is, the first argument is pushed first. -Finally you call lua_call; -nargs is the number of arguments that you pushed onto the stack. -All arguments and the function value are popped from the stack -when the function is called. -The function results are pushed onto the stack when the function returns. -The number of results is adjusted to nresults, -unless nresults is LUA_MULTRET. -In this case, all results from the function are pushed. -Lua takes care that the returned values fit into the stack space. -The function results are pushed onto the stack in direct order -(the first result is pushed first), -so that after the call the last result is on the top of the stack. - - -

-Any error inside the called function is propagated upwards -(with a longjmp). - - -

-The following example shows how the host program can do the -equivalent to this Lua code: - -

-     a = f("how", t.x, 14)
-

-Here it is in C: - -

-     lua_getglobal(L, "f");                  /* function to be called */
-     lua_pushstring(L, "how");                        /* 1st argument */
-     lua_getglobal(L, "t");                    /* table to be indexed */
-     lua_getfield(L, -1, "x");        /* push result of t.x (2nd arg) */
-     lua_remove(L, -2);                  /* remove 't' from the stack */
-     lua_pushinteger(L, 14);                          /* 3rd argument */
-     lua_call(L, 3, 1);     /* call 'f' with 3 arguments and 1 result */
-     lua_setglobal(L, "a");                         /* set global 'a' */
-

-Note that the code above is "balanced": -at its end, the stack is back to its original configuration. -This is considered good programming practice. - - - - - -


lua_callk

-[-(nargs + 1), +nresults, e] -

void lua_callk (lua_State *L, int nargs, int nresults, int ctx,
-                lua_CFunction k);
- -

-This function behaves exactly like lua_call, -but allows the called function to yield (see §4.7). - - - - - -


lua_CFunction

-
typedef int (*lua_CFunction) (lua_State *L);
- -

-Type for C functions. - - -

-In order to communicate properly with Lua, -a C function must use the following protocol, -which defines the way parameters and results are passed: -a C function receives its arguments from Lua in its stack -in direct order (the first argument is pushed first). -So, when the function starts, -lua_gettop(L) returns the number of arguments received by the function. -The first argument (if any) is at index 1 -and its last argument is at index lua_gettop(L). -To return values to Lua, a C function just pushes them onto the stack, -in direct order (the first result is pushed first), -and returns the number of results. -Any other value in the stack below the results will be properly -discarded by Lua. -Like a Lua function, a C function called by Lua can also return -many results. - - -

-As an example, the following function receives a variable number -of numerical arguments and returns their average and sum: - -

-     static int foo (lua_State *L) {
-       int n = lua_gettop(L);    /* number of arguments */
-       lua_Number sum = 0;
-       int i;
-       for (i = 1; i <= n; i++) {
-         if (!lua_isnumber(L, i)) {
-           lua_pushstring(L, "incorrect argument");
-           lua_error(L);
-         }
-         sum += lua_tonumber(L, i);
-       }
-       lua_pushnumber(L, sum/n);        /* first result */
-       lua_pushnumber(L, sum);         /* second result */
-       return 2;                   /* number of results */
-     }
-
- - - - -

lua_checkstack

-[-0, +0, –] -

int lua_checkstack (lua_State *L, int extra);
- -

-Ensures that there are at least extra free stack slots in the stack. -It returns false if it cannot fulfill the request, -because it would cause the stack to be larger than a fixed maximum size -(typically at least a few thousand elements) or -because it cannot allocate memory for the new stack size. -This function never shrinks the stack; -if the stack is already larger than the new size, -it is left unchanged. - - - - - -


lua_close

-[-0, +0, –] -

void lua_close (lua_State *L);
- -

-Destroys all objects in the given Lua state -(calling the corresponding garbage-collection metamethods, if any) -and frees all dynamic memory used by this state. -On several platforms, you may not need to call this function, -because all resources are naturally released when the host program ends. -On the other hand, long-running programs that create multiple states, -such as daemons or web servers, -might need to close states as soon as they are not needed. - - - - - -


lua_compare

-[-0, +0, e] -

int lua_compare (lua_State *L, int index1, int index2, int op);
- -

-Compares two Lua values. -Returns 1 if the value at index index1 satisfies op -when compared with the value at index index2, -following the semantics of the corresponding Lua operator -(that is, it may call metamethods). -Otherwise returns 0. -Also returns 0 if any of the indices is non valid. - - -

-The value of op must be one of the following constants: - -

- - - - -

lua_concat

-[-n, +1, e] -

void lua_concat (lua_State *L, int n);
- -

-Concatenates the n values at the top of the stack, -pops them, and leaves the result at the top. -If n is 1, the result is the single value on the stack -(that is, the function does nothing); -if n is 0, the result is the empty string. -Concatenation is performed following the usual semantics of Lua -(see §3.4.5). - - - - - -


lua_copy

-[-0, +0, –] -

void lua_copy (lua_State *L, int fromidx, int toidx);
- -

-Moves the element at index fromidx -into the valid index toidx -without shifting any element -(therefore replacing the value at that position). - - - - - -


lua_createtable

-[-0, +1, e] -

void lua_createtable (lua_State *L, int narr, int nrec);
- -

-Creates a new empty table and pushes it onto the stack. -Parameter narr is a hint for how many elements the table -will have as a sequence; -parameter nrec is a hint for how many other elements -the table will have. -Lua may use these hints to preallocate memory for the new table. -This pre-allocation is useful for performance when you know in advance -how many elements the table will have. -Otherwise you can use the function lua_newtable. - - - - - -


lua_dump

-[-0, +0, e] -

int lua_dump (lua_State *L, lua_Writer writer, void *data);
- -

-Dumps a function as a binary chunk. -Receives a Lua function on the top of the stack -and produces a binary chunk that, -if loaded again, -results in a function equivalent to the one dumped. -As it produces parts of the chunk, -lua_dump calls function writer (see lua_Writer) -with the given data -to write them. - - -

-The value returned is the error code returned by the last -call to the writer; -0 means no errors. - - -

-This function does not pop the Lua function from the stack. - - - - - -


lua_error

-[-1, +0, v] -

int lua_error (lua_State *L);
- -

-Generates a Lua error. -The error message (which can actually be a Lua value of any type) -must be on the stack top. -This function does a long jump, -and therefore never returns -(see luaL_error). - - - - - -


lua_gc

-[-0, +0, e] -

int lua_gc (lua_State *L, int what, int data);
- -

-Controls the garbage collector. - - -

-This function performs several tasks, -according to the value of the parameter what: - -

- -

-For more details about these options, -see collectgarbage. - - - - - -


lua_getallocf

-[-0, +0, –] -

lua_Alloc lua_getallocf (lua_State *L, void **ud);
- -

-Returns the memory-allocation function of a given state. -If ud is not NULL, Lua stores in *ud the -opaque pointer passed to lua_newstate. - - - - - -


lua_getctx

-[-0, +0, –] -

int lua_getctx (lua_State *L, int *ctx);
- -

-This function is called by a continuation function (see §4.7) -to retrieve the status of the thread and a context information. - - -

-When called in the original function, -lua_getctx always returns LUA_OK -and does not change the value of its argument ctx. -When called inside a continuation function, -lua_getctx returns LUA_YIELD and sets -the value of ctx to be the context information -(the value passed as the ctx argument -to the callee together with the continuation function). - - -

-When the callee is lua_pcallk, -Lua may also call its continuation function -to handle errors during the call. -That is, upon an error in the function called by lua_pcallk, -Lua may not return to the original function -but instead may call the continuation function. -In that case, a call to lua_getctx will return the error code -(the value that would be returned by lua_pcallk); -the value of ctx will be set to the context information, -as in the case of a yield. - - - - - -


lua_getfield

-[-0, +1, e] -

void lua_getfield (lua_State *L, int index, const char *k);
- -

-Pushes onto the stack the value t[k], -where t is the value at the given index. -As in Lua, this function may trigger a metamethod -for the "index" event (see §2.4). - - - - - -


lua_getglobal

-[-0, +1, e] -

void lua_getglobal (lua_State *L, const char *name);
- -

-Pushes onto the stack the value of the global name. - - - - - -


lua_getmetatable

-[-0, +(0|1), –] -

int lua_getmetatable (lua_State *L, int index);
- -

-Pushes onto the stack the metatable of the value at the given index. -If the value does not have a metatable, -the function returns 0 and pushes nothing on the stack. - - - - - -


lua_gettable

-[-1, +1, e] -

void lua_gettable (lua_State *L, int index);
- -

-Pushes onto the stack the value t[k], -where t is the value at the given index -and k is the value at the top of the stack. - - -

-This function pops the key from the stack -(putting the resulting value in its place). -As in Lua, this function may trigger a metamethod -for the "index" event (see §2.4). - - - - - -


lua_gettop

-[-0, +0, –] -

int lua_gettop (lua_State *L);
- -

-Returns the index of the top element in the stack. -Because indices start at 1, -this result is equal to the number of elements in the stack -(and so 0 means an empty stack). - - - - - -


lua_getuservalue

-[-0, +1, –] -

void lua_getuservalue (lua_State *L, int index);
- -

-Pushes onto the stack the Lua value associated with the userdata -at the given index. -This Lua value must be a table or nil. - - - - - -


lua_insert

-[-1, +1, –] -

void lua_insert (lua_State *L, int index);
- -

-Moves the top element into the given valid index, -shifting up the elements above this index to open space. -This function cannot be called with a pseudo-index, -because a pseudo-index is not an actual stack position. - - - - - -


lua_Integer

-
typedef ptrdiff_t lua_Integer;
- -

-The type used by the Lua API to represent signed integral values. - - -

-By default it is a ptrdiff_t, -which is usually the largest signed integral type the machine handles -"comfortably". - - - - - -


lua_isboolean

-[-0, +0, –] -

int lua_isboolean (lua_State *L, int index);
- -

-Returns 1 if the value at the given index is a boolean, -and 0 otherwise. - - - - - -


lua_iscfunction

-[-0, +0, –] -

int lua_iscfunction (lua_State *L, int index);
- -

-Returns 1 if the value at the given index is a C function, -and 0 otherwise. - - - - - -


lua_isfunction

-[-0, +0, –] -

int lua_isfunction (lua_State *L, int index);
- -

-Returns 1 if the value at the given index is a function -(either C or Lua), and 0 otherwise. - - - - - -


lua_islightuserdata

-[-0, +0, –] -

int lua_islightuserdata (lua_State *L, int index);
- -

-Returns 1 if the value at the given index is a light userdata, -and 0 otherwise. - - - - - -


lua_isnil

-[-0, +0, –] -

int lua_isnil (lua_State *L, int index);
- -

-Returns 1 if the value at the given index is nil, -and 0 otherwise. - - - - - -


lua_isnone

-[-0, +0, –] -

int lua_isnone (lua_State *L, int index);
- -

-Returns 1 if the given index is not valid, -and 0 otherwise. - - - - - -


lua_isnoneornil

-[-0, +0, –] -

int lua_isnoneornil (lua_State *L, int index);
- -

-Returns 1 if the given index is not valid -or if the value at this index is nil, -and 0 otherwise. - - - - - -


lua_isnumber

-[-0, +0, –] -

int lua_isnumber (lua_State *L, int index);
- -

-Returns 1 if the value at the given index is a number -or a string convertible to a number, -and 0 otherwise. - - - - - -


lua_isstring

-[-0, +0, –] -

int lua_isstring (lua_State *L, int index);
- -

-Returns 1 if the value at the given index is a string -or a number (which is always convertible to a string), -and 0 otherwise. - - - - - -


lua_istable

-[-0, +0, –] -

int lua_istable (lua_State *L, int index);
- -

-Returns 1 if the value at the given index is a table, -and 0 otherwise. - - - - - -


lua_isthread

-[-0, +0, –] -

int lua_isthread (lua_State *L, int index);
- -

-Returns 1 if the value at the given index is a thread, -and 0 otherwise. - - - - - -


lua_isuserdata

-[-0, +0, –] -

int lua_isuserdata (lua_State *L, int index);
- -

-Returns 1 if the value at the given index is a userdata -(either full or light), and 0 otherwise. - - - - - -


lua_len

-[-0, +1, e] -

void lua_len (lua_State *L, int index);
- -

-Returns the "length" of the value at the given index; -it is equivalent to the '#' operator in Lua (see §3.4.6). -The result is pushed on the stack. - - - - - -


lua_load

-[-0, +1, –] -

int lua_load (lua_State *L,
-              lua_Reader reader,
-              void *data,
-              const char *source,
-              const char *mode);
- -

-Loads a Lua chunk (without running it). -If there are no errors, -lua_load pushes the compiled chunk as a Lua -function on top of the stack. -Otherwise, it pushes an error message. - - -

-The return values of lua_load are: - -

- -

-The lua_load function uses a user-supplied reader function -to read the chunk (see lua_Reader). -The data argument is an opaque value passed to the reader function. - - -

-The source argument gives a name to the chunk, -which is used for error messages and in debug information (see §4.9). - - -

-lua_load automatically detects whether the chunk is text or binary -and loads it accordingly (see program luac). -The string mode works as in function load, -with the addition that -a NULL value is equivalent to the string "bt". - - -

-lua_load uses the stack internally, -so the reader function should always leave the stack -unmodified when returning. - - -

-If the resulting function has one upvalue, -this upvalue is set to the value of the global environment -stored at index LUA_RIDX_GLOBALS in the registry (see §4.5). -When loading main chunks, -this upvalue will be the _ENV variable (see §2.2). - - - - - -


lua_newstate

-[-0, +0, –] -

lua_State *lua_newstate (lua_Alloc f, void *ud);
- -

-Creates a new thread running in a new, independent state. -Returns NULL if cannot create the thread or the state -(due to lack of memory). -The argument f is the allocator function; -Lua does all memory allocation for this state through this function. -The second argument, ud, is an opaque pointer that Lua -passes to the allocator in every call. - - - - - -


lua_newtable

-[-0, +1, e] -

void lua_newtable (lua_State *L);
- -

-Creates a new empty table and pushes it onto the stack. -It is equivalent to lua_createtable(L, 0, 0). - - - - - -


lua_newthread

-[-0, +1, e] -

lua_State *lua_newthread (lua_State *L);
- -

-Creates a new thread, pushes it on the stack, -and returns a pointer to a lua_State that represents this new thread. -The new thread returned by this function shares with the original thread -its global environment, -but has an independent execution stack. - - -

-There is no explicit function to close or to destroy a thread. -Threads are subject to garbage collection, -like any Lua object. - - - - - -


lua_newuserdata

-[-0, +1, e] -

void *lua_newuserdata (lua_State *L, size_t size);
- -

-This function allocates a new block of memory with the given size, -pushes onto the stack a new full userdata with the block address, -and returns this address. -The host program can freely use this memory. - - - - - -


lua_next

-[-1, +(2|0), e] -

int lua_next (lua_State *L, int index);
- -

-Pops a key from the stack, -and pushes a key–value pair from the table at the given index -(the "next" pair after the given key). -If there are no more elements in the table, -then lua_next returns 0 (and pushes nothing). - - -

-A typical traversal looks like this: - -

-     /* table is in the stack at index 't' */
-     lua_pushnil(L);  /* first key */
-     while (lua_next(L, t) != 0) {
-       /* uses 'key' (at index -2) and 'value' (at index -1) */
-       printf("%s - %s\n",
-              lua_typename(L, lua_type(L, -2)),
-              lua_typename(L, lua_type(L, -1)));
-       /* removes 'value'; keeps 'key' for next iteration */
-       lua_pop(L, 1);
-     }
-
- -

-While traversing a table, -do not call lua_tolstring directly on a key, -unless you know that the key is actually a string. -Recall that lua_tolstring may change -the value at the given index; -this confuses the next call to lua_next. - - -

-See function next for the caveats of modifying -the table during its traversal. - - - - - -


lua_Number

-
typedef double lua_Number;
- -

-The type of numbers in Lua. -By default, it is double, but that can be changed in luaconf.h. -Through this configuration file you can change -Lua to operate with another type for numbers (e.g., float or long). - - - - - -


lua_pcall

-[-(nargs + 1), +(nresults|1), –] -

int lua_pcall (lua_State *L, int nargs, int nresults, int msgh);
- -

-Calls a function in protected mode. - - -

-Both nargs and nresults have the same meaning as -in lua_call. -If there are no errors during the call, -lua_pcall behaves exactly like lua_call. -However, if there is any error, -lua_pcall catches it, -pushes a single value on the stack (the error message), -and returns an error code. -Like lua_call, -lua_pcall always removes the function -and its arguments from the stack. - - -

-If msgh is 0, -then the error message returned on the stack -is exactly the original error message. -Otherwise, msgh is the stack index of a -message handler. -(In the current implementation, this index cannot be a pseudo-index.) -In case of runtime errors, -this function will be called with the error message -and its return value will be the message -returned on the stack by lua_pcall. - - -

-Typically, the message handler is used to add more debug -information to the error message, such as a stack traceback. -Such information cannot be gathered after the return of lua_pcall, -since by then the stack has unwound. - - -

-The lua_pcall function returns one of the following codes -(defined in lua.h): - -

- - - - -

lua_pcallk

-[-(nargs + 1), +(nresults|1), –] -

int lua_pcallk (lua_State *L,
-                int nargs,
-                int nresults,
-                int errfunc,
-                int ctx,
-                lua_CFunction k);
- -

-This function behaves exactly like lua_pcall, -but allows the called function to yield (see §4.7). - - - - - -


lua_pop

-[-n, +0, –] -

void lua_pop (lua_State *L, int n);
- -

-Pops n elements from the stack. - - - - - -


lua_pushboolean

-[-0, +1, –] -

void lua_pushboolean (lua_State *L, int b);
- -

-Pushes a boolean value with value b onto the stack. - - - - - -


lua_pushcclosure

-[-n, +1, e] -

void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);
- -

-Pushes a new C closure onto the stack. - - -

-When a C function is created, -it is possible to associate some values with it, -thus creating a C closure (see §4.4); -these values are then accessible to the function whenever it is called. -To associate values with a C function, -first these values should be pushed onto the stack -(when there are multiple values, the first value is pushed first). -Then lua_pushcclosure -is called to create and push the C function onto the stack, -with the argument n telling how many values should be -associated with the function. -lua_pushcclosure also pops these values from the stack. - - -

-The maximum value for n is 255. - - -

-When n is zero, -this function creates a light C function, -which is just a pointer to the C function. -In that case, it never throws a memory error. - - - - - -


lua_pushcfunction

-[-0, +1, –] -

void lua_pushcfunction (lua_State *L, lua_CFunction f);
- -

-Pushes a C function onto the stack. -This function receives a pointer to a C function -and pushes onto the stack a Lua value of type function that, -when called, invokes the corresponding C function. - - -

-Any function to be registered in Lua must -follow the correct protocol to receive its parameters -and return its results (see lua_CFunction). - - -

-lua_pushcfunction is defined as a macro: - -

-     #define lua_pushcfunction(L,f)  lua_pushcclosure(L,f,0)
-

-Note that f is used twice. - - - - - -


lua_pushfstring

-[-0, +1, e] -

const char *lua_pushfstring (lua_State *L, const char *fmt, ...);
- -

-Pushes onto the stack a formatted string -and returns a pointer to this string. -It is similar to the ANSI C function sprintf, -but has some important differences: - -

- - - - -

lua_pushglobaltable

-[-0, +1, –] -

void lua_pushglobaltable (lua_State *L);
- -

-Pushes the global environment onto the stack. - - - - - -


lua_pushinteger

-[-0, +1, –] -

void lua_pushinteger (lua_State *L, lua_Integer n);
- -

-Pushes a number with value n onto the stack. - - - - - -


lua_pushlightuserdata

-[-0, +1, –] -

void lua_pushlightuserdata (lua_State *L, void *p);
- -

-Pushes a light userdata onto the stack. - - -

-Userdata represent C values in Lua. -A light userdata represents a pointer, a void*. -It is a value (like a number): -you do not create it, it has no individual metatable, -and it is not collected (as it was never created). -A light userdata is equal to "any" -light userdata with the same C address. - - - - - -


lua_pushliteral

-[-0, +1, e] -

const char *lua_pushliteral (lua_State *L, const char *s);
- -

-This macro is equivalent to lua_pushlstring, -but can be used only when s is a literal string. -It automatically provides the string length. - - - - - -


lua_pushlstring

-[-0, +1, e] -

const char *lua_pushlstring (lua_State *L, const char *s, size_t len);
- -

-Pushes the string pointed to by s with size len -onto the stack. -Lua makes (or reuses) an internal copy of the given string, -so the memory at s can be freed or reused immediately after -the function returns. -The string can contain any binary data, -including embedded zeros. - - -

-Returns a pointer to the internal copy of the string. - - - - - -


lua_pushnil

-[-0, +1, –] -

void lua_pushnil (lua_State *L);
- -

-Pushes a nil value onto the stack. - - - - - -


lua_pushnumber

-[-0, +1, –] -

void lua_pushnumber (lua_State *L, lua_Number n);
- -

-Pushes a number with value n onto the stack. - - - - - -


lua_pushstring

-[-0, +1, e] -

const char *lua_pushstring (lua_State *L, const char *s);
- -

-Pushes the zero-terminated string pointed to by s -onto the stack. -Lua makes (or reuses) an internal copy of the given string, -so the memory at s can be freed or reused immediately after -the function returns. - - -

-Returns a pointer to the internal copy of the string. - - -

-If s is NULL, pushes nil and returns NULL. - - - - - -


lua_pushthread

-[-0, +1, –] -

int lua_pushthread (lua_State *L);
- -

-Pushes the thread represented by L onto the stack. -Returns 1 if this thread is the main thread of its state. - - - - - -


lua_pushunsigned

-[-0, +1, –] -

void lua_pushunsigned (lua_State *L, lua_Unsigned n);
- -

-Pushes a number with value n onto the stack. - - - - - -


lua_pushvalue

-[-0, +1, –] -

void lua_pushvalue (lua_State *L, int index);
- -

-Pushes a copy of the element at the given index -onto the stack. - - - - - -


lua_pushvfstring

-[-0, +1, e] -

const char *lua_pushvfstring (lua_State *L,
-                              const char *fmt,
-                              va_list argp);
- -

-Equivalent to lua_pushfstring, except that it receives a va_list -instead of a variable number of arguments. - - - - - -


lua_rawequal

-[-0, +0, –] -

int lua_rawequal (lua_State *L, int index1, int index2);
- -

-Returns 1 if the two values in indices index1 and -index2 are primitively equal -(that is, without calling metamethods). -Otherwise returns 0. -Also returns 0 if any of the indices are non valid. - - - - - -


lua_rawget

-[-1, +1, –] -

void lua_rawget (lua_State *L, int index);
- -

-Similar to lua_gettable, but does a raw access -(i.e., without metamethods). - - - - - -


lua_rawgeti

-[-0, +1, –] -

void lua_rawgeti (lua_State *L, int index, int n);
- -

-Pushes onto the stack the value t[n], -where t is the table at the given index. -The access is raw; -that is, it does not invoke metamethods. - - - - - -


lua_rawgetp

-[-0, +1, –] -

void lua_rawgetp (lua_State *L, int index, const void *p);
- -

-Pushes onto the stack the value t[k], -where t is the table at the given index and -k is the pointer p represented as a light userdata. -The access is raw; -that is, it does not invoke metamethods. - - - - - -


lua_rawlen

-[-0, +0, –] -

size_t lua_rawlen (lua_State *L, int index);
- -

-Returns the raw "length" of the value at the given index: -for strings, this is the string length; -for tables, this is the result of the length operator ('#') -with no metamethods; -for userdata, this is the size of the block of memory allocated -for the userdata; -for other values, it is 0. - - - - - -


lua_rawset

-[-2, +0, e] -

void lua_rawset (lua_State *L, int index);
- -

-Similar to lua_settable, but does a raw assignment -(i.e., without metamethods). - - - - - -


lua_rawseti

-[-1, +0, e] -

void lua_rawseti (lua_State *L, int index, int n);
- -

-Does the equivalent of t[n] = v, -where t is the table at the given index -and v is the value at the top of the stack. - - -

-This function pops the value from the stack. -The assignment is raw; -that is, it does not invoke metamethods. - - - - - -


lua_rawsetp

-[-1, +0, e] -

void lua_rawsetp (lua_State *L, int index, const void *p);
- -

-Does the equivalent of t[k] = v, -where t is the table at the given index, -k is the pointer p represented as a light userdata, -and v is the value at the top of the stack. - - -

-This function pops the value from the stack. -The assignment is raw; -that is, it does not invoke metamethods. - - - - - -


lua_Reader

-
typedef const char * (*lua_Reader) (lua_State *L,
-                                    void *data,
-                                    size_t *size);
- -

-The reader function used by lua_load. -Every time it needs another piece of the chunk, -lua_load calls the reader, -passing along its data parameter. -The reader must return a pointer to a block of memory -with a new piece of the chunk -and set size to the block size. -The block must exist until the reader function is called again. -To signal the end of the chunk, -the reader must return NULL or set size to zero. -The reader function may return pieces of any size greater than zero. - - - - - -


lua_register

-[-0, +0, e] -

void lua_register (lua_State *L, const char *name, lua_CFunction f);
- -

-Sets the C function f as the new value of global name. -It is defined as a macro: - -

-     #define lua_register(L,n,f) \
-            (lua_pushcfunction(L, f), lua_setglobal(L, n))
-
- - - - -

lua_remove

-[-1, +0, –] -

void lua_remove (lua_State *L, int index);
- -

-Removes the element at the given valid index, -shifting down the elements above this index to fill the gap. -This function cannot be called with a pseudo-index, -because a pseudo-index is not an actual stack position. - - - - - -


lua_replace

-[-1, +0, –] -

void lua_replace (lua_State *L, int index);
- -

-Moves the top element into the given valid index -without shifting any element -(therefore replacing the value at the given index), -and then pops the top element. - - - - - -


lua_resume

-[-?, +?, –] -

int lua_resume (lua_State *L, lua_State *from, int nargs);
- -

-Starts and resumes a coroutine in a given thread. - - -

-To start a coroutine, -you push onto the thread stack the main function plus any arguments; -then you call lua_resume, -with nargs being the number of arguments. -This call returns when the coroutine suspends or finishes its execution. -When it returns, the stack contains all values passed to lua_yield, -or all values returned by the body function. -lua_resume returns -LUA_YIELD if the coroutine yields, -LUA_OK if the coroutine finishes its execution -without errors, -or an error code in case of errors (see lua_pcall). - - -

-In case of errors, -the stack is not unwound, -so you can use the debug API over it. -The error message is on the top of the stack. - - -

-To resume a coroutine, -you remove any results from the last lua_yield, -put on its stack only the values to -be passed as results from yield, -and then call lua_resume. - - -

-The parameter from represents the coroutine that is resuming L. -If there is no such coroutine, -this parameter can be NULL. - - - - - -


lua_setallocf

-[-0, +0, –] -

void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
- -

-Changes the allocator function of a given state to f -with user data ud. - - - - - -


lua_setfield

-[-1, +0, e] -

void lua_setfield (lua_State *L, int index, const char *k);
- -

-Does the equivalent to t[k] = v, -where t is the value at the given index -and v is the value at the top of the stack. - - -

-This function pops the value from the stack. -As in Lua, this function may trigger a metamethod -for the "newindex" event (see §2.4). - - - - - -


lua_setglobal

-[-1, +0, e] -

void lua_setglobal (lua_State *L, const char *name);
- -

-Pops a value from the stack and -sets it as the new value of global name. - - - - - -


lua_setmetatable

-[-1, +0, –] -

void lua_setmetatable (lua_State *L, int index);
- -

-Pops a table from the stack and -sets it as the new metatable for the value at the given index. - - - - - -


lua_settable

-[-2, +0, e] -

void lua_settable (lua_State *L, int index);
- -

-Does the equivalent to t[k] = v, -where t is the value at the given index, -v is the value at the top of the stack, -and k is the value just below the top. - - -

-This function pops both the key and the value from the stack. -As in Lua, this function may trigger a metamethod -for the "newindex" event (see §2.4). - - - - - -


lua_settop

-[-?, +?, –] -

void lua_settop (lua_State *L, int index);
- -

-Accepts any index, or 0, -and sets the stack top to this index. -If the new top is larger than the old one, -then the new elements are filled with nil. -If index is 0, then all stack elements are removed. - - - - - -


lua_setuservalue

-[-1, +0, –] -

void lua_setuservalue (lua_State *L, int index);
- -

-Pops a table or nil from the stack and sets it as -the new value associated to the userdata at the given index. - - - - - -


lua_State

-
typedef struct lua_State lua_State;
- -

-An opaque structure that points to a thread and indirectly -(through the thread) to the whole state of a Lua interpreter. -The Lua library is fully reentrant: -it has no global variables. -All information about a state is accessible through this structure. - - -

-A pointer to this structure must be passed as the first argument to -every function in the library, except to lua_newstate, -which creates a Lua state from scratch. - - - - - -


lua_status

-[-0, +0, –] -

int lua_status (lua_State *L);
- -

-Returns the status of the thread L. - - -

-The status can be 0 (LUA_OK) for a normal thread, -an error code if the thread finished the execution -of a lua_resume with an error, -or LUA_YIELD if the thread is suspended. - - -

-You can only call functions in threads with status LUA_OK. -You can resume threads with status LUA_OK -(to start a new coroutine) or LUA_YIELD -(to resume a coroutine). - - - - - -


lua_toboolean

-[-0, +0, –] -

int lua_toboolean (lua_State *L, int index);
- -

-Converts the Lua value at the given index to a C boolean -value (0 or 1). -Like all tests in Lua, -lua_toboolean returns true for any Lua value -different from false and nil; -otherwise it returns false. -(If you want to accept only actual boolean values, -use lua_isboolean to test the value's type.) - - - - - -


lua_tocfunction

-[-0, +0, –] -

lua_CFunction lua_tocfunction (lua_State *L, int index);
- -

-Converts a value at the given index to a C function. -That value must be a C function; -otherwise, returns NULL. - - - - - -


lua_tointeger

-[-0, +0, –] -

lua_Integer lua_tointeger (lua_State *L, int index);
- -

-Equivalent to lua_tointegerx with isnum equal to NULL. - - - - - -


lua_tointegerx

-[-0, +0, –] -

lua_Integer lua_tointegerx (lua_State *L, int index, int *isnum);
- -

-Converts the Lua value at the given index -to the signed integral type lua_Integer. -The Lua value must be a number or a string convertible to a number -(see §3.4.2); -otherwise, lua_tointegerx returns 0. - - -

-If the number is not an integer, -it is truncated in some non-specified way. - - -

-If isnum is not NULL, -its referent is assigned a boolean value that -indicates whether the operation succeeded. - - - - - -


lua_tolstring

-[-0, +0, e] -

const char *lua_tolstring (lua_State *L, int index, size_t *len);
- -

-Converts the Lua value at the given index to a C string. -If len is not NULL, -it also sets *len with the string length. -The Lua value must be a string or a number; -otherwise, the function returns NULL. -If the value is a number, -then lua_tolstring also -changes the actual value in the stack to a string. -(This change confuses lua_next -when lua_tolstring is applied to keys during a table traversal.) - - -

-lua_tolstring returns a fully aligned pointer -to a string inside the Lua state. -This string always has a zero ('\0') -after its last character (as in C), -but can contain other zeros in its body. -Because Lua has garbage collection, -there is no guarantee that the pointer returned by lua_tolstring -will be valid after the corresponding value is removed from the stack. - - - - - -


lua_tonumber

-[-0, +0, –] -

lua_Number lua_tonumber (lua_State *L, int index);
- -

-Equivalent to lua_tonumberx with isnum equal to NULL. - - - - - -


lua_tonumberx

-[-0, +0, –] -

lua_Number lua_tonumberx (lua_State *L, int index, int *isnum);
- -

-Converts the Lua value at the given index -to the C type lua_Number (see lua_Number). -The Lua value must be a number or a string convertible to a number -(see §3.4.2); -otherwise, lua_tonumberx returns 0. - - -

-If isnum is not NULL, -its referent is assigned a boolean value that -indicates whether the operation succeeded. - - - - - -


lua_topointer

-[-0, +0, –] -

const void *lua_topointer (lua_State *L, int index);
- -

-Converts the value at the given index to a generic -C pointer (void*). -The value can be a userdata, a table, a thread, or a function; -otherwise, lua_topointer returns NULL. -Different objects will give different pointers. -There is no way to convert the pointer back to its original value. - - -

-Typically this function is used only for debug information. - - - - - -


lua_tostring

-[-0, +0, e] -

const char *lua_tostring (lua_State *L, int index);
- -

-Equivalent to lua_tolstring with len equal to NULL. - - - - - -


lua_tothread

-[-0, +0, –] -

lua_State *lua_tothread (lua_State *L, int index);
- -

-Converts the value at the given index to a Lua thread -(represented as lua_State*). -This value must be a thread; -otherwise, the function returns NULL. - - - - - -


lua_tounsigned

-[-0, +0, –] -

lua_Unsigned lua_tounsigned (lua_State *L, int index);
- -

-Equivalent to lua_tounsignedx with isnum equal to NULL. - - - - - -


lua_tounsignedx

-[-0, +0, –] -

lua_Unsigned lua_tounsignedx (lua_State *L, int index, int *isnum);
- -

-Converts the Lua value at the given index -to the unsigned integral type lua_Unsigned. -The Lua value must be a number or a string convertible to a number -(see §3.4.2); -otherwise, lua_tounsignedx returns 0. - - -

-If the number is not an integer, -it is truncated in some non-specified way. -If the number is outside the range of representable values, -it is normalized to the remainder of its division by -one more than the maximum representable value. - - -

-If isnum is not NULL, -its referent is assigned a boolean value that -indicates whether the operation succeeded. - - - - - -


lua_touserdata

-[-0, +0, –] -

void *lua_touserdata (lua_State *L, int index);
- -

-If the value at the given index is a full userdata, -returns its block address. -If the value is a light userdata, -returns its pointer. -Otherwise, returns NULL. - - - - - -


lua_type

-[-0, +0, –] -

int lua_type (lua_State *L, int index);
- -

-Returns the type of the value in the given valid index, -or LUA_TNONE for a non-valid (but acceptable) index. -The types returned by lua_type are coded by the following constants -defined in lua.h: -LUA_TNIL, -LUA_TNUMBER, -LUA_TBOOLEAN, -LUA_TSTRING, -LUA_TTABLE, -LUA_TFUNCTION, -LUA_TUSERDATA, -LUA_TTHREAD, -and -LUA_TLIGHTUSERDATA. - - - - - -


lua_typename

-[-0, +0, –] -

const char *lua_typename (lua_State *L, int tp);
- -

-Returns the name of the type encoded by the value tp, -which must be one the values returned by lua_type. - - - - - -


lua_Unsigned

-
typedef unsigned long lua_Unsigned;
- -

-The type used by the Lua API to represent unsigned integral values. -It must have at least 32 bits. - - -

-By default it is an unsigned int or an unsigned long, -whichever can hold 32-bit values. - - - - - -


lua_upvalueindex

-[-0, +0, –] -

int lua_upvalueindex (int i);
- -

-Returns the pseudo-index that represents the i-th upvalue of -the running function (see §4.4). - - - - - -


lua_version

-[-0, +0, v] -

const lua_Number *lua_version (lua_State *L);
- -

-Returns the address of the version number stored in the Lua core. -When called with a valid lua_State, -returns the address of the version used to create that state. -When called with NULL, -returns the address of the version running the call. - - - - - -


lua_Writer

-
typedef int (*lua_Writer) (lua_State *L,
-                           const void* p,
-                           size_t sz,
-                           void* ud);
- -

-The type of the writer function used by lua_dump. -Every time it produces another piece of chunk, -lua_dump calls the writer, -passing along the buffer to be written (p), -its size (sz), -and the data parameter supplied to lua_dump. - - -

-The writer returns an error code: -0 means no errors; -any other value means an error and stops lua_dump from -calling the writer again. - - - - - -


lua_xmove

-[-?, +?, –] -

void lua_xmove (lua_State *from, lua_State *to, int n);
- -

-Exchange values between different threads of the same state. - - -

-This function pops n values from the stack from, -and pushes them onto the stack to. - - - - - -


lua_yield

-[-?, +?, –] -

int lua_yield (lua_State *L, int nresults);
- -

-This function is equivalent to lua_yieldk, -but it has no continuation (see §4.7). -Therefore, when the thread resumes, -it returns to the function that called -the function calling lua_yield. - - - - - -


lua_yieldk

-[-?, +?, –] -

int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k);
- -

-Yields a coroutine. - - -

-This function should only be called as the -return expression of a C function, as follows: - -

-     return lua_yieldk (L, n, i, k);
-

-When a C function calls lua_yieldk in that way, -the running coroutine suspends its execution, -and the call to lua_resume that started this coroutine returns. -The parameter nresults is the number of values from the stack -that are passed as results to lua_resume. - - -

-When the coroutine is resumed again, -Lua calls the given continuation function k to continue -the execution of the C function that yielded (see §4.7). -This continuation function receives the same stack -from the previous function, -with the results removed and -replaced by the arguments passed to lua_resume. -Moreover, -the continuation function may access the value ctx -by calling lua_getctx. - - - - - - - -

4.9 – The Debug Interface

- -

-Lua has no built-in debugging facilities. -Instead, it offers a special interface -by means of functions and hooks. -This interface allows the construction of different -kinds of debuggers, profilers, and other tools -that need "inside information" from the interpreter. - - - -


lua_Debug

-
typedef struct lua_Debug {
-  int event;
-  const char *name;           /* (n) */
-  const char *namewhat;       /* (n) */
-  const char *what;           /* (S) */
-  const char *source;         /* (S) */
-  int currentline;            /* (l) */
-  int linedefined;            /* (S) */
-  int lastlinedefined;        /* (S) */
-  unsigned char nups;         /* (u) number of upvalues */
-  unsigned char nparams;      /* (u) number of parameters */
-  char isvararg;              /* (u) */
-  char istailcall;            /* (t) */
-  char short_src[LUA_IDSIZE]; /* (S) */
-  /* private part */
-  other fields
-} lua_Debug;
- -

-A structure used to carry different pieces of -information about a function or an activation record. -lua_getstack fills only the private part -of this structure, for later use. -To fill the other fields of lua_Debug with useful information, -call lua_getinfo. - - -

-The fields of lua_Debug have the following meaning: - -

- - - - -

lua_gethook

-[-0, +0, –] -

lua_Hook lua_gethook (lua_State *L);
- -

-Returns the current hook function. - - - - - -


lua_gethookcount

-[-0, +0, –] -

int lua_gethookcount (lua_State *L);
- -

-Returns the current hook count. - - - - - -


lua_gethookmask

-[-0, +0, –] -

int lua_gethookmask (lua_State *L);
- -

-Returns the current hook mask. - - - - - -


lua_getinfo

-[-(0|1), +(0|1|2), e] -

int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
- -

-Gets information about a specific function or function invocation. - - -

-To get information about a function invocation, -the parameter ar must be a valid activation record that was -filled by a previous call to lua_getstack or -given as argument to a hook (see lua_Hook). - - -

-To get information about a function you push it onto the stack -and start the what string with the character '>'. -(In that case, -lua_getinfo pops the function from the top of the stack.) -For instance, to know in which line a function f was defined, -you can write the following code: - -

-     lua_Debug ar;
-     lua_getglobal(L, "f");  /* get global 'f' */
-     lua_getinfo(L, ">S", &ar);
-     printf("%d\n", ar.linedefined);
-
- -

-Each character in the string what -selects some fields of the structure ar to be filled or -a value to be pushed on the stack: - -

- -

-This function returns 0 on error -(for instance, an invalid option in what). - - - - - -


lua_getlocal

-[-0, +(0|1), –] -

const char *lua_getlocal (lua_State *L, lua_Debug *ar, int n);
- -

-Gets information about a local variable of -a given activation record or a given function. - - -

-In the first case, -the parameter ar must be a valid activation record that was -filled by a previous call to lua_getstack or -given as argument to a hook (see lua_Hook). -The index n selects which local variable to inspect; -see debug.getlocal for details about variable indices -and names. - - -

-lua_getlocal pushes the variable's value onto the stack -and returns its name. - - -

-In the second case, ar should be NULL and the function -to be inspected must be at the top of the stack. -In this case, only parameters of Lua functions are visible -(as there is no information about what variables are active) -and no values are pushed onto the stack. - - -

-Returns NULL (and pushes nothing) -when the index is greater than -the number of active local variables. - - - - - -


lua_getstack

-[-0, +0, –] -

int lua_getstack (lua_State *L, int level, lua_Debug *ar);
- -

-Gets information about the interpreter runtime stack. - - -

-This function fills parts of a lua_Debug structure with -an identification of the activation record -of the function executing at a given level. -Level 0 is the current running function, -whereas level n+1 is the function that has called level n -(except for tail calls, which do not count on the stack). -When there are no errors, lua_getstack returns 1; -when called with a level greater than the stack depth, -it returns 0. - - - - - -


lua_getupvalue

-[-0, +(0|1), –] -

const char *lua_getupvalue (lua_State *L, int funcindex, int n);
- -

-Gets information about a closure's upvalue. -(For Lua functions, -upvalues are the external local variables that the function uses, -and that are consequently included in its closure.) -lua_getupvalue gets the index n of an upvalue, -pushes the upvalue's value onto the stack, -and returns its name. -funcindex points to the closure in the stack. -(Upvalues have no particular order, -as they are active through the whole function. -So, they are numbered in an arbitrary order.) - - -

-Returns NULL (and pushes nothing) -when the index is greater than the number of upvalues. -For C functions, this function uses the empty string "" -as a name for all upvalues. - - - - - -


lua_Hook

-
typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
- -

-Type for debugging hook functions. - - -

-Whenever a hook is called, its ar argument has its field -event set to the specific event that triggered the hook. -Lua identifies these events with the following constants: -LUA_HOOKCALL, LUA_HOOKRET, -LUA_HOOKTAILCALL, LUA_HOOKLINE, -and LUA_HOOKCOUNT. -Moreover, for line events, the field currentline is also set. -To get the value of any other field in ar, -the hook must call lua_getinfo. - - -

-For call events, event can be LUA_HOOKCALL, -the normal value, or LUA_HOOKTAILCALL, for a tail call; -in this case, there will be no corresponding return event. - - -

-While Lua is running a hook, it disables other calls to hooks. -Therefore, if a hook calls back Lua to execute a function or a chunk, -this execution occurs without any calls to hooks. - - -

-Hook functions cannot have continuations, -that is, they cannot call lua_yieldk, -lua_pcallk, or lua_callk with a non-null k. - - -

-Hook functions can yield under the following conditions: -Only count and line events can yield -and they cannot yield any value; -to yield a hook function must finish its execution -calling lua_yield with nresults equal to zero. - - - - - -


lua_sethook

-[-0, +0, –] -

int lua_sethook (lua_State *L, lua_Hook f, int mask, int count);
- -

-Sets the debugging hook function. - - -

-Argument f is the hook function. -mask specifies on which events the hook will be called: -it is formed by a bitwise or of the constants -LUA_MASKCALL, -LUA_MASKRET, -LUA_MASKLINE, -and LUA_MASKCOUNT. -The count argument is only meaningful when the mask -includes LUA_MASKCOUNT. -For each event, the hook is called as explained below: - -

- -

-A hook is disabled by setting mask to zero. - - - - - -


lua_setlocal

-[-(0|1), +0, –] -

const char *lua_setlocal (lua_State *L, lua_Debug *ar, int n);
- -

-Sets the value of a local variable of a given activation record. -Parameters ar and n are as in lua_getlocal -(see lua_getlocal). -lua_setlocal assigns the value at the top of the stack -to the variable and returns its name. -It also pops the value from the stack. - - -

-Returns NULL (and pops nothing) -when the index is greater than -the number of active local variables. - - - - - -


lua_setupvalue

-[-(0|1), +0, –] -

const char *lua_setupvalue (lua_State *L, int funcindex, int n);
- -

-Sets the value of a closure's upvalue. -It assigns the value at the top of the stack -to the upvalue and returns its name. -It also pops the value from the stack. -Parameters funcindex and n are as in the lua_getupvalue -(see lua_getupvalue). - - -

-Returns NULL (and pops nothing) -when the index is greater than the number of upvalues. - - - - - -


lua_upvalueid

-[-0, +0, –] -

void *lua_upvalueid (lua_State *L, int funcindex, int n);
- -

-Returns an unique identifier for the upvalue numbered n -from the closure at index funcindex. -Parameters funcindex and n are as in the lua_getupvalue -(see lua_getupvalue) -(but n cannot be greater than the number of upvalues). - - -

-These unique identifiers allow a program to check whether different -closures share upvalues. -Lua closures that share an upvalue -(that is, that access a same external local variable) -will return identical ids for those upvalue indices. - - - - - -


lua_upvaluejoin

-[-0, +0, –] -

void lua_upvaluejoin (lua_State *L, int funcindex1, int n1,
-                                    int funcindex2, int n2);
- -

-Make the n1-th upvalue of the Lua closure at index funcindex1 -refer to the n2-th upvalue of the Lua closure at index funcindex2. - - - - - - - -

5 – The Auxiliary Library

- -

- -The auxiliary library provides several convenient functions -to interface C with Lua. -While the basic API provides the primitive functions for all -interactions between C and Lua, -the auxiliary library provides higher-level functions for some -common tasks. - - -

-All functions and types from the auxiliary library -are defined in header file lauxlib.h and -have a prefix luaL_. - - -

-All functions in the auxiliary library are built on -top of the basic API, -and so they provide nothing that cannot be done with that API. -Nevertheless, the use of the auxiliary library ensures -more consistency to your code. - - -

-Several functions in the auxiliary library use internally some -extra stack slots. -When a function in the auxiliary library uses less than five slots, -it does not check the stack size; -it simply assumes that there are enough slots. - - -

-Several functions in the auxiliary library are used to -check C function arguments. -Because the error message is formatted for arguments -(e.g., "bad argument #1"), -you should not use these functions for other stack values. - - -

-Functions called luaL_check* -always throw an error if the check is not satisfied. - - - -

5.1 – Functions and Types

- -

-Here we list all functions and types from the auxiliary library -in alphabetical order. - - - -


luaL_addchar

-[-?, +?, e] -

void luaL_addchar (luaL_Buffer *B, char c);
- -

-Adds the byte c to the buffer B -(see luaL_Buffer). - - - - - -


luaL_addlstring

-[-?, +?, e] -

void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l);
- -

-Adds the string pointed to by s with length l to -the buffer B -(see luaL_Buffer). -The string can contain embedded zeros. - - - - - -


luaL_addsize

-[-?, +?, e] -

void luaL_addsize (luaL_Buffer *B, size_t n);
- -

-Adds to the buffer B (see luaL_Buffer) -a string of length n previously copied to the -buffer area (see luaL_prepbuffer). - - - - - -


luaL_addstring

-[-?, +?, e] -

void luaL_addstring (luaL_Buffer *B, const char *s);
- -

-Adds the zero-terminated string pointed to by s -to the buffer B -(see luaL_Buffer). -The string cannot contain embedded zeros. - - - - - -


luaL_addvalue

-[-1, +?, e] -

void luaL_addvalue (luaL_Buffer *B);
- -

-Adds the value at the top of the stack -to the buffer B -(see luaL_Buffer). -Pops the value. - - -

-This is the only function on string buffers that can (and must) -be called with an extra element on the stack, -which is the value to be added to the buffer. - - - - - -


luaL_argcheck

-[-0, +0, v] -

void luaL_argcheck (lua_State *L,
-                    int cond,
-                    int arg,
-                    const char *extramsg);
- -

-Checks whether cond is true. -If not, raises an error with a standard message. - - - - - -


luaL_argerror

-[-0, +0, v] -

int luaL_argerror (lua_State *L, int arg, const char *extramsg);
- -

-Raises an error with a standard message -that includes extramsg as a comment. - - -

-This function never returns, -but it is an idiom to use it in C functions -as return luaL_argerror(args). - - - - - -


luaL_Buffer

-
typedef struct luaL_Buffer luaL_Buffer;
- -

-Type for a string buffer. - - -

-A string buffer allows C code to build Lua strings piecemeal. -Its pattern of use is as follows: - -

- -

-If you know beforehand the total size of the resulting string, -you can use the buffer like this: - -

- -

-During its normal operation, -a string buffer uses a variable number of stack slots. -So, while using a buffer, you cannot assume that you know where -the top of the stack is. -You can use the stack between successive calls to buffer operations -as long as that use is balanced; -that is, -when you call a buffer operation, -the stack is at the same level -it was immediately after the previous buffer operation. -(The only exception to this rule is luaL_addvalue.) -After calling luaL_pushresult the stack is back to its -level when the buffer was initialized, -plus the final string on its top. - - - - - -


luaL_buffinit

-[-0, +0, –] -

void luaL_buffinit (lua_State *L, luaL_Buffer *B);
- -

-Initializes a buffer B. -This function does not allocate any space; -the buffer must be declared as a variable -(see luaL_Buffer). - - - - - -


luaL_buffinitsize

-[-?, +?, e] -

char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz);
- -

-Equivalent to the sequence -luaL_buffinit, luaL_prepbuffsize. - - - - - -


luaL_callmeta

-[-0, +(0|1), e] -

int luaL_callmeta (lua_State *L, int obj, const char *e);
- -

-Calls a metamethod. - - -

-If the object at index obj has a metatable and this -metatable has a field e, -this function calls this field passing the object as its only argument. -In this case this function returns true and pushes onto the -stack the value returned by the call. -If there is no metatable or no metamethod, -this function returns false (without pushing any value on the stack). - - - - - -


luaL_checkany

-[-0, +0, v] -

void luaL_checkany (lua_State *L, int arg);
- -

-Checks whether the function has an argument -of any type (including nil) at position arg. - - - - - -


luaL_checkint

-[-0, +0, v] -

int luaL_checkint (lua_State *L, int arg);
- -

-Checks whether the function argument arg is a number -and returns this number cast to an int. - - - - - -


luaL_checkinteger

-[-0, +0, v] -

lua_Integer luaL_checkinteger (lua_State *L, int arg);
- -

-Checks whether the function argument arg is a number -and returns this number cast to a lua_Integer. - - - - - -


luaL_checklong

-[-0, +0, v] -

long luaL_checklong (lua_State *L, int arg);
- -

-Checks whether the function argument arg is a number -and returns this number cast to a long. - - - - - -


luaL_checklstring

-[-0, +0, v] -

const char *luaL_checklstring (lua_State *L, int arg, size_t *l);
- -

-Checks whether the function argument arg is a string -and returns this string; -if l is not NULL fills *l -with the string's length. - - -

-This function uses lua_tolstring to get its result, -so all conversions and caveats of that function apply here. - - - - - -


luaL_checknumber

-[-0, +0, v] -

lua_Number luaL_checknumber (lua_State *L, int arg);
- -

-Checks whether the function argument arg is a number -and returns this number. - - - - - -


luaL_checkoption

-[-0, +0, v] -

int luaL_checkoption (lua_State *L,
-                      int arg,
-                      const char *def,
-                      const char *const lst[]);
- -

-Checks whether the function argument arg is a string and -searches for this string in the array lst -(which must be NULL-terminated). -Returns the index in the array where the string was found. -Raises an error if the argument is not a string or -if the string cannot be found. - - -

-If def is not NULL, -the function uses def as a default value when -there is no argument arg or when this argument is nil. - - -

-This is a useful function for mapping strings to C enums. -(The usual convention in Lua libraries is -to use strings instead of numbers to select options.) - - - - - -


luaL_checkstack

-[-0, +0, v] -

void luaL_checkstack (lua_State *L, int sz, const char *msg);
- -

-Grows the stack size to top + sz elements, -raising an error if the stack cannot grow to that size. -msg is an additional text to go into the error message -(or NULL for no additional text). - - - - - -


luaL_checkstring

-[-0, +0, v] -

const char *luaL_checkstring (lua_State *L, int arg);
- -

-Checks whether the function argument arg is a string -and returns this string. - - -

-This function uses lua_tolstring to get its result, -so all conversions and caveats of that function apply here. - - - - - -


luaL_checktype

-[-0, +0, v] -

void luaL_checktype (lua_State *L, int arg, int t);
- -

-Checks whether the function argument arg has type t. -See lua_type for the encoding of types for t. - - - - - -


luaL_checkudata

-[-0, +0, v] -

void *luaL_checkudata (lua_State *L, int arg, const char *tname);
- -

-Checks whether the function argument arg is a userdata -of the type tname (see luaL_newmetatable) and -returns the userdata address (see lua_touserdata). - - - - - -


luaL_checkunsigned

-[-0, +0, v] -

lua_Unsigned luaL_checkunsigned (lua_State *L, int arg);
- -

-Checks whether the function argument arg is a number -and returns this number cast to a lua_Unsigned. - - - - - -


luaL_checkversion

-[-0, +0, –] -

void luaL_checkversion (lua_State *L);
- -

-Checks whether the core running the call, -the core that created the Lua state, -and the code making the call are all using the same version of Lua. -Also checks whether the core running the call -and the core that created the Lua state -are using the same address space. - - - - - -


luaL_dofile

-[-0, +?, e] -

int luaL_dofile (lua_State *L, const char *filename);
- -

-Loads and runs the given file. -It is defined as the following macro: - -

-     (luaL_loadfile(L, filename) || lua_pcall(L, 0, LUA_MULTRET, 0))
-

-It returns false if there are no errors -or true in case of errors. - - - - - -


luaL_dostring

-[-0, +?, –] -

int luaL_dostring (lua_State *L, const char *str);
- -

-Loads and runs the given string. -It is defined as the following macro: - -

-     (luaL_loadstring(L, str) || lua_pcall(L, 0, LUA_MULTRET, 0))
-

-It returns false if there are no errors -or true in case of errors. - - - - - -


luaL_error

-[-0, +0, v] -

int luaL_error (lua_State *L, const char *fmt, ...);
- -

-Raises an error. -The error message format is given by fmt -plus any extra arguments, -following the same rules of lua_pushfstring. -It also adds at the beginning of the message the file name and -the line number where the error occurred, -if this information is available. - - -

-This function never returns, -but it is an idiom to use it in C functions -as return luaL_error(args). - - - - - -


luaL_execresult

-[-0, +3, e] -

int luaL_execresult (lua_State *L, int stat);
- -

-This function produces the return values for -process-related functions in the standard library -(os.execute and io.close). - - - - - -


luaL_fileresult

-[-0, +(1|3), e] -

int luaL_fileresult (lua_State *L, int stat, const char *fname);
- -

-This function produces the return values for -file-related functions in the standard library -(io.open, os.rename, file:seek, etc.). - - - - - -


luaL_getmetafield

-[-0, +(0|1), e] -

int luaL_getmetafield (lua_State *L, int obj, const char *e);
- -

-Pushes onto the stack the field e from the metatable -of the object at index obj. -If the object does not have a metatable, -or if the metatable does not have this field, -returns false and pushes nothing. - - - - - -


luaL_getmetatable

-[-0, +1, –] -

void luaL_getmetatable (lua_State *L, const char *tname);
- -

-Pushes onto the stack the metatable associated with name tname -in the registry (see luaL_newmetatable). - - - - - -


luaL_getsubtable

-[-0, +1, e] -

int luaL_getsubtable (lua_State *L, int idx, const char *fname);
- -

-Ensures that the value t[fname], -where t is the value at index idx, -is a table, -and pushes that table onto the stack. -Returns true if it finds a previous table there -and false if it creates a new table. - - - - - -


luaL_gsub

-[-0, +1, e] -

const char *luaL_gsub (lua_State *L,
-                       const char *s,
-                       const char *p,
-                       const char *r);
- -

-Creates a copy of string s by replacing -any occurrence of the string p -with the string r. -Pushes the resulting string on the stack and returns it. - - - - - -


luaL_len

-[-0, +0, e] -

int luaL_len (lua_State *L, int index);
- -

-Returns the "length" of the value at the given index -as a number; -it is equivalent to the '#' operator in Lua (see §3.4.6). -Raises an error if the result of the operation is not a number. -(This case only can happen through metamethods.) - - - - - -


luaL_loadbuffer

-[-0, +1, –] -

int luaL_loadbuffer (lua_State *L,
-                     const char *buff,
-                     size_t sz,
-                     const char *name);
- -

-Equivalent to luaL_loadbufferx with mode equal to NULL. - - - - - -


luaL_loadbufferx

-[-0, +1, –] -

int luaL_loadbufferx (lua_State *L,
-                      const char *buff,
-                      size_t sz,
-                      const char *name,
-                      const char *mode);
- -

-Loads a buffer as a Lua chunk. -This function uses lua_load to load the chunk in the -buffer pointed to by buff with size sz. - - -

-This function returns the same results as lua_load. -name is the chunk name, -used for debug information and error messages. -The string mode works as in function lua_load. - - - - - -


luaL_loadfile

-[-0, +1, e] -

int luaL_loadfile (lua_State *L, const char *filename);
- -

-Equivalent to luaL_loadfilex with mode equal to NULL. - - - - - -


luaL_loadfilex

-[-0, +1, e] -

int luaL_loadfilex (lua_State *L, const char *filename,
-                                            const char *mode);
- -

-Loads a file as a Lua chunk. -This function uses lua_load to load the chunk in the file -named filename. -If filename is NULL, -then it loads from the standard input. -The first line in the file is ignored if it starts with a #. - - -

-The string mode works as in function lua_load. - - -

-This function returns the same results as lua_load, -but it has an extra error code LUA_ERRFILE -if it cannot open/read the file or the file has a wrong mode. - - -

-As lua_load, this function only loads the chunk; -it does not run it. - - - - - -


luaL_loadstring

-[-0, +1, –] -

int luaL_loadstring (lua_State *L, const char *s);
- -

-Loads a string as a Lua chunk. -This function uses lua_load to load the chunk in -the zero-terminated string s. - - -

-This function returns the same results as lua_load. - - -

-Also as lua_load, this function only loads the chunk; -it does not run it. - - - - - -


luaL_newlib

-[-0, +1, e] -

void luaL_newlib (lua_State *L, const luaL_Reg *l);
- -

-Creates a new table and registers there -the functions in list l. -It is implemented as the following macro: - -

-     (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
-
- - - - -

luaL_newlibtable

-[-0, +1, e] -

void luaL_newlibtable (lua_State *L, const luaL_Reg l[]);
- -

-Creates a new table with a size optimized -to store all entries in the array l -(but does not actually store them). -It is intended to be used in conjunction with luaL_setfuncs -(see luaL_newlib). - - -

-It is implemented as a macro. -The array l must be the actual array, -not a pointer to it. - - - - - -


luaL_newmetatable

-[-0, +1, e] -

int luaL_newmetatable (lua_State *L, const char *tname);
- -

-If the registry already has the key tname, -returns 0. -Otherwise, -creates a new table to be used as a metatable for userdata, -adds it to the registry with key tname, -and returns 1. - - -

-In both cases pushes onto the stack the final value associated -with tname in the registry. - - - - - -


luaL_newstate

-[-0, +0, –] -

lua_State *luaL_newstate (void);
- -

-Creates a new Lua state. -It calls lua_newstate with an -allocator based on the standard C realloc function -and then sets a panic function (see §4.6) that prints -an error message to the standard error output in case of fatal -errors. - - -

-Returns the new state, -or NULL if there is a memory allocation error. - - - - - -


luaL_openlibs

-[-0, +0, e] -

void luaL_openlibs (lua_State *L);
- -

-Opens all standard Lua libraries into the given state. - - - - - -


luaL_optint

-[-0, +0, v] -

int luaL_optint (lua_State *L, int arg, int d);
- -

-If the function argument arg is a number, -returns this number cast to an int. -If this argument is absent or is nil, -returns d. -Otherwise, raises an error. - - - - - -


luaL_optinteger

-[-0, +0, v] -

lua_Integer luaL_optinteger (lua_State *L,
-                             int arg,
-                             lua_Integer d);
- -

-If the function argument arg is a number, -returns this number cast to a lua_Integer. -If this argument is absent or is nil, -returns d. -Otherwise, raises an error. - - - - - -


luaL_optlong

-[-0, +0, v] -

long luaL_optlong (lua_State *L, int arg, long d);
- -

-If the function argument arg is a number, -returns this number cast to a long. -If this argument is absent or is nil, -returns d. -Otherwise, raises an error. - - - - - -


luaL_optlstring

-[-0, +0, v] -

const char *luaL_optlstring (lua_State *L,
-                             int arg,
-                             const char *d,
-                             size_t *l);
- -

-If the function argument arg is a string, -returns this string. -If this argument is absent or is nil, -returns d. -Otherwise, raises an error. - - -

-If l is not NULL, -fills the position *l with the result's length. - - - - - -


luaL_optnumber

-[-0, +0, v] -

lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number d);
- -

-If the function argument arg is a number, -returns this number. -If this argument is absent or is nil, -returns d. -Otherwise, raises an error. - - - - - -


luaL_optstring

-[-0, +0, v] -

const char *luaL_optstring (lua_State *L,
-                            int arg,
-                            const char *d);
- -

-If the function argument arg is a string, -returns this string. -If this argument is absent or is nil, -returns d. -Otherwise, raises an error. - - - - - -


luaL_optunsigned

-[-0, +0, v] -

lua_Unsigned luaL_optunsigned (lua_State *L,
-                               int arg,
-                               lua_Unsigned u);
- -

-If the function argument arg is a number, -returns this number cast to a lua_Unsigned. -If this argument is absent or is nil, -returns u. -Otherwise, raises an error. - - - - - -


luaL_prepbuffer

-[-?, +?, e] -

char *luaL_prepbuffer (luaL_Buffer *B);
- -

-Equivalent to luaL_prepbuffsize -with the predefined size LUAL_BUFFERSIZE. - - - - - -


luaL_prepbuffsize

-[-?, +?, e] -

char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz);
- -

-Returns an address to a space of size sz -where you can copy a string to be added to buffer B -(see luaL_Buffer). -After copying the string into this space you must call -luaL_addsize with the size of the string to actually add -it to the buffer. - - - - - -


luaL_pushresult

-[-?, +1, e] -

void luaL_pushresult (luaL_Buffer *B);
- -

-Finishes the use of buffer B leaving the final string on -the top of the stack. - - - - - -


luaL_pushresultsize

-[-?, +1, e] -

void luaL_pushresultsize (luaL_Buffer *B, size_t sz);
- -

-Equivalent to the sequence luaL_addsize, luaL_pushresult. - - - - - -


luaL_ref

-[-1, +0, e] -

int luaL_ref (lua_State *L, int t);
- -

-Creates and returns a reference, -in the table at index t, -for the object at the top of the stack (and pops the object). - - -

-A reference is a unique integer key. -As long as you do not manually add integer keys into table t, -luaL_ref ensures the uniqueness of the key it returns. -You can retrieve an object referred by reference r -by calling lua_rawgeti(L, t, r). -Function luaL_unref frees a reference and its associated object. - - -

-If the object at the top of the stack is nil, -luaL_ref returns the constant LUA_REFNIL. -The constant LUA_NOREF is guaranteed to be different -from any reference returned by luaL_ref. - - - - - -


luaL_Reg

-
typedef struct luaL_Reg {
-  const char *name;
-  lua_CFunction func;
-} luaL_Reg;
- -

-Type for arrays of functions to be registered by -luaL_setfuncs. -name is the function name and func is a pointer to -the function. -Any array of luaL_Reg must end with an sentinel entry -in which both name and func are NULL. - - - - - -


luaL_requiref

-[-0, +1, e] -

void luaL_requiref (lua_State *L, const char *modname,
-                    lua_CFunction openf, int glb);
- -

-Calls function openf with string modname as an argument -and sets the call result in package.loaded[modname], -as if that function has been called through require. - - -

-If glb is true, -also stores the result into global modname. - - -

-Leaves a copy of that result on the stack. - - - - - -


luaL_setfuncs

-[-nup, +0, e] -

void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup);
- -

-Registers all functions in the array l -(see luaL_Reg) into the table on the top of the stack -(below optional upvalues, see next). - - -

-When nup is not zero, -all functions are created sharing nup upvalues, -which must be previously pushed on the stack -on top of the library table. -These values are popped from the stack after the registration. - - - - - -


luaL_setmetatable

-[-0, +0, –] -

void luaL_setmetatable (lua_State *L, const char *tname);
- -

-Sets the metatable of the object at the top of the stack -as the metatable associated with name tname -in the registry (see luaL_newmetatable). - - - - - -


luaL_testudata

-[-0, +0, e] -

void *luaL_testudata (lua_State *L, int arg, const char *tname);
- -

-This function works like luaL_checkudata, -except that, when the test fails, -it returns NULL instead of throwing an error. - - - - - -


luaL_tolstring

-[-0, +1, e] -

const char *luaL_tolstring (lua_State *L, int idx, size_t *len);
- -

-Converts any Lua value at the given index to a C string -in a reasonable format. -The resulting string is pushed onto the stack and also -returned by the function. -If len is not NULL, -the function also sets *len with the string length. - - -

-If the value has a metatable with a "__tostring" field, -then luaL_tolstring calls the corresponding metamethod -with the value as argument, -and uses the result of the call as its result. - - - - - -


luaL_traceback

-[-0, +1, e] -

void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
-                     int level);
- -

-Creates and pushes a traceback of the stack L1. -If msg is not NULL it is appended -at the beginning of the traceback. -The level parameter tells at which level -to start the traceback. - - - - - -


luaL_typename

-[-0, +0, –] -

const char *luaL_typename (lua_State *L, int index);
- -

-Returns the name of the type of the value at the given index. - - - - - -


luaL_unref

-[-0, +0, –] -

void luaL_unref (lua_State *L, int t, int ref);
- -

-Releases reference ref from the table at index t -(see luaL_ref). -The entry is removed from the table, -so that the referred object can be collected. -The reference ref is also freed to be used again. - - -

-If ref is LUA_NOREF or LUA_REFNIL, -luaL_unref does nothing. - - - - - -


luaL_where

-[-0, +1, e] -

void luaL_where (lua_State *L, int lvl);
- -

-Pushes onto the stack a string identifying the current position -of the control at level lvl in the call stack. -Typically this string has the following format: - -

-     chunkname:currentline:
-

-Level 0 is the running function, -level 1 is the function that called the running function, -etc. - - -

-This function is used to build a prefix for error messages. - - - - - - - -

6 – Standard Libraries

- -

-The standard Lua libraries provide useful functions -that are implemented directly through the C API. -Some of these functions provide essential services to the language -(e.g., type and getmetatable); -others provide access to "outside" services (e.g., I/O); -and others could be implemented in Lua itself, -but are quite useful or have critical performance requirements that -deserve an implementation in C (e.g., table.sort). - - -

-All libraries are implemented through the official C API -and are provided as separate C modules. -Currently, Lua has the following standard libraries: - -

-Except for the basic and the package libraries, -each library provides all its functions as fields of a global table -or as methods of its objects. - - -

-To have access to these libraries, -the C host program should call the luaL_openlibs function, -which opens all standard libraries. -Alternatively, -the host program can open them individually by using -luaL_requiref to call -luaopen_base (for the basic library), -luaopen_package (for the package library), -luaopen_coroutine (for the coroutine library), -luaopen_string (for the string library), -luaopen_table (for the table library), -luaopen_math (for the mathematical library), -luaopen_bit32 (for the bit library), -luaopen_io (for the I/O library), -luaopen_os (for the Operating System library), -and luaopen_debug (for the debug library). -These functions are declared in lualib.h. - - - -

6.1 – Basic Functions

- -

-The basic library provides core functions to Lua. -If you do not include this library in your application, -you should check carefully whether you need to provide -implementations for some of its facilities. - - -

-


assert (v [, message])

-Issues an error when -the value of its argument v is false (i.e., nil or false); -otherwise, returns all its arguments. -message is an error message; -when absent, it defaults to "assertion failed!" - - - - -

-


collectgarbage ([opt [, arg]])

- - -

-This function is a generic interface to the garbage collector. -It performs different functions according to its first argument, opt: - -

- - - -

-


dofile ([filename])

-Opens the named file and executes its contents as a Lua chunk. -When called without arguments, -dofile executes the contents of the standard input (stdin). -Returns all values returned by the chunk. -In case of errors, dofile propagates the error -to its caller (that is, dofile does not run in protected mode). - - - - -

-


error (message [, level])

-Terminates the last protected function called -and returns message as the error message. -Function error never returns. - - -

-Usually, error adds some information about the error position -at the beginning of the message, if the message is a string. -The level argument specifies how to get the error position. -With level 1 (the default), the error position is where the -error function was called. -Level 2 points the error to where the function -that called error was called; and so on. -Passing a level 0 avoids the addition of error position information -to the message. - - - - -

-


_G

-A global variable (not a function) that -holds the global environment (see §2.2). -Lua itself does not use this variable; -changing its value does not affect any environment, -nor vice-versa. - - - - -

-


getmetatable (object)

- - -

-If object does not have a metatable, returns nil. -Otherwise, -if the object's metatable has a "__metatable" field, -returns the associated value. -Otherwise, returns the metatable of the given object. - - - - -

-


ipairs (t)

- - -

-If t has a metamethod __ipairs, -calls it with t as argument and returns the first three -results from the call. - - -

-Otherwise, -returns three values: an iterator function, the table t, and 0, -so that the construction - -

-     for i,v in ipairs(t) do body end
-

-will iterate over the pairs (1,t[1]), (2,t[2]), ..., -up to the first integer key absent from the table. - - - - -

-


load (ld [, source [, mode [, env]]])

- - -

-Loads a chunk. - - -

-If ld is a string, the chunk is this string. -If ld is a function, -load calls it repeatedly to get the chunk pieces. -Each call to ld must return a string that concatenates -with previous results. -A return of an empty string, nil, or no value signals the end of the chunk. - - -

-If there are no syntactic errors, -returns the compiled chunk as a function; -otherwise, returns nil plus the error message. - - -

-If the resulting function has upvalues, -the first upvalue is set to the value of env, -if that parameter is given, -or to the value of the global environment. -(When you load a main chunk, -the resulting function will always have exactly one upvalue, -the _ENV variable (see §2.2). -When you load a binary chunk created from a function (see string.dump), -the resulting function can have arbitrary upvalues.) - - -

-source is used as the source of the chunk for error messages -and debug information (see §4.9). -When absent, -it defaults to ld, if ld is a string, -or to "=(load)" otherwise. - - -

-The string mode controls whether the chunk can be text or binary -(that is, a precompiled chunk). -It may be the string "b" (only binary chunks), -"t" (only text chunks), -or "bt" (both binary and text). -The default is "bt". - - - - -

-


loadfile ([filename [, mode [, env]]])

- - -

-Similar to load, -but gets the chunk from file filename -or from the standard input, -if no file name is given. - - - - -

-


next (table [, index])

- - -

-Allows a program to traverse all fields of a table. -Its first argument is a table and its second argument -is an index in this table. -next returns the next index of the table -and its associated value. -When called with nil as its second argument, -next returns an initial index -and its associated value. -When called with the last index, -or with nil in an empty table, -next returns nil. -If the second argument is absent, then it is interpreted as nil. -In particular, -you can use next(t) to check whether a table is empty. - - -

-The order in which the indices are enumerated is not specified, -even for numeric indices. -(To traverse a table in numeric order, -use a numerical for.) - - -

-The behavior of next is undefined if, -during the traversal, -you assign any value to a non-existent field in the table. -You may however modify existing fields. -In particular, you may clear existing fields. - - - - -

-


pairs (t)

- - -

-If t has a metamethod __pairs, -calls it with t as argument and returns the first three -results from the call. - - -

-Otherwise, -returns three values: the next function, the table t, and nil, -so that the construction - -

-     for k,v in pairs(t) do body end
-

-will iterate over all key–value pairs of table t. - - -

-See function next for the caveats of modifying -the table during its traversal. - - - - -

-


pcall (f [, arg1, ···])

- - -

-Calls function f with -the given arguments in protected mode. -This means that any error inside f is not propagated; -instead, pcall catches the error -and returns a status code. -Its first result is the status code (a boolean), -which is true if the call succeeds without errors. -In such case, pcall also returns all results from the call, -after this first result. -In case of any error, pcall returns false plus the error message. - - - - -

-


print (···)

-Receives any number of arguments -and prints their values to stdout, -using the tostring function to convert each argument to a string. -print is not intended for formatted output, -but only as a quick way to show a value, -for instance for debugging. -For complete control over the output, -use string.format and io.write. - - - - -

-


rawequal (v1, v2)

-Checks whether v1 is equal to v2, -without invoking any metamethod. -Returns a boolean. - - - - -

-


rawget (table, index)

-Gets the real value of table[index], -without invoking any metamethod. -table must be a table; -index may be any value. - - - - -

-


rawlen (v)

-Returns the length of the object v, -which must be a table or a string, -without invoking any metamethod. -Returns an integer number. - - - - -

-


rawset (table, index, value)

-Sets the real value of table[index] to value, -without invoking any metamethod. -table must be a table, -index any value different from nil and NaN, -and value any Lua value. - - -

-This function returns table. - - - - -

-


select (index, ···)

- - -

-If index is a number, -returns all arguments after argument number index; -a negative number indexes from the end (-1 is the last argument). -Otherwise, index must be the string "#", -and select returns the total number of extra arguments it received. - - - - -

-


setmetatable (table, metatable)

- - -

-Sets the metatable for the given table. -(You cannot change the metatable of other types from Lua, only from C.) -If metatable is nil, -removes the metatable of the given table. -If the original metatable has a "__metatable" field, -raises an error. - - -

-This function returns table. - - - - -

-


tonumber (e [, base])

- - -

-When called with no base, -tonumber tries to convert its argument to a number. -If the argument is already a number or -a string convertible to a number (see §3.4.2), -then tonumber returns this number; -otherwise, it returns nil. - - -

-When called with base, -then e should be a string to be interpreted as -an integer numeral in that base. -The base may be any integer between 2 and 36, inclusive. -In bases above 10, the letter 'A' (in either upper or lower case) -represents 10, 'B' represents 11, and so forth, -with 'Z' representing 35. -If the string e is not a valid numeral in the given base, -the function returns nil. - - - - -

-


tostring (v)

-Receives a value of any type and -converts it to a string in a reasonable format. -(For complete control of how numbers are converted, -use string.format.) - - -

-If the metatable of v has a "__tostring" field, -then tostring calls the corresponding value -with v as argument, -and uses the result of the call as its result. - - - - -

-


type (v)

-Returns the type of its only argument, coded as a string. -The possible results of this function are -"nil" (a string, not the value nil), -"number", -"string", -"boolean", -"table", -"function", -"thread", -and "userdata". - - - - -

-


_VERSION

-A global variable (not a function) that -holds a string containing the current interpreter version. -The current contents of this variable is "Lua 5.2". - - - - -

-


xpcall (f, msgh [, arg1, ···])

- - -

-This function is similar to pcall, -except that it sets a new message handler msgh. - - - - - - - -

6.2 – Coroutine Manipulation

- -

-The operations related to coroutines comprise a sub-library of -the basic library and come inside the table coroutine. -See §2.6 for a general description of coroutines. - - -

-


coroutine.create (f)

- - -

-Creates a new coroutine, with body f. -f must be a Lua function. -Returns this new coroutine, -an object with type "thread". - - - - -

-


coroutine.resume (co [, val1, ···])

- - -

-Starts or continues the execution of coroutine co. -The first time you resume a coroutine, -it starts running its body. -The values val1, ... are passed -as the arguments to the body function. -If the coroutine has yielded, -resume restarts it; -the values val1, ... are passed -as the results from the yield. - - -

-If the coroutine runs without any errors, -resume returns true plus any values passed to yield -(if the coroutine yields) or any values returned by the body function -(if the coroutine terminates). -If there is any error, -resume returns false plus the error message. - - - - -

-


coroutine.running ()

- - -

-Returns the running coroutine plus a boolean, -true when the running coroutine is the main one. - - - - -

-


coroutine.status (co)

- - -

-Returns the status of coroutine co, as a string: -"running", -if the coroutine is running (that is, it called status); -"suspended", if the coroutine is suspended in a call to yield, -or if it has not started running yet; -"normal" if the coroutine is active but not running -(that is, it has resumed another coroutine); -and "dead" if the coroutine has finished its body function, -or if it has stopped with an error. - - - - -

-


coroutine.wrap (f)

- - -

-Creates a new coroutine, with body f. -f must be a Lua function. -Returns a function that resumes the coroutine each time it is called. -Any arguments passed to the function behave as the -extra arguments to resume. -Returns the same values returned by resume, -except the first boolean. -In case of error, propagates the error. - - - - -

-


coroutine.yield (···)

- - -

-Suspends the execution of the calling coroutine. -Any arguments to yield are passed as extra results to resume. - - - - - - - -

6.3 – Modules

- -

-The package library provides basic -facilities for loading modules in Lua. -It exports one function directly in the global environment: -require. -Everything else is exported in a table package. - - -

-


require (modname)

- - -

-Loads the given module. -The function starts by looking into the package.loaded table -to determine whether modname is already loaded. -If it is, then require returns the value stored -at package.loaded[modname]. -Otherwise, it tries to find a loader for the module. - - -

-To find a loader, -require is guided by the package.searchers sequence. -By changing this sequence, -we can change how require looks for a module. -The following explanation is based on the default configuration -for package.searchers. - - -

-First require queries package.preload[modname]. -If it has a value, -this value (which should be a function) is the loader. -Otherwise require searches for a Lua loader using the -path stored in package.path. -If that also fails, it searches for a C loader using the -path stored in package.cpath. -If that also fails, -it tries an all-in-one loader (see package.searchers). - - -

-Once a loader is found, -require calls the loader with two arguments: -modname and an extra value dependent on how it got the loader. -(If the loader came from a file, -this extra value is the file name.) -If the loader returns any non-nil value, -require assigns the returned value to package.loaded[modname]. -If the loader does not return a non-nil value and -has not assigned any value to package.loaded[modname], -then require assigns true to this entry. -In any case, require returns the -final value of package.loaded[modname]. - - -

-If there is any error loading or running the module, -or if it cannot find any loader for the module, -then require raises an error. - - - - -

-


package.config

- - -

-A string describing some compile-time configurations for packages. -This string is a sequence of lines: - -

- - - -

-


package.cpath

- - -

-The path used by require to search for a C loader. - - -

-Lua initializes the C path package.cpath in the same way -it initializes the Lua path package.path, -using the environment variable LUA_CPATH_5_2 -or the environment variable LUA_CPATH -or a default path defined in luaconf.h. - - - - -

-


package.loaded

- - -

-A table used by require to control which -modules are already loaded. -When you require a module modname and -package.loaded[modname] is not false, -require simply returns the value stored there. - - -

-This variable is only a reference to the real table; -assignments to this variable do not change the -table used by require. - - - - -

-


package.loadlib (libname, funcname)

- - -

-Dynamically links the host program with the C library libname. - - -

-If funcname is "*", -then it only links with the library, -making the symbols exported by the library -available to other dynamically linked libraries. -Otherwise, -it looks for a function funcname inside the library -and returns this function as a C function. -So, funcname must follow the lua_CFunction prototype -(see lua_CFunction). - - -

-This is a low-level function. -It completely bypasses the package and module system. -Unlike require, -it does not perform any path searching and -does not automatically adds extensions. -libname must be the complete file name of the C library, -including if necessary a path and an extension. -funcname must be the exact name exported by the C library -(which may depend on the C compiler and linker used). - - -

-This function is not supported by Standard C. -As such, it is only available on some platforms -(Windows, Linux, Mac OS X, Solaris, BSD, -plus other Unix systems that support the dlfcn standard). - - - - -

-


package.path

- - -

-The path used by require to search for a Lua loader. - - -

-At start-up, Lua initializes this variable with -the value of the environment variable LUA_PATH_5_2 or -the environment variable LUA_PATH or -with a default path defined in luaconf.h, -if those environment variables are not defined. -Any ";;" in the value of the environment variable -is replaced by the default path. - - - - -

-


package.preload

- - -

-A table to store loaders for specific modules -(see require). - - -

-This variable is only a reference to the real table; -assignments to this variable do not change the -table used by require. - - - - -

-


package.searchers

- - -

-A table used by require to control how to load modules. - - -

-Each entry in this table is a searcher function. -When looking for a module, -require calls each of these searchers in ascending order, -with the module name (the argument given to require) as its -sole parameter. -The function can return another function (the module loader) -plus an extra value that will be passed to that loader, -or a string explaining why it did not find that module -(or nil if it has nothing to say). - - -

-Lua initializes this table with four searcher functions. - - -

-The first searcher simply looks for a loader in the -package.preload table. - - -

-The second searcher looks for a loader as a Lua library, -using the path stored at package.path. -The search is done as described in function package.searchpath. - - -

-The third searcher looks for a loader as a C library, -using the path given by the variable package.cpath. -Again, -the search is done as described in function package.searchpath. -For instance, -if the C path is the string - -

-     "./?.so;./?.dll;/usr/local/?/init.so"
-

-the searcher for module foo -will try to open the files ./foo.so, ./foo.dll, -and /usr/local/foo/init.so, in that order. -Once it finds a C library, -this searcher first uses a dynamic link facility to link the -application with the library. -Then it tries to find a C function inside the library to -be used as the loader. -The name of this C function is the string "luaopen_" -concatenated with a copy of the module name where each dot -is replaced by an underscore. -Moreover, if the module name has a hyphen, -its prefix up to (and including) the first hyphen is removed. -For instance, if the module name is a.v1-b.c, -the function name will be luaopen_b_c. - - -

-The fourth searcher tries an all-in-one loader. -It searches the C path for a library for -the root name of the given module. -For instance, when requiring a.b.c, -it will search for a C library for a. -If found, it looks into it for an open function for -the submodule; -in our example, that would be luaopen_a_b_c. -With this facility, a package can pack several C submodules -into one single library, -with each submodule keeping its original open function. - - -

-All searchers except the first one (preload) return as the extra value -the file name where the module was found, -as returned by package.searchpath. -The first searcher returns no extra value. - - - - -

-


package.searchpath (name, path [, sep [, rep]])

- - -

-Searches for the given name in the given path. - - -

-A path is a string containing a sequence of -templates separated by semicolons. -For each template, -the function replaces each interrogation mark (if any) -in the template with a copy of name -wherein all occurrences of sep -(a dot, by default) -were replaced by rep -(the system's directory separator, by default), -and then tries to open the resulting file name. - - -

-For instance, if the path is the string - -

-     "./?.lua;./?.lc;/usr/local/?/init.lua"
-

-the search for the name foo.a -will try to open the files -./foo/a.lua, ./foo/a.lc, and -/usr/local/foo/a/init.lua, in that order. - - -

-Returns the resulting name of the first file that it can -open in read mode (after closing the file), -or nil plus an error message if none succeeds. -(This error message lists all file names it tried to open.) - - - - - - - -

6.4 – String Manipulation

- -

-This library provides generic functions for string manipulation, -such as finding and extracting substrings, and pattern matching. -When indexing a string in Lua, the first character is at position 1 -(not at 0, as in C). -Indices are allowed to be negative and are interpreted as indexing backwards, -from the end of the string. -Thus, the last character is at position -1, and so on. - - -

-The string library provides all its functions inside the table -string. -It also sets a metatable for strings -where the __index field points to the string table. -Therefore, you can use the string functions in object-oriented style. -For instance, string.byte(s,i) -can be written as s:byte(i). - - -

-The string library assumes one-byte character encodings. - - -

-


string.byte (s [, i [, j]])

-Returns the internal numerical codes of the characters s[i], -s[i+1], ..., s[j]. -The default value for i is 1; -the default value for j is i. -These indices are corrected -following the same rules of function string.sub. - - -

-Numerical codes are not necessarily portable across platforms. - - - - -

-


string.char (···)

-Receives zero or more integers. -Returns a string with length equal to the number of arguments, -in which each character has the internal numerical code equal -to its corresponding argument. - - -

-Numerical codes are not necessarily portable across platforms. - - - - -

-


string.dump (function)

- - -

-Returns a string containing a binary representation of the given function, -so that a later load on this string returns -a copy of the function (but with new upvalues). - - - - -

-


string.find (s, pattern [, init [, plain]])

- - -

-Looks for the first match of -pattern in the string s. -If it finds a match, then find returns the indices of s -where this occurrence starts and ends; -otherwise, it returns nil. -A third, optional numerical argument init specifies -where to start the search; -its default value is 1 and can be negative. -A value of true as a fourth, optional argument plain -turns off the pattern matching facilities, -so the function does a plain "find substring" operation, -with no characters in pattern being considered magic. -Note that if plain is given, then init must be given as well. - - -

-If the pattern has captures, -then in a successful match -the captured values are also returned, -after the two indices. - - - - -

-


string.format (formatstring, ···)

- - -

-Returns a formatted version of its variable number of arguments -following the description given in its first argument (which must be a string). -The format string follows the same rules as the ANSI C function sprintf. -The only differences are that the options/modifiers -*, h, L, l, n, -and p are not supported -and that there is an extra option, q. -The q option formats a string between double quotes, -using escape sequences when necessary to ensure that -it can safely be read back by the Lua interpreter. -For instance, the call - -

-     string.format('%q', 'a string with "quotes" and \n new line')
-

-may produce the string: - -

-     "a string with \"quotes\" and \
-      new line"
-
- -

-Options -A and a (when available), -E, e, f, -G, and g all expect a number as argument. -Options c, d, -i, o, u, X, and x -also expect a number, -but the range of that number may be limited by -the underlying C implementation. -For options o, u, X, and x, -the number cannot be negative. -Option q expects a string; -option s expects a string without embedded zeros. -If the argument to option s is not a string, -it is converted to one following the same rules of tostring. - - - - -

-


string.gmatch (s, pattern)

-Returns an iterator function that, -each time it is called, -returns the next captures from pattern over the string s. -If pattern specifies no captures, -then the whole match is produced in each call. - - -

-As an example, the following loop -will iterate over all the words from string s, -printing one per line: - -

-     s = "hello world from Lua"
-     for w in string.gmatch(s, "%a+") do
-       print(w)
-     end
-

-The next example collects all pairs key=value from the -given string into a table: - -

-     t = {}
-     s = "from=world, to=Lua"
-     for k, v in string.gmatch(s, "(%w+)=(%w+)") do
-       t[k] = v
-     end
-
- -

-For this function, a caret '^' at the start of a pattern does not -work as an anchor, as this would prevent the iteration. - - - - -

-


string.gsub (s, pattern, repl [, n])

-Returns a copy of s -in which all (or the first n, if given) -occurrences of the pattern have been -replaced by a replacement string specified by repl, -which can be a string, a table, or a function. -gsub also returns, as its second value, -the total number of matches that occurred. -The name gsub comes from Global SUBstitution. - - -

-If repl is a string, then its value is used for replacement. -The character % works as an escape character: -any sequence in repl of the form %d, -with d between 1 and 9, -stands for the value of the d-th captured substring. -The sequence %0 stands for the whole match. -The sequence %% stands for a single %. - - -

-If repl is a table, then the table is queried for every match, -using the first capture as the key. - - -

-If repl is a function, then this function is called every time a -match occurs, with all captured substrings passed as arguments, -in order. - - -

-In any case, -if the pattern specifies no captures, -then it behaves as if the whole pattern was inside a capture. - - -

-If the value returned by the table query or by the function call -is a string or a number, -then it is used as the replacement string; -otherwise, if it is false or nil, -then there is no replacement -(that is, the original match is kept in the string). - - -

-Here are some examples: - -

-     x = string.gsub("hello world", "(%w+)", "%1 %1")
-     --> x="hello hello world world"
-     
-     x = string.gsub("hello world", "%w+", "%0 %0", 1)
-     --> x="hello hello world"
-     
-     x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1")
-     --> x="world hello Lua from"
-     
-     x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv)
-     --> x="home = /home/roberto, user = roberto"
-     
-     x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s)
-           return load(s)()
-         end)
-     --> x="4+5 = 9"
-     
-     local t = {name="lua", version="5.2"}
-     x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t)
-     --> x="lua-5.2.tar.gz"
-
- - - -

-


string.len (s)

-Receives a string and returns its length. -The empty string "" has length 0. -Embedded zeros are counted, -so "a\000bc\000" has length 5. - - - - -

-


string.lower (s)

-Receives a string and returns a copy of this string with all -uppercase letters changed to lowercase. -All other characters are left unchanged. -The definition of what an uppercase letter is depends on the current locale. - - - - -

-


string.match (s, pattern [, init])

-Looks for the first match of -pattern in the string s. -If it finds one, then match returns -the captures from the pattern; -otherwise it returns nil. -If pattern specifies no captures, -then the whole match is returned. -A third, optional numerical argument init specifies -where to start the search; -its default value is 1 and can be negative. - - - - -

-


string.rep (s, n [, sep])

-Returns a string that is the concatenation of n copies of -the string s separated by the string sep. -The default value for sep is the empty string -(that is, no separator). - - - - -

-


string.reverse (s)

-Returns a string that is the string s reversed. - - - - -

-


string.sub (s, i [, j])

-Returns the substring of s that -starts at i and continues until j; -i and j can be negative. -If j is absent, then it is assumed to be equal to -1 -(which is the same as the string length). -In particular, -the call string.sub(s,1,j) returns a prefix of s -with length j, -and string.sub(s, -i) returns a suffix of s -with length i. - - -

-If, after the translation of negative indices, -i is less than 1, -it is corrected to 1. -If j is greater than the string length, -it is corrected to that length. -If, after these corrections, -i is greater than j, -the function returns the empty string. - - - - -

-


string.upper (s)

-Receives a string and returns a copy of this string with all -lowercase letters changed to uppercase. -All other characters are left unchanged. -The definition of what a lowercase letter is depends on the current locale. - - - -

6.4.1 – Patterns

- - -

Character Class:

-A character class is used to represent a set of characters. -The following combinations are allowed in describing a character class: - -

-For all classes represented by single letters (%a, %c, etc.), -the corresponding uppercase letter represents the complement of the class. -For instance, %S represents all non-space characters. - - -

-The definitions of letter, space, and other character groups -depend on the current locale. -In particular, the class [a-z] may not be equivalent to %l. - - - - - -

Pattern Item:

-A pattern item can be - -

- - - - -

Pattern:

-A pattern is a sequence of pattern items. -A caret '^' at the beginning of a pattern anchors the match at the -beginning of the subject string. -A '$' at the end of a pattern anchors the match at the -end of the subject string. -At other positions, -'^' and '$' have no special meaning and represent themselves. - - - - - -

Captures:

-A pattern can contain sub-patterns enclosed in parentheses; -they describe captures. -When a match succeeds, the substrings of the subject string -that match captures are stored (captured) for future use. -Captures are numbered according to their left parentheses. -For instance, in the pattern "(a*(.)%w(%s*))", -the part of the string matching "a*(.)%w(%s*)" is -stored as the first capture (and therefore has number 1); -the character matching "." is captured with number 2, -and the part matching "%s*" has number 3. - - -

-As a special case, the empty capture () captures -the current string position (a number). -For instance, if we apply the pattern "()aa()" on the -string "flaaap", there will be two captures: 3 and 5. - - - - - - - - - - - -

6.5 – Table Manipulation

- -

-This library provides generic functions for table manipulation. -It provides all its functions inside the table table. - - -

-Remember that, whenever an operation needs the length of a table, -the table should be a proper sequence -or have a __len metamethod (see §3.4.6). -All functions ignore non-numeric keys -in tables given as arguments. - - -

-For performance reasons, -all table accesses (get/set) performed by these functions are raw. - - -

-


table.concat (list [, sep [, i [, j]]])

- - -

-Given a list where all elements are strings or numbers, -returns the string list[i]..sep..list[i+1] ··· sep..list[j]. -The default value for sep is the empty string, -the default for i is 1, -and the default for j is #list. -If i is greater than j, returns the empty string. - - - - -

-


table.insert (list, [pos,] value)

- - -

-Inserts element value at position pos in list, -shifting up the elements -list[pos], list[pos+1], ···, list[#list]. -The default value for pos is #list+1, -so that a call table.insert(t,x) inserts x at the end -of list t. - - - - -

-


table.pack (···)

- - -

-Returns a new table with all parameters stored into keys 1, 2, etc. -and with a field "n" with the total number of parameters. -Note that the resulting table may not be a sequence. - - - - -

-


table.remove (list [, pos])

- - -

-Removes from list the element at position pos, -returning the value of the removed element. -When pos is an integer between 1 and #list, -it shifts down the elements -list[pos+1], list[pos+2], ···, list[#list] -and erases element list[#list]; -The index pos can also be 0 when #list is 0, -or #list + 1; -in those cases, the function erases the element list[pos]. - - -

-The default value for pos is #list, -so that a call table.remove(t) removes the last element -of list t. - - - - -

-


table.sort (list [, comp])

- - -

-Sorts list elements in a given order, in-place, -from list[1] to list[#list]. -If comp is given, -then it must be a function that receives two list elements -and returns true when the first element must come -before the second in the final order -(so that not comp(list[i+1],list[i]) will be true after the sort). -If comp is not given, -then the standard Lua operator < is used instead. - - -

-The sort algorithm is not stable; -that is, elements considered equal by the given order -may have their relative positions changed by the sort. - - - - -

-


table.unpack (list [, i [, j]])

- - -

-Returns the elements from the given table. -This function is equivalent to - -

-     return list[i], list[i+1], ···, list[j]
-

-By default, i is 1 and j is #list. - - - - - - - -

6.6 – Mathematical Functions

- -

-This library is an interface to the standard C math library. -It provides all its functions inside the table math. - - -

-


math.abs (x)

- - -

-Returns the absolute value of x. - - - - -

-


math.acos (x)

- - -

-Returns the arc cosine of x (in radians). - - - - -

-


math.asin (x)

- - -

-Returns the arc sine of x (in radians). - - - - -

-


math.atan (x)

- - -

-Returns the arc tangent of x (in radians). - - - - -

-


math.atan2 (y, x)

- - -

-Returns the arc tangent of y/x (in radians), -but uses the signs of both parameters to find the -quadrant of the result. -(It also handles correctly the case of x being zero.) - - - - -

-


math.ceil (x)

- - -

-Returns the smallest integer larger than or equal to x. - - - - -

-


math.cos (x)

- - -

-Returns the cosine of x (assumed to be in radians). - - - - -

-


math.cosh (x)

- - -

-Returns the hyperbolic cosine of x. - - - - -

-


math.deg (x)

- - -

-Returns the angle x (given in radians) in degrees. - - - - -

-


math.exp (x)

- - -

-Returns the value ex. - - - - -

-


math.floor (x)

- - -

-Returns the largest integer smaller than or equal to x. - - - - -

-


math.fmod (x, y)

- - -

-Returns the remainder of the division of x by y -that rounds the quotient towards zero. - - - - -

-


math.frexp (x)

- - -

-Returns m and e such that x = m2e, -e is an integer and the absolute value of m is -in the range [0.5, 1) -(or zero when x is zero). - - - - -

-


math.huge

- - -

-The value HUGE_VAL, -a value larger than or equal to any other numerical value. - - - - -

-


math.ldexp (m, e)

- - -

-Returns m2e (e should be an integer). - - - - -

-


math.log (x [, base])

- - -

-Returns the logarithm of x in the given base. -The default for base is e -(so that the function returns the natural logarithm of x). - - - - -

-


math.max (x, ···)

- - -

-Returns the maximum value among its arguments. - - - - -

-


math.min (x, ···)

- - -

-Returns the minimum value among its arguments. - - - - -

-


math.modf (x)

- - -

-Returns two numbers, -the integral part of x and the fractional part of x. - - - - -

-


math.pi

- - -

-The value of π. - - - - -

-


math.pow (x, y)

- - -

-Returns xy. -(You can also use the expression x^y to compute this value.) - - - - -

-


math.rad (x)

- - -

-Returns the angle x (given in degrees) in radians. - - - - -

-


math.random ([m [, n]])

- - -

-This function is an interface to the simple -pseudo-random generator function rand provided by Standard C. -(No guarantees can be given for its statistical properties.) - - -

-When called without arguments, -returns a uniform pseudo-random real number -in the range [0,1). -When called with an integer number m, -math.random returns -a uniform pseudo-random integer in the range [1, m]. -When called with two integer numbers m and n, -math.random returns a uniform pseudo-random -integer in the range [m, n]. - - - - -

-


math.randomseed (x)

- - -

-Sets x as the "seed" -for the pseudo-random generator: -equal seeds produce equal sequences of numbers. - - - - -

-


math.sin (x)

- - -

-Returns the sine of x (assumed to be in radians). - - - - -

-


math.sinh (x)

- - -

-Returns the hyperbolic sine of x. - - - - -

-


math.sqrt (x)

- - -

-Returns the square root of x. -(You can also use the expression x^0.5 to compute this value.) - - - - -

-


math.tan (x)

- - -

-Returns the tangent of x (assumed to be in radians). - - - - -

-


math.tanh (x)

- - -

-Returns the hyperbolic tangent of x. - - - - - - - -

6.7 – Bitwise Operations

- -

-This library provides bitwise operations. -It provides all its functions inside the table bit32. - - -

-Unless otherwise stated, -all functions accept numeric arguments in the range -(-251,+251); -each argument is normalized to -the remainder of its division by 232 -and truncated to an integer (in some unspecified way), -so that its final value falls in the range [0,232 - 1]. -Similarly, all results are in the range [0,232 - 1]. -Note that bit32.bnot(0) is 0xFFFFFFFF, -which is different from -1. - - -

-


bit32.arshift (x, disp)

- - -

-Returns the number x shifted disp bits to the right. -The number disp may be any representable integer. -Negative displacements shift to the left. - - -

-This shift operation is what is called arithmetic shift. -Vacant bits on the left are filled -with copies of the higher bit of x; -vacant bits on the right are filled with zeros. -In particular, -displacements with absolute values higher than 31 -result in zero or 0xFFFFFFFF (all original bits are shifted out). - - - - -

-


bit32.band (···)

- - -

-Returns the bitwise and of its operands. - - - - -

-


bit32.bnot (x)

- - -

-Returns the bitwise negation of x. -For any integer x, -the following identity holds: - -

-     assert(bit32.bnot(x) == (-1 - x) % 2^32)
-
- - - -

-


bit32.bor (···)

- - -

-Returns the bitwise or of its operands. - - - - -

-


bit32.btest (···)

- - -

-Returns a boolean signaling -whether the bitwise and of its operands is different from zero. - - - - -

-


bit32.bxor (···)

- - -

-Returns the bitwise exclusive or of its operands. - - - - -

-


bit32.extract (n, field [, width])

- - -

-Returns the unsigned number formed by the bits -field to field + width - 1 from n. -Bits are numbered from 0 (least significant) to 31 (most significant). -All accessed bits must be in the range [0, 31]. - - -

-The default for width is 1. - - - - -

-


bit32.replace (n, v, field [, width])

- - -

-Returns a copy of n with -the bits field to field + width - 1 -replaced by the value v. -See bit32.extract for details about field and width. - - - - -

-


bit32.lrotate (x, disp)

- - -

-Returns the number x rotated disp bits to the left. -The number disp may be any representable integer. - - -

-For any valid displacement, -the following identity holds: - -

-     assert(bit32.lrotate(x, disp) == bit32.lrotate(x, disp % 32))
-

-In particular, -negative displacements rotate to the right. - - - - -

-


bit32.lshift (x, disp)

- - -

-Returns the number x shifted disp bits to the left. -The number disp may be any representable integer. -Negative displacements shift to the right. -In any direction, vacant bits are filled with zeros. -In particular, -displacements with absolute values higher than 31 -result in zero (all bits are shifted out). - - -

-For positive displacements, -the following equality holds: - -

-     assert(bit32.lshift(b, disp) == (b * 2^disp) % 2^32)
-
- - - -

-


bit32.rrotate (x, disp)

- - -

-Returns the number x rotated disp bits to the right. -The number disp may be any representable integer. - - -

-For any valid displacement, -the following identity holds: - -

-     assert(bit32.rrotate(x, disp) == bit32.rrotate(x, disp % 32))
-

-In particular, -negative displacements rotate to the left. - - - - -

-


bit32.rshift (x, disp)

- - -

-Returns the number x shifted disp bits to the right. -The number disp may be any representable integer. -Negative displacements shift to the left. -In any direction, vacant bits are filled with zeros. -In particular, -displacements with absolute values higher than 31 -result in zero (all bits are shifted out). - - -

-For positive displacements, -the following equality holds: - -

-     assert(bit32.rshift(b, disp) == math.floor(b % 2^32 / 2^disp))
-
- -

-This shift operation is what is called logical shift. - - - - - - - -

6.8 – Input and Output Facilities

- -

-The I/O library provides two different styles for file manipulation. -The first one uses implicit file descriptors; -that is, there are operations to set a default input file and a -default output file, -and all input/output operations are over these default files. -The second style uses explicit file descriptors. - - -

-When using implicit file descriptors, -all operations are supplied by table io. -When using explicit file descriptors, -the operation io.open returns a file descriptor -and then all operations are supplied as methods of the file descriptor. - - -

-The table io also provides -three predefined file descriptors with their usual meanings from C: -io.stdin, io.stdout, and io.stderr. -The I/O library never closes these files. - - -

-Unless otherwise stated, -all I/O functions return nil on failure -(plus an error message as a second result and -a system-dependent error code as a third result) -and some value different from nil on success. -On non-Posix systems, -the computation of the error message and error code -in case of errors -may be not thread safe, -because they rely on the global C variable errno. - - -

-


io.close ([file])

- - -

-Equivalent to file:close(). -Without a file, closes the default output file. - - - - -

-


io.flush ()

- - -

-Equivalent to io.output():flush(). - - - - -

-


io.input ([file])

- - -

-When called with a file name, it opens the named file (in text mode), -and sets its handle as the default input file. -When called with a file handle, -it simply sets this file handle as the default input file. -When called without parameters, -it returns the current default input file. - - -

-In case of errors this function raises the error, -instead of returning an error code. - - - - -

-


io.lines ([filename ···])

- - -

-Opens the given file name in read mode -and returns an iterator function that -works like file:lines(···) over the opened file. -When the iterator function detects the end of file, -it returns nil (to finish the loop) and automatically closes the file. - - -

-The call io.lines() (with no file name) is equivalent -to io.input():lines(); -that is, it iterates over the lines of the default input file. -In this case it does not close the file when the loop ends. - - -

-In case of errors this function raises the error, -instead of returning an error code. - - - - -

-


io.open (filename [, mode])

- - -

-This function opens a file, -in the mode specified in the string mode. -It returns a new file handle, -or, in case of errors, nil plus an error message. - - -

-The mode string can be any of the following: - -

-The mode string can also have a 'b' at the end, -which is needed in some systems to open the file in binary mode. - - - - -

-


io.output ([file])

- - -

-Similar to io.input, but operates over the default output file. - - - - -

-


io.popen (prog [, mode])

- - -

-This function is system dependent and is not available -on all platforms. - - -

-Starts program prog in a separated process and returns -a file handle that you can use to read data from this program -(if mode is "r", the default) -or to write data to this program -(if mode is "w"). - - - - -

-


io.read (···)

- - -

-Equivalent to io.input():read(···). - - - - -

-


io.tmpfile ()

- - -

-Returns a handle for a temporary file. -This file is opened in update mode -and it is automatically removed when the program ends. - - - - -

-


io.type (obj)

- - -

-Checks whether obj is a valid file handle. -Returns the string "file" if obj is an open file handle, -"closed file" if obj is a closed file handle, -or nil if obj is not a file handle. - - - - -

-


io.write (···)

- - -

-Equivalent to io.output():write(···). - - - - -

-


file:close ()

- - -

-Closes file. -Note that files are automatically closed when -their handles are garbage collected, -but that takes an unpredictable amount of time to happen. - - -

-When closing a file handle created with io.popen, -file:close returns the same values -returned by os.execute. - - - - -

-


file:flush ()

- - -

-Saves any written data to file. - - - - -

-


file:lines (···)

- - -

-Returns an iterator function that, -each time it is called, -reads the file according to the given formats. -When no format is given, -uses "*l" as a default. -As an example, the construction - -

-     for c in file:lines(1) do body end
-

-will iterate over all characters of the file, -starting at the current position. -Unlike io.lines, this function does not close the file -when the loop ends. - - -

-In case of errors this function raises the error, -instead of returning an error code. - - - - -

-


file:read (···)

- - -

-Reads the file file, -according to the given formats, which specify what to read. -For each format, -the function returns a string (or a number) with the characters read, -or nil if it cannot read data with the specified format. -When called without formats, -it uses a default format that reads the next line -(see below). - - -

-The available formats are - -

- - - -

-


file:seek ([whence [, offset]])

- - -

-Sets and gets the file position, -measured from the beginning of the file, -to the position given by offset plus a base -specified by the string whence, as follows: - -

-In case of success, seek returns the final file position, -measured in bytes from the beginning of the file. -If seek fails, it returns nil, -plus a string describing the error. - - -

-The default value for whence is "cur", -and for offset is 0. -Therefore, the call file:seek() returns the current -file position, without changing it; -the call file:seek("set") sets the position to the -beginning of the file (and returns 0); -and the call file:seek("end") sets the position to the -end of the file, and returns its size. - - - - -

-


file:setvbuf (mode [, size])

- - -

-Sets the buffering mode for an output file. -There are three available modes: - -

-For the last two cases, size -specifies the size of the buffer, in bytes. -The default is an appropriate size. - - - - -

-


file:write (···)

- - -

-Writes the value of each of its arguments to file. -The arguments must be strings or numbers. - - -

-In case of success, this function returns file. -Otherwise it returns nil plus a string describing the error. - - - - - - - -

6.9 – Operating System Facilities

- -

-This library is implemented through table os. - - -

-


os.clock ()

- - -

-Returns an approximation of the amount in seconds of CPU time -used by the program. - - - - -

-


os.date ([format [, time]])

- - -

-Returns a string or a table containing date and time, -formatted according to the given string format. - - -

-If the time argument is present, -this is the time to be formatted -(see the os.time function for a description of this value). -Otherwise, date formats the current time. - - -

-If format starts with '!', -then the date is formatted in Coordinated Universal Time. -After this optional character, -if format is the string "*t", -then date returns a table with the following fields: -year (four digits), month (1–12), day (1–31), -hour (0–23), min (0–59), sec (0–61), -wday (weekday, Sunday is 1), -yday (day of the year), -and isdst (daylight saving flag, a boolean). -This last field may be absent -if the information is not available. - - -

-If format is not "*t", -then date returns the date as a string, -formatted according to the same rules as the ANSI C function strftime. - - -

-When called without arguments, -date returns a reasonable date and time representation that depends on -the host system and on the current locale -(that is, os.date() is equivalent to os.date("%c")). - - -

-On non-Posix systems, -this function may be not thread safe -because of its reliance on C function gmtime and C function localtime. - - - - -

-


os.difftime (t2, t1)

- - -

-Returns the number of seconds from time t1 to time t2. -In POSIX, Windows, and some other systems, -this value is exactly t2-t1. - - - - -

-


os.execute ([command])

- - -

-This function is equivalent to the ANSI C function system. -It passes command to be executed by an operating system shell. -Its first result is true -if the command terminated successfully, -or nil otherwise. -After this first result -the function returns a string and a number, -as follows: - -

- -

-When called without a command, -os.execute returns a boolean that is true if a shell is available. - - - - -

-


os.exit ([code [, close])

- - -

-Calls the ANSI C function exit to terminate the host program. -If code is true, -the returned status is EXIT_SUCCESS; -if code is false, -the returned status is EXIT_FAILURE; -if code is a number, -the returned status is this number. -The default value for code is true. - - -

-If the optional second argument close is true, -closes the Lua state before exiting. - - - - -

-


os.getenv (varname)

- - -

-Returns the value of the process environment variable varname, -or nil if the variable is not defined. - - - - -

-


os.remove (filename)

- - -

-Deletes the file (or empty directory, on POSIX systems) -with the given name. -If this function fails, it returns nil, -plus a string describing the error and the error code. - - - - -

-


os.rename (oldname, newname)

- - -

-Renames file or directory named oldname to newname. -If this function fails, it returns nil, -plus a string describing the error and the error code. - - - - -

-


os.setlocale (locale [, category])

- - -

-Sets the current locale of the program. -locale is a system-dependent string specifying a locale; -category is an optional string describing which category to change: -"all", "collate", "ctype", -"monetary", "numeric", or "time"; -the default category is "all". -The function returns the name of the new locale, -or nil if the request cannot be honored. - - -

-If locale is the empty string, -the current locale is set to an implementation-defined native locale. -If locale is the string "C", -the current locale is set to the standard C locale. - - -

-When called with nil as the first argument, -this function only returns the name of the current locale -for the given category. - - -

-This function may be not thread safe -because of its reliance on C function setlocale. - - - - -

-


os.time ([table])

- - -

-Returns the current time when called without arguments, -or a time representing the date and time specified by the given table. -This table must have fields year, month, and day, -and may have fields -hour (default is 12), -min (default is 0), -sec (default is 0), -and isdst (default is nil). -For a description of these fields, see the os.date function. - - -

-The returned value is a number, whose meaning depends on your system. -In POSIX, Windows, and some other systems, -this number counts the number -of seconds since some given start time (the "epoch"). -In other systems, the meaning is not specified, -and the number returned by time can be used only as an argument to -os.date and os.difftime. - - - - -

-


os.tmpname ()

- - -

-Returns a string with a file name that can -be used for a temporary file. -The file must be explicitly opened before its use -and explicitly removed when no longer needed. - - -

-On POSIX systems, -this function also creates a file with that name, -to avoid security risks. -(Someone else might create the file with wrong permissions -in the time between getting the name and creating the file.) -You still have to open the file to use it -and to remove it (even if you do not use it). - - -

-When possible, -you may prefer to use io.tmpfile, -which automatically removes the file when the program ends. - - - - - - - -

6.10 – The Debug Library

- -

-This library provides -the functionality of the debug interface (§4.9) to Lua programs. -You should exert care when using this library. -Several of its functions -violate basic assumptions about Lua code -(e.g., that variables local to a function -cannot be accessed from outside; -that userdata metatables cannot be changed by Lua code; -that Lua programs do not crash) -and therefore can compromise otherwise secure code. -Moreover, some functions in this library may be slow. - - -

-All functions in this library are provided -inside the debug table. -All functions that operate over a thread -have an optional first argument which is the -thread to operate over. -The default is always the current thread. - - -

-


debug.debug ()

- - -

-Enters an interactive mode with the user, -running each string that the user enters. -Using simple commands and other debug facilities, -the user can inspect global and local variables, -change their values, evaluate expressions, and so on. -A line containing only the word cont finishes this function, -so that the caller continues its execution. - - -

-Note that commands for debug.debug are not lexically nested -within any function and so have no direct access to local variables. - - - - -

-


debug.gethook ([thread])

- - -

-Returns the current hook settings of the thread, as three values: -the current hook function, the current hook mask, -and the current hook count -(as set by the debug.sethook function). - - - - -

-


debug.getinfo ([thread,] f [, what])

- - -

-Returns a table with information about a function. -You can give the function directly -or you can give a number as the value of f, -which means the function running at level f of the call stack -of the given thread: -level 0 is the current function (getinfo itself); -level 1 is the function that called getinfo -(except for tail calls, which do not count on the stack); -and so on. -If f is a number larger than the number of active functions, -then getinfo returns nil. - - -

-The returned table can contain all the fields returned by lua_getinfo, -with the string what describing which fields to fill in. -The default for what is to get all information available, -except the table of valid lines. -If present, -the option 'f' -adds a field named func with the function itself. -If present, -the option 'L' -adds a field named activelines with the table of -valid lines. - - -

-For instance, the expression debug.getinfo(1,"n").name returns -a table with a name for the current function, -if a reasonable name can be found, -and the expression debug.getinfo(print) -returns a table with all available information -about the print function. - - - - -

-


debug.getlocal ([thread,] f, local)

- - -

-This function returns the name and the value of the local variable -with index local of the function at level f of the stack. -This function accesses not only explicit local variables, -but also parameters, temporaries, etc. - - -

-The first parameter or local variable has index 1, and so on, -until the last active variable. -Negative indices refer to vararg parameters; --1 is the first vararg parameter. -The function returns nil if there is no variable with the given index, -and raises an error when called with a level out of range. -(You can call debug.getinfo to check whether the level is valid.) - - -

-Variable names starting with '(' (open parenthesis) -represent internal variables -(loop control variables, temporaries, varargs, and C function locals). - - -

-The parameter f may also be a function. -In that case, getlocal returns only the name of function parameters. - - - - -

-


debug.getmetatable (value)

- - -

-Returns the metatable of the given value -or nil if it does not have a metatable. - - - - -

-


debug.getregistry ()

- - -

-Returns the registry table (see §4.5). - - - - -

-


debug.getupvalue (f, up)

- - -

-This function returns the name and the value of the upvalue -with index up of the function f. -The function returns nil if there is no upvalue with the given index. - - - - -

-


debug.getuservalue (u)

- - -

-Returns the Lua value associated to u. -If u is not a userdata, -returns nil. - - - - -

-


debug.sethook ([thread,] hook, mask [, count])

- - -

-Sets the given function as a hook. -The string mask and the number count describe -when the hook will be called. -The string mask may have the following characters, -with the given meaning: - -

-With a count different from zero, -the hook is called after every count instructions. - - -

-When called without arguments, -debug.sethook turns off the hook. - - -

-When the hook is called, its first parameter is a string -describing the event that has triggered its call: -"call" (or "tail call"), -"return", -"line", and "count". -For line events, -the hook also gets the new line number as its second parameter. -Inside a hook, -you can call getinfo with level 2 to get more information about -the running function -(level 0 is the getinfo function, -and level 1 is the hook function). - - - - -

-


debug.setlocal ([thread,] level, local, value)

- - -

-This function assigns the value value to the local variable -with index local of the function at level level of the stack. -The function returns nil if there is no local -variable with the given index, -and raises an error when called with a level out of range. -(You can call getinfo to check whether the level is valid.) -Otherwise, it returns the name of the local variable. - - -

-See debug.getlocal for more information about -variable indices and names. - - - - -

-


debug.setmetatable (value, table)

- - -

-Sets the metatable for the given value to the given table -(which can be nil). -Returns value. - - - - -

-


debug.setupvalue (f, up, value)

- - -

-This function assigns the value value to the upvalue -with index up of the function f. -The function returns nil if there is no upvalue -with the given index. -Otherwise, it returns the name of the upvalue. - - - - -

-


debug.setuservalue (udata, value)

- - -

-Sets the given value as -the Lua value associated to the given udata. -value must be a table or nil; -udata must be a full userdata. - - -

-Returns udata. - - - - -

-


debug.traceback ([thread,] [message [, level]])

- - -

-If message is present but is neither a string nor nil, -this function returns message without further processing. -Otherwise, -it returns a string with a traceback of the call stack. -An optional message string is appended -at the beginning of the traceback. -An optional level number tells at which level -to start the traceback -(default is 1, the function calling traceback). - - - - -

-


debug.upvalueid (f, n)

- - -

-Returns an unique identifier (as a light userdata) -for the upvalue numbered n -from the given function. - - -

-These unique identifiers allow a program to check whether different -closures share upvalues. -Lua closures that share an upvalue -(that is, that access a same external local variable) -will return identical ids for those upvalue indices. - - - - -

-


debug.upvaluejoin (f1, n1, f2, n2)

- - -

-Make the n1-th upvalue of the Lua closure f1 -refer to the n2-th upvalue of the Lua closure f2. - - - - - - - -

7 – Lua Standalone

- -

-Although Lua has been designed as an extension language, -to be embedded in a host C program, -it is also frequently used as a standalone language. -An interpreter for Lua as a standalone language, -called simply lua, -is provided with the standard distribution. -The standalone interpreter includes -all standard libraries, including the debug library. -Its usage is: - -

-     lua [options] [script [args]]
-

-The options are: - -

-After handling its options, lua runs the given script, -passing to it the given args as string arguments. -When called without arguments, -lua behaves as lua -v -i -when the standard input (stdin) is a terminal, -and as lua - otherwise. - - -

-When called without option -E, -the interpreter checks for an environment variable LUA_INIT_5_2 -(or LUA_INIT if it is not defined) -before running any argument. -If the variable content has the format @filename, -then lua executes the file. -Otherwise, lua executes the string itself. - - -

-When called with option -E, -besides ignoring LUA_INIT, -Lua also ignores -the values of LUA_PATH and LUA_CPATH, -setting the values of -package.path and package.cpath -with the default paths defined in luaconf.h. - - -

-All options are handled in order, except -i and -E. -For instance, an invocation like - -

-     $ lua -e'a=1' -e 'print(a)' script.lua
-

-will first set a to 1, then print the value of a, -and finally run the file script.lua with no arguments. -(Here $ is the shell prompt. Your prompt may be different.) - - -

-Before starting to run the script, -lua collects all arguments in the command line -in a global table called arg. -The script name is stored at index 0, -the first argument after the script name goes to index 1, -and so on. -Any arguments before the script name -(that is, the interpreter name plus the options) -go to negative indices. -For instance, in the call - -

-     $ lua -la b.lua t1 t2
-

-the interpreter first runs the file a.lua, -then creates a table - -

-     arg = { [-2] = "lua", [-1] = "-la",
-             [0] = "b.lua",
-             [1] = "t1", [2] = "t2" }
-

-and finally runs the file b.lua. -The script is called with arg[1], arg[2], ... -as arguments; -it can also access these arguments with the vararg expression '...'. - - -

-In interactive mode, -if you write an incomplete statement, -the interpreter waits for its completion -by issuing a different prompt. - - -

-In case of unprotected errors in the script, -the interpreter reports the error to the standard error stream. -If the error object is a string, -the interpreter adds a stack traceback to it. -Otherwise, if the error object has a metamethod __tostring, -the interpreter calls this metamethod to produce the final message. -Finally, if the error object is nil, -the interpreter does not report the error. - - -

-When finishing normally, -the interpreter closes its main Lua state -(see lua_close). -The script can avoid this step by -calling os.exit to terminate. - - -

-To allow the use of Lua as a -script interpreter in Unix systems, -the standalone interpreter skips -the first line of a chunk if it starts with #. -Therefore, Lua scripts can be made into executable programs -by using chmod +x and the #! form, -as in - -

-     #!/usr/local/bin/lua
-

-(Of course, -the location of the Lua interpreter may be different in your machine. -If lua is in your PATH, -then - -

-     #!/usr/bin/env lua
-

-is a more portable solution.) - - - -

8 – Incompatibilities with the Previous Version

- -

-Here we list the incompatibilities that you may find when moving a program -from Lua 5.1 to Lua 5.2. -You can avoid some incompatibilities by compiling Lua with -appropriate options (see file luaconf.h). -However, -all these compatibility options will be removed in the next version of Lua. -Similarly, -all features marked as deprecated in Lua 5.1 -have been removed in Lua 5.2. - - - -

8.1 – Changes in the Language

- - - - - -

8.2 – Changes in the Libraries

- - - - - -

8.3 – Changes in the API

- - - - - -

9 – The Complete Syntax of Lua

- -

-Here is the complete syntax of Lua in extended BNF. -(It does not describe operator precedences.) - - - - -

-
-	chunk ::= block
-
-	block ::= {stat} [retstat]
-
-	stat ::=  ‘;’ | 
-		 varlist ‘=’ explist | 
-		 functioncall | 
-		 label | 
-		 break | 
-		 goto Name | 
-		 do block end | 
-		 while exp do block end | 
-		 repeat block until exp | 
-		 if exp then block {elseif exp then block} [else block] end | 
-		 for Name ‘=’ exp ‘,’ exp [‘,’ exp] do block end | 
-		 for namelist in explist do block end | 
-		 function funcname funcbody | 
-		 local function Name funcbody | 
-		 local namelist [‘=’ explist] 
-
-	retstat ::= return [explist] [‘;’]
-
-	label ::= ‘::’ Name ‘::’
-
-	funcname ::= Name {‘.’ Name} [‘:’ Name]
-
-	varlist ::= var {‘,’ var}
-
-	var ::=  Name | prefixexp ‘[’ exp ‘]’ | prefixexp ‘.’ Name 
-
-	namelist ::= Name {‘,’ Name}
-
-	explist ::= exp {‘,’ exp}
-
-	exp ::=  nil | false | true | Number | String | ‘...’ | functiondef | 
-		 prefixexp | tableconstructor | exp binop exp | unop exp 
-
-	prefixexp ::= var | functioncall | ‘(’ exp ‘)’
-
-	functioncall ::=  prefixexp args | prefixexp ‘:’ Name args 
-
-	args ::=  ‘(’ [explist] ‘)’ | tableconstructor | String 
-
-	functiondef ::= function funcbody
-
-	funcbody ::= ‘(’ [parlist] ‘)’ block end
-
-	parlist ::= namelist [‘,’ ‘...’] | ‘...’
-
-	tableconstructor ::= ‘{’ [fieldlist] ‘}’
-
-	fieldlist ::= field {fieldsep field} [fieldsep]
-
-	field ::= ‘[’ exp ‘]’ ‘=’ exp | Name ‘=’ exp | exp
-
-	fieldsep ::= ‘,’ | ‘;’
-
-	binop ::= ‘+’ | ‘-’ | ‘*’ | ‘/’ | ‘^’ | ‘%’ | ‘..’ | 
-		 ‘<’ | ‘<=’ | ‘>’ | ‘>=’ | ‘==’ | ‘~=’ | 
-		 and | or
-
-	unop ::= ‘-’ | not | ‘#’
-
-
- -

- - - - - - - -


- -Last update: -Thu Mar 21 12:58:59 BRT 2013 - - - - - diff --git a/contrib/lua/lua/doc/osi-certified-72x60.png b/contrib/lua/lua/doc/osi-certified-72x60.png deleted file mode 100644 index 07df5f6ee7a..00000000000 Binary files a/contrib/lua/lua/doc/osi-certified-72x60.png and /dev/null differ diff --git a/contrib/lua/lua/doc/readme.html b/contrib/lua/lua/doc/readme.html deleted file mode 100644 index 5b9e47ecba8..00000000000 --- a/contrib/lua/lua/doc/readme.html +++ /dev/null @@ -1,412 +0,0 @@ - - - -Lua 5.2 readme - - - - - - - -
-

-Lua -Welcome to Lua 5.2 -

- -

-about -· -installation -· -changes -· -license -· -reference manual - -

About Lua

- -

-Lua is a powerful, fast, lightweight, embeddable scripting language -developed by a -team -at -PUC-Rio, -the Pontifical Catholic University of Rio de Janeiro in Brazil. -Lua is -free software -used in many products and projects around the world. - -

-Lua's -official web site -provides complete information -about Lua, -including -an -executive summary -and -updated -documentation, -especially the -reference manual, -which may differ slightly from the -local copy -distributed in this package. - -

Installing Lua

- -

-Lua is distributed in -source -form. -You need to build it before using it. -Building Lua should be straightforward -because -Lua is implemented in pure ANSI C and compiles unmodified in all known -platforms that have an ANSI C compiler. -Lua also compiles unmodified as C++. -The instructions given below for building Lua are for Unix-like platforms. -See also -instructions for other systems -and -customization options. - -

-If you don't have the time or the inclination to compile Lua yourself, -get a binary from -LuaBinaries. -Try also -Lua for Windows, -an easy-to-use distribution of Lua that includes many useful libraries. - -

Building Lua

- -

-In most Unix-like platforms, simply do "make" with a suitable target. -Here are the details. - -

    -
  1. -Open a terminal window and move to -the top-level directory, which is named lua-5.2.2. -The Makefile there controls both the build process and the installation process. -

    -

  2. - Do "make" and see if your platform is listed. - The platforms currently supported are: -

    -

    - aix ansi bsd freebsd generic linux macosx mingw posix solaris -

    -

    - If your platform is listed, just do "make xxx", where xxx - is your platform name. -

    - If your platform is not listed, try the closest one or posix, generic, - ansi, in this order. -

    -

  3. -The compilation takes only a few moments -and produces three files in the src directory: -lua (the interpreter), -luac (the compiler), -and liblua.a (the library). -

    -

  4. - To check that Lua has been built correctly, do "make test" - after building Lua. This will run the interpreter and print its version string. -
-

-If you're running Linux and get compilation errors, -make sure you have installed the readline development package. -If you get link errors after that, -then try "make linux MYLIBS=-ltermcap". - -

Installing Lua

-

- Once you have built Lua, you may want to install it in an official - place in your system. In this case, do "make install". The official - place and the way to install files are defined in the Makefile. You'll - probably need the right permissions to install files. - -

- To build and install Lua in one step, do "make xxx install", - where xxx is your platform name. - -

- To install Lua locally, do "make local". - This will create a directory install with subdirectories - bin, include, lib, man, - and install Lua as listed below. - - To install Lua locally, but in some other directory, do - "make install INSTALL_TOP=xxx", where xxx is your chosen directory. - -

-
- bin: -
- lua luac -
- include: -
- lua.h luaconf.h lualib.h lauxlib.h lua.hpp -
- lib: -
- liblua.a -
- man/man1: -
- lua.1 luac.1 -
- -

- These are the only directories you need for development. - If you only want to run Lua programs, - you only need the files in bin and man. - The files in include and lib are needed for - embedding Lua in C or C++ programs. - -

Customization

-

- Three kinds of things can be customized by editing a file: -

- -

- You don't actually need to edit the Makefiles because you may set the - relevant variables in the command line when invoking make. - Nevertheless, it's probably best to edit and save the Makefiles to - record the changes you need. - -

- On the other hand, if you need to customize some Lua features, you'll need - to edit src/luaconf.h before building and installing Lua. - The edited file will be the one installed, and - it will be used by any Lua clients that you build, to ensure consistency. - Further customization is available to experts by editing the Lua sources. - -

- We strongly recommend that you enable dynamic loading in src/luaconf.h. - This is done automatically for all platforms listed above that have - this feature and also for Windows. - -

Building Lua on other systems

- -

- If you're not using the usual Unix tools, then the instructions for - building Lua depend on the compiler you use. You'll need to create - projects (or whatever your compiler uses) for building the library, - the interpreter, and the compiler, as follows: - -

-
-library: -
-lapi.c lcode.c lctype.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c -lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c ltable.c -ltm.c lundump.c lvm.c lzio.c -lauxlib.c lbaselib.c lbitlib.c lcorolib.c ldblib.c liolib.c -lmathlib.c loslib.c lstrlib.c ltablib.c loadlib.c linit.c -
-interpreter: -
- library, lua.c -
-compiler: -
- library, luac.c -
- -

- To use Lua as a library in your own programs you'll need to know how to - create and use libraries with your compiler. Moreover, to dynamically load - C libraries for Lua you'll need to know how to create dynamic libraries - and you'll need to make sure that the Lua API functions are accessible to - those dynamic libraries — but don't link the Lua library - into each dynamic library. For Unix, we recommend that the Lua library - be linked statically into the host program and its symbols exported for - dynamic linking; src/Makefile does this for the Lua interpreter. - For Windows, we recommend that the Lua library be a DLL. - -

- As mentioned above, you may edit src/luaconf.h to customize - some features before building Lua. - -

Changes since Lua 5.1

- -

-Here are the main changes introduced in Lua 5.2. -The -reference manual -lists the -incompatibilities that had to be introduced. - -

Main changes

- - -Here are the other changes introduced in Lua 5.2: -

Language

- - -

Libraries

- - -

C API

- - -

Implementation

- - -

Lua standalone interpreter

- - -

License

- -[osi certified] - - -

-Lua is free software distributed under the terms of the -MIT license -reproduced below; -it may be used for any purpose, including commercial purposes, -at absolutely no cost without having to ask us. - -The only requirement is that if you do use Lua, -then you should give us credit by including the appropriate copyright notice somewhere in your product or its documentation. - -For details, see -this. - -

-Copyright © 1994–2013 Lua.org, PUC-Rio. - -

-Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -

-The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -

-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -

-

- -


- -Last update: -Fri Feb 22 09:24:20 BRT 2013 - - - - - diff --git a/contrib/lua/lua/src/lapi.c b/contrib/lua/lua/src/lapi.c deleted file mode 100644 index 791d85454fb..00000000000 --- a/contrib/lua/lua/src/lapi.c +++ /dev/null @@ -1,1284 +0,0 @@ -/* -** $Id: lapi.c,v 2.171 2013/03/16 21:10:18 roberto Exp $ -** Lua API -** See Copyright Notice in lua.h -*/ - - -#include -#include - -#define lapi_c -#define LUA_CORE - -#include "lua.h" - -#include "lapi.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lundump.h" -#include "lvm.h" - - - -const char lua_ident[] = - "$LuaVersion: " LUA_COPYRIGHT " $" - "$LuaAuthors: " LUA_AUTHORS " $"; - - -/* value at a non-valid index */ -#define NONVALIDVALUE cast(TValue *, luaO_nilobject) - -/* corresponding test */ -#define isvalid(o) ((o) != luaO_nilobject) - -/* test for pseudo index */ -#define ispseudo(i) ((i) <= LUA_REGISTRYINDEX) - -/* test for valid but not pseudo index */ -#define isstackindex(i, o) (isvalid(o) && !ispseudo(i)) - -#define api_checkvalidindex(L, o) api_check(L, isvalid(o), "invalid index") - -#define api_checkstackindex(L, i, o) \ - api_check(L, isstackindex(i, o), "index not in the stack") - - -static TValue *index2addr (lua_State *L, int idx) { - CallInfo *ci = L->ci; - if (idx > 0) { - TValue *o = ci->func + idx; - api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index"); - if (o >= L->top) return NONVALIDVALUE; - else return o; - } - else if (!ispseudo(idx)) { /* negative index */ - api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); - return L->top + idx; - } - else if (idx == LUA_REGISTRYINDEX) - return &G(L)->l_registry; - else { /* upvalues */ - idx = LUA_REGISTRYINDEX - idx; - api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large"); - if (ttislcf(ci->func)) /* light C function? */ - return NONVALIDVALUE; /* it has no upvalues */ - else { - CClosure *func = clCvalue(ci->func); - return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : NONVALIDVALUE; - } - } -} - - -/* -** to be called by 'lua_checkstack' in protected mode, to grow stack -** capturing memory errors -*/ -static void growstack (lua_State *L, void *ud) { - int size = *(int *)ud; - luaD_growstack(L, size); -} - - -LUA_API int lua_checkstack (lua_State *L, int size) { - int res; - CallInfo *ci = L->ci; - lua_lock(L); - if (L->stack_last - L->top > size) /* stack large enough? */ - res = 1; /* yes; check is OK */ - else { /* no; need to grow stack */ - int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; - if (inuse > LUAI_MAXSTACK - size) /* can grow without overflow? */ - res = 0; /* no */ - else /* try to grow stack */ - res = (luaD_rawrunprotected(L, &growstack, &size) == LUA_OK); - } - if (res && ci->top < L->top + size) - ci->top = L->top + size; /* adjust frame top */ - lua_unlock(L); - return res; -} - - -LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { - int i; - if (from == to) return; - lua_lock(to); - api_checknelems(from, n); - api_check(from, G(from) == G(to), "moving among independent states"); - api_check(from, to->ci->top - to->top >= n, "not enough elements to move"); - from->top -= n; - for (i = 0; i < n; i++) { - setobj2s(to, to->top++, from->top + i); - } - lua_unlock(to); -} - - -LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { - lua_CFunction old; - lua_lock(L); - old = G(L)->panic; - G(L)->panic = panicf; - lua_unlock(L); - return old; -} - - -LUA_API const lua_Number *lua_version (lua_State *L) { - static const lua_Number version = LUA_VERSION_NUM; - if (L == NULL) return &version; - else return G(L)->version; -} - - - -/* -** basic stack manipulation -*/ - - -/* -** convert an acceptable stack index into an absolute index -*/ -LUA_API int lua_absindex (lua_State *L, int idx) { - return (idx > 0 || ispseudo(idx)) - ? idx - : cast_int(L->top - L->ci->func + idx); -} - - -LUA_API int lua_gettop (lua_State *L) { - return cast_int(L->top - (L->ci->func + 1)); -} - - -LUA_API void lua_settop (lua_State *L, int idx) { - StkId func = L->ci->func; - lua_lock(L); - if (idx >= 0) { - api_check(L, idx <= L->stack_last - (func + 1), "new top too large"); - while (L->top < (func + 1) + idx) - setnilvalue(L->top++); - L->top = (func + 1) + idx; - } - else { - api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top"); - L->top += idx+1; /* `subtract' index (index is negative) */ - } - lua_unlock(L); -} - - -LUA_API void lua_remove (lua_State *L, int idx) { - StkId p; - lua_lock(L); - p = index2addr(L, idx); - api_checkstackindex(L, idx, p); - while (++p < L->top) setobjs2s(L, p-1, p); - L->top--; - lua_unlock(L); -} - - -LUA_API void lua_insert (lua_State *L, int idx) { - StkId p; - StkId q; - lua_lock(L); - p = index2addr(L, idx); - api_checkstackindex(L, idx, p); - for (q = L->top; q > p; q--) /* use L->top as a temporary */ - setobjs2s(L, q, q - 1); - setobjs2s(L, p, L->top); - lua_unlock(L); -} - - -static void moveto (lua_State *L, TValue *fr, int idx) { - TValue *to = index2addr(L, idx); - api_checkvalidindex(L, to); - setobj(L, to, fr); - if (idx < LUA_REGISTRYINDEX) /* function upvalue? */ - luaC_barrier(L, clCvalue(L->ci->func), fr); - /* LUA_REGISTRYINDEX does not need gc barrier - (collector revisits it before finishing collection) */ -} - - -LUA_API void lua_replace (lua_State *L, int idx) { - lua_lock(L); - api_checknelems(L, 1); - moveto(L, L->top - 1, idx); - L->top--; - lua_unlock(L); -} - - -LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { - TValue *fr; - lua_lock(L); - fr = index2addr(L, fromidx); - moveto(L, fr, toidx); - lua_unlock(L); -} - - -LUA_API void lua_pushvalue (lua_State *L, int idx) { - lua_lock(L); - setobj2s(L, L->top, index2addr(L, idx)); - api_incr_top(L); - lua_unlock(L); -} - - - -/* -** access functions (stack -> C) -*/ - - -LUA_API int lua_type (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - return (isvalid(o) ? ttypenv(o) : LUA_TNONE); -} - - -LUA_API const char *lua_typename (lua_State *L, int t) { - UNUSED(L); - return ttypename(t); -} - - -LUA_API int lua_iscfunction (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - return (ttislcf(o) || (ttisCclosure(o))); -} - - -LUA_API int lua_isnumber (lua_State *L, int idx) { - TValue n; - const TValue *o = index2addr(L, idx); - return tonumber(o, &n); -} - - -LUA_API int lua_isstring (lua_State *L, int idx) { - int t = lua_type(L, idx); - return (t == LUA_TSTRING || t == LUA_TNUMBER); -} - - -LUA_API int lua_isuserdata (lua_State *L, int idx) { - const TValue *o = index2addr(L, idx); - return (ttisuserdata(o) || ttislightuserdata(o)); -} - - -LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { - StkId o1 = index2addr(L, index1); - StkId o2 = index2addr(L, index2); - return (isvalid(o1) && isvalid(o2)) ? luaV_rawequalobj(o1, o2) : 0; -} - - -LUA_API void lua_arith (lua_State *L, int op) { - StkId o1; /* 1st operand */ - StkId o2; /* 2nd operand */ - lua_lock(L); - if (op != LUA_OPUNM) /* all other operations expect two operands */ - api_checknelems(L, 2); - else { /* for unary minus, add fake 2nd operand */ - api_checknelems(L, 1); - setobjs2s(L, L->top, L->top - 1); - L->top++; - } - o1 = L->top - 2; - o2 = L->top - 1; - if (ttisnumber(o1) && ttisnumber(o2)) { - setnvalue(o1, luaO_arith(op, nvalue(o1), nvalue(o2))); - } - else - luaV_arith(L, o1, o1, o2, cast(TMS, op - LUA_OPADD + TM_ADD)); - L->top--; - lua_unlock(L); -} - - -LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { - StkId o1, o2; - int i = 0; - lua_lock(L); /* may call tag method */ - o1 = index2addr(L, index1); - o2 = index2addr(L, index2); - if (isvalid(o1) && isvalid(o2)) { - switch (op) { - case LUA_OPEQ: i = equalobj(L, o1, o2); break; - case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break; - case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break; - default: api_check(L, 0, "invalid option"); - } - } - lua_unlock(L); - return i; -} - - -LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *isnum) { - TValue n; - const TValue *o = index2addr(L, idx); - if (tonumber(o, &n)) { - if (isnum) *isnum = 1; - return nvalue(o); - } - else { - if (isnum) *isnum = 0; - return 0; - } -} - - -LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *isnum) { - TValue n; - const TValue *o = index2addr(L, idx); - if (tonumber(o, &n)) { - lua_Integer res; - lua_Number num = nvalue(o); - lua_number2integer(res, num); - if (isnum) *isnum = 1; - return res; - } - else { - if (isnum) *isnum = 0; - return 0; - } -} - - -LUA_API lua_Unsigned lua_tounsignedx (lua_State *L, int idx, int *isnum) { - TValue n; - const TValue *o = index2addr(L, idx); - if (tonumber(o, &n)) { - lua_Unsigned res; - lua_Number num = nvalue(o); - lua_number2unsigned(res, num); - if (isnum) *isnum = 1; - return res; - } - else { - if (isnum) *isnum = 0; - return 0; - } -} - - -LUA_API int lua_toboolean (lua_State *L, int idx) { - const TValue *o = index2addr(L, idx); - return !l_isfalse(o); -} - - -LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { - StkId o = index2addr(L, idx); - if (!ttisstring(o)) { - lua_lock(L); /* `luaV_tostring' may create a new string */ - if (!luaV_tostring(L, o)) { /* conversion failed? */ - if (len != NULL) *len = 0; - lua_unlock(L); - return NULL; - } - luaC_checkGC(L); - o = index2addr(L, idx); /* previous call may reallocate the stack */ - lua_unlock(L); - } - if (len != NULL) *len = tsvalue(o)->len; - return svalue(o); -} - - -LUA_API size_t lua_rawlen (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - switch (ttypenv(o)) { - case LUA_TSTRING: return tsvalue(o)->len; - case LUA_TUSERDATA: return uvalue(o)->len; - case LUA_TTABLE: return luaH_getn(hvalue(o)); - default: return 0; - } -} - - -LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - if (ttislcf(o)) return fvalue(o); - else if (ttisCclosure(o)) - return clCvalue(o)->f; - else return NULL; /* not a C function */ -} - - -LUA_API void *lua_touserdata (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - switch (ttypenv(o)) { - case LUA_TUSERDATA: return (rawuvalue(o) + 1); - case LUA_TLIGHTUSERDATA: return pvalue(o); - default: return NULL; - } -} - - -LUA_API lua_State *lua_tothread (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - return (!ttisthread(o)) ? NULL : thvalue(o); -} - - -LUA_API const void *lua_topointer (lua_State *L, int idx) { - StkId o = index2addr(L, idx); - switch (ttype(o)) { - case LUA_TTABLE: return hvalue(o); - case LUA_TLCL: return clLvalue(o); - case LUA_TCCL: return clCvalue(o); - case LUA_TLCF: return cast(void *, cast(size_t, fvalue(o))); - case LUA_TTHREAD: return thvalue(o); - case LUA_TUSERDATA: - case LUA_TLIGHTUSERDATA: - return lua_touserdata(L, idx); - default: return NULL; - } -} - - - -/* -** push functions (C -> stack) -*/ - - -LUA_API void lua_pushnil (lua_State *L) { - lua_lock(L); - setnilvalue(L->top); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { - lua_lock(L); - setnvalue(L->top, n); - luai_checknum(L, L->top, - luaG_runerror(L, "C API - attempt to push a signaling NaN")); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { - lua_lock(L); - setnvalue(L->top, cast_num(n)); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushunsigned (lua_State *L, lua_Unsigned u) { - lua_Number n; - lua_lock(L); - n = lua_unsigned2number(u); - setnvalue(L->top, n); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { - TString *ts; - lua_lock(L); - luaC_checkGC(L); - ts = luaS_newlstr(L, s, len); - setsvalue2s(L, L->top, ts); - api_incr_top(L); - lua_unlock(L); - return getstr(ts); -} - - -LUA_API const char *lua_pushstring (lua_State *L, const char *s) { - if (s == NULL) { - lua_pushnil(L); - return NULL; - } - else { - TString *ts; - lua_lock(L); - luaC_checkGC(L); - ts = luaS_new(L, s); - setsvalue2s(L, L->top, ts); - api_incr_top(L); - lua_unlock(L); - return getstr(ts); - } -} - - -LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, - va_list argp) { - const char *ret; - lua_lock(L); - luaC_checkGC(L); - ret = luaO_pushvfstring(L, fmt, argp); - lua_unlock(L); - return ret; -} - - -LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { - const char *ret; - va_list argp; - lua_lock(L); - luaC_checkGC(L); - va_start(argp, fmt); - ret = luaO_pushvfstring(L, fmt, argp); - va_end(argp); - lua_unlock(L); - return ret; -} - - -LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { - lua_lock(L); - if (n == 0) { - setfvalue(L->top, fn); - } - else { - Closure *cl; - api_checknelems(L, n); - api_check(L, n <= MAXUPVAL, "upvalue index too large"); - luaC_checkGC(L); - cl = luaF_newCclosure(L, n); - cl->c.f = fn; - L->top -= n; - while (n--) - setobj2n(L, &cl->c.upvalue[n], L->top + n); - setclCvalue(L, L->top, cl); - } - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushboolean (lua_State *L, int b) { - lua_lock(L); - setbvalue(L->top, (b != 0)); /* ensure that true is 1 */ - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { - lua_lock(L); - setpvalue(L->top, p); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API int lua_pushthread (lua_State *L) { - lua_lock(L); - setthvalue(L, L->top, L); - api_incr_top(L); - lua_unlock(L); - return (G(L)->mainthread == L); -} - - - -/* -** get functions (Lua -> stack) -*/ - - -LUA_API void lua_getglobal (lua_State *L, const char *var) { - Table *reg = hvalue(&G(L)->l_registry); - const TValue *gt; /* global table */ - lua_lock(L); - gt = luaH_getint(reg, LUA_RIDX_GLOBALS); - setsvalue2s(L, L->top++, luaS_new(L, var)); - luaV_gettable(L, gt, L->top - 1, L->top - 1); - lua_unlock(L); -} - - -LUA_API void lua_gettable (lua_State *L, int idx) { - StkId t; - lua_lock(L); - t = index2addr(L, idx); - luaV_gettable(L, t, L->top - 1, L->top - 1); - lua_unlock(L); -} - - -LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { - StkId t; - lua_lock(L); - t = index2addr(L, idx); - setsvalue2s(L, L->top, luaS_new(L, k)); - api_incr_top(L); - luaV_gettable(L, t, L->top - 1, L->top - 1); - lua_unlock(L); -} - - -LUA_API void lua_rawget (lua_State *L, int idx) { - StkId t; - lua_lock(L); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); - setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); - lua_unlock(L); -} - - -LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { - StkId t; - lua_lock(L); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); - setobj2s(L, L->top, luaH_getint(hvalue(t), n)); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_rawgetp (lua_State *L, int idx, const void *p) { - StkId t; - TValue k; - lua_lock(L); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); - setpvalue(&k, cast(void *, p)); - setobj2s(L, L->top, luaH_get(hvalue(t), &k)); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { - Table *t; - lua_lock(L); - luaC_checkGC(L); - t = luaH_new(L); - sethvalue(L, L->top, t); - api_incr_top(L); - if (narray > 0 || nrec > 0) - luaH_resize(L, t, narray, nrec); - lua_unlock(L); -} - - -LUA_API int lua_getmetatable (lua_State *L, int objindex) { - const TValue *obj; - Table *mt = NULL; - int res; - lua_lock(L); - obj = index2addr(L, objindex); - switch (ttypenv(obj)) { - case LUA_TTABLE: - mt = hvalue(obj)->metatable; - break; - case LUA_TUSERDATA: - mt = uvalue(obj)->metatable; - break; - default: - mt = G(L)->mt[ttypenv(obj)]; - break; - } - if (mt == NULL) - res = 0; - else { - sethvalue(L, L->top, mt); - api_incr_top(L); - res = 1; - } - lua_unlock(L); - return res; -} - - -LUA_API void lua_getuservalue (lua_State *L, int idx) { - StkId o; - lua_lock(L); - o = index2addr(L, idx); - api_check(L, ttisuserdata(o), "userdata expected"); - if (uvalue(o)->env) { - sethvalue(L, L->top, uvalue(o)->env); - } else - setnilvalue(L->top); - api_incr_top(L); - lua_unlock(L); -} - - -/* -** set functions (stack -> Lua) -*/ - - -LUA_API void lua_setglobal (lua_State *L, const char *var) { - Table *reg = hvalue(&G(L)->l_registry); - const TValue *gt; /* global table */ - lua_lock(L); - api_checknelems(L, 1); - gt = luaH_getint(reg, LUA_RIDX_GLOBALS); - setsvalue2s(L, L->top++, luaS_new(L, var)); - luaV_settable(L, gt, L->top - 1, L->top - 2); - L->top -= 2; /* pop value and key */ - lua_unlock(L); -} - - -LUA_API void lua_settable (lua_State *L, int idx) { - StkId t; - lua_lock(L); - api_checknelems(L, 2); - t = index2addr(L, idx); - luaV_settable(L, t, L->top - 2, L->top - 1); - L->top -= 2; /* pop index and value */ - lua_unlock(L); -} - - -LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { - StkId t; - lua_lock(L); - api_checknelems(L, 1); - t = index2addr(L, idx); - setsvalue2s(L, L->top++, luaS_new(L, k)); - luaV_settable(L, t, L->top - 1, L->top - 2); - L->top -= 2; /* pop value and key */ - lua_unlock(L); -} - - -LUA_API void lua_rawset (lua_State *L, int idx) { - StkId t; - lua_lock(L); - api_checknelems(L, 2); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); - setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); - invalidateTMcache(hvalue(t)); - luaC_barrierback(L, gcvalue(t), L->top-1); - L->top -= 2; - lua_unlock(L); -} - - -LUA_API void lua_rawseti (lua_State *L, int idx, int n) { - StkId t; - lua_lock(L); - api_checknelems(L, 1); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); - luaH_setint(L, hvalue(t), n, L->top - 1); - luaC_barrierback(L, gcvalue(t), L->top-1); - L->top--; - lua_unlock(L); -} - - -LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { - StkId t; - TValue k; - lua_lock(L); - api_checknelems(L, 1); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); - setpvalue(&k, cast(void *, p)); - setobj2t(L, luaH_set(L, hvalue(t), &k), L->top - 1); - luaC_barrierback(L, gcvalue(t), L->top - 1); - L->top--; - lua_unlock(L); -} - - -LUA_API int lua_setmetatable (lua_State *L, int objindex) { - TValue *obj; - Table *mt; - lua_lock(L); - api_checknelems(L, 1); - obj = index2addr(L, objindex); - if (ttisnil(L->top - 1)) - mt = NULL; - else { - api_check(L, ttistable(L->top - 1), "table expected"); - mt = hvalue(L->top - 1); - } - switch (ttypenv(obj)) { - case LUA_TTABLE: { - hvalue(obj)->metatable = mt; - if (mt) { - luaC_objbarrierback(L, gcvalue(obj), mt); - luaC_checkfinalizer(L, gcvalue(obj), mt); - } - break; - } - case LUA_TUSERDATA: { - uvalue(obj)->metatable = mt; - if (mt) { - luaC_objbarrier(L, rawuvalue(obj), mt); - luaC_checkfinalizer(L, gcvalue(obj), mt); - } - break; - } - default: { - G(L)->mt[ttypenv(obj)] = mt; - break; - } - } - L->top--; - lua_unlock(L); - return 1; -} - - -LUA_API void lua_setuservalue (lua_State *L, int idx) { - StkId o; - lua_lock(L); - api_checknelems(L, 1); - o = index2addr(L, idx); - api_check(L, ttisuserdata(o), "userdata expected"); - if (ttisnil(L->top - 1)) - uvalue(o)->env = NULL; - else { - api_check(L, ttistable(L->top - 1), "table expected"); - uvalue(o)->env = hvalue(L->top - 1); - luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); - } - L->top--; - lua_unlock(L); -} - - -/* -** `load' and `call' functions (run Lua code) -*/ - - -#define checkresults(L,na,nr) \ - api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ - "results from function overflow current stack size") - - -LUA_API int lua_getctx (lua_State *L, int *ctx) { - if (L->ci->callstatus & CIST_YIELDED) { - if (ctx) *ctx = L->ci->u.c.ctx; - return L->ci->u.c.status; - } - else return LUA_OK; -} - - -LUA_API void lua_callk (lua_State *L, int nargs, int nresults, int ctx, - lua_CFunction k) { - StkId func; - lua_lock(L); - api_check(L, k == NULL || !isLua(L->ci), - "cannot use continuations inside hooks"); - api_checknelems(L, nargs+1); - api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); - checkresults(L, nargs, nresults); - func = L->top - (nargs+1); - if (k != NULL && L->nny == 0) { /* need to prepare continuation? */ - L->ci->u.c.k = k; /* save continuation */ - L->ci->u.c.ctx = ctx; /* save context */ - luaD_call(L, func, nresults, 1); /* do the call */ - } - else /* no continuation or no yieldable */ - luaD_call(L, func, nresults, 0); /* just do the call */ - adjustresults(L, nresults); - lua_unlock(L); -} - - - -/* -** Execute a protected call. -*/ -struct CallS { /* data to `f_call' */ - StkId func; - int nresults; -}; - - -static void f_call (lua_State *L, void *ud) { - struct CallS *c = cast(struct CallS *, ud); - luaD_call(L, c->func, c->nresults, 0); -} - - - -LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, - int ctx, lua_CFunction k) { - struct CallS c; - int status; - ptrdiff_t func; - lua_lock(L); - api_check(L, k == NULL || !isLua(L->ci), - "cannot use continuations inside hooks"); - api_checknelems(L, nargs+1); - api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); - checkresults(L, nargs, nresults); - if (errfunc == 0) - func = 0; - else { - StkId o = index2addr(L, errfunc); - api_checkstackindex(L, errfunc, o); - func = savestack(L, o); - } - c.func = L->top - (nargs+1); /* function to be called */ - if (k == NULL || L->nny > 0) { /* no continuation or no yieldable? */ - c.nresults = nresults; /* do a 'conventional' protected call */ - status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); - } - else { /* prepare continuation (call is already protected by 'resume') */ - CallInfo *ci = L->ci; - ci->u.c.k = k; /* save continuation */ - ci->u.c.ctx = ctx; /* save context */ - /* save information for error recovery */ - ci->extra = savestack(L, c.func); - ci->u.c.old_allowhook = L->allowhook; - ci->u.c.old_errfunc = L->errfunc; - L->errfunc = func; - /* mark that function may do error recovery */ - ci->callstatus |= CIST_YPCALL; - luaD_call(L, c.func, nresults, 1); /* do the call */ - ci->callstatus &= ~CIST_YPCALL; - L->errfunc = ci->u.c.old_errfunc; - status = LUA_OK; /* if it is here, there were no errors */ - } - adjustresults(L, nresults); - lua_unlock(L); - return status; -} - - -LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, - const char *chunkname, const char *mode) { - ZIO z; - int status; - lua_lock(L); - if (!chunkname) chunkname = "?"; - luaZ_init(L, &z, reader, data); - status = luaD_protectedparser(L, &z, chunkname, mode); - if (status == LUA_OK) { /* no errors? */ - LClosure *f = clLvalue(L->top - 1); /* get newly created function */ - if (f->nupvalues == 1) { /* does it have one upvalue? */ - /* get global table from registry */ - Table *reg = hvalue(&G(L)->l_registry); - const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS); - /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ - setobj(L, f->upvals[0]->v, gt); - luaC_barrier(L, f->upvals[0], gt); - } - } - lua_unlock(L); - return status; -} - - -LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { - int status; - TValue *o; - lua_lock(L); - api_checknelems(L, 1); - o = L->top - 1; - if (isLfunction(o)) - status = luaU_dump(L, getproto(o), writer, data, 0); - else - status = 1; - lua_unlock(L); - return status; -} - - -LUA_API int lua_status (lua_State *L) { - return L->status; -} - - -/* -** Garbage-collection function -*/ - -LUA_API int lua_gc (lua_State *L, int what, int data) { - int res = 0; - global_State *g; - lua_lock(L); - g = G(L); - switch (what) { - case LUA_GCSTOP: { - g->gcrunning = 0; - break; - } - case LUA_GCRESTART: { - luaE_setdebt(g, 0); - g->gcrunning = 1; - break; - } - case LUA_GCCOLLECT: { - luaC_fullgc(L, 0); - break; - } - case LUA_GCCOUNT: { - /* GC values are expressed in Kbytes: #bytes/2^10 */ - res = cast_int(gettotalbytes(g) >> 10); - break; - } - case LUA_GCCOUNTB: { - res = cast_int(gettotalbytes(g) & 0x3ff); - break; - } - case LUA_GCSTEP: { - if (g->gckind == KGC_GEN) { /* generational mode? */ - res = (g->GCestimate == 0); /* true if it will do major collection */ - luaC_forcestep(L); /* do a single step */ - } - else { - lu_mem debt = cast(lu_mem, data) * 1024 - GCSTEPSIZE; - if (g->gcrunning) - debt += g->GCdebt; /* include current debt */ - luaE_setdebt(g, debt); - luaC_forcestep(L); - if (g->gcstate == GCSpause) /* end of cycle? */ - res = 1; /* signal it */ - } - break; - } - case LUA_GCSETPAUSE: { - res = g->gcpause; - g->gcpause = data; - break; - } - case LUA_GCSETMAJORINC: { - res = g->gcmajorinc; - g->gcmajorinc = data; - break; - } - case LUA_GCSETSTEPMUL: { - res = g->gcstepmul; - g->gcstepmul = data; - break; - } - case LUA_GCISRUNNING: { - res = g->gcrunning; - break; - } - case LUA_GCGEN: { /* change collector to generational mode */ - luaC_changemode(L, KGC_GEN); - break; - } - case LUA_GCINC: { /* change collector to incremental mode */ - luaC_changemode(L, KGC_NORMAL); - break; - } - default: res = -1; /* invalid option */ - } - lua_unlock(L); - return res; -} - - - -/* -** miscellaneous functions -*/ - - -LUA_API int lua_error (lua_State *L) { - lua_lock(L); - api_checknelems(L, 1); - luaG_errormsg(L); - /* code unreachable; will unlock when control actually leaves the kernel */ - return 0; /* to avoid warnings */ -} - - -LUA_API int lua_next (lua_State *L, int idx) { - StkId t; - int more; - lua_lock(L); - t = index2addr(L, idx); - api_check(L, ttistable(t), "table expected"); - more = luaH_next(L, hvalue(t), L->top - 1); - if (more) { - api_incr_top(L); - } - else /* no more elements */ - L->top -= 1; /* remove key */ - lua_unlock(L); - return more; -} - - -LUA_API void lua_concat (lua_State *L, int n) { - lua_lock(L); - api_checknelems(L, n); - if (n >= 2) { - luaC_checkGC(L); - luaV_concat(L, n); - } - else if (n == 0) { /* push empty string */ - setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); - api_incr_top(L); - } - /* else n == 1; nothing to do */ - lua_unlock(L); -} - - -LUA_API void lua_len (lua_State *L, int idx) { - StkId t; - lua_lock(L); - t = index2addr(L, idx); - luaV_objlen(L, L->top, t); - api_incr_top(L); - lua_unlock(L); -} - - -LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { - lua_Alloc f; - lua_lock(L); - if (ud) *ud = G(L)->ud; - f = G(L)->frealloc; - lua_unlock(L); - return f; -} - - -LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { - lua_lock(L); - G(L)->ud = ud; - G(L)->frealloc = f; - lua_unlock(L); -} - - -LUA_API void *lua_newuserdata (lua_State *L, size_t size) { - Udata *u; - lua_lock(L); - luaC_checkGC(L); - u = luaS_newudata(L, size, NULL); - setuvalue(L, L->top, u); - api_incr_top(L); - lua_unlock(L); - return u + 1; -} - - - -static const char *aux_upvalue (StkId fi, int n, TValue **val, - GCObject **owner) { - switch (ttype(fi)) { - case LUA_TCCL: { /* C closure */ - CClosure *f = clCvalue(fi); - if (!(1 <= n && n <= f->nupvalues)) return NULL; - *val = &f->upvalue[n-1]; - if (owner) *owner = obj2gco(f); - return ""; - } - case LUA_TLCL: { /* Lua closure */ - LClosure *f = clLvalue(fi); - TString *name; - Proto *p = f->p; - if (!(1 <= n && n <= p->sizeupvalues)) return NULL; - *val = f->upvals[n-1]->v; - if (owner) *owner = obj2gco(f->upvals[n - 1]); - name = p->upvalues[n-1].name; - return (name == NULL) ? "" : getstr(name); - } - default: return NULL; /* not a closure */ - } -} - - -LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { - const char *name; - TValue *val = NULL; /* to avoid warnings */ - lua_lock(L); - name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL); - if (name) { - setobj2s(L, L->top, val); - api_incr_top(L); - } - lua_unlock(L); - return name; -} - - -LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { - const char *name; - TValue *val = NULL; /* to avoid warnings */ - GCObject *owner = NULL; /* to avoid warnings */ - StkId fi; - lua_lock(L); - fi = index2addr(L, funcindex); - api_checknelems(L, 1); - name = aux_upvalue(fi, n, &val, &owner); - if (name) { - L->top--; - setobj(L, val, L->top); - luaC_barrier(L, owner, L->top); - } - lua_unlock(L); - return name; -} - - -static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { - LClosure *f; - StkId fi = index2addr(L, fidx); - api_check(L, ttisLclosure(fi), "Lua function expected"); - f = clLvalue(fi); - api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); - if (pf) *pf = f; - return &f->upvals[n - 1]; /* get its upvalue pointer */ -} - - -LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { - StkId fi = index2addr(L, fidx); - switch (ttype(fi)) { - case LUA_TLCL: { /* lua closure */ - return *getupvalref(L, fidx, n, NULL); - } - case LUA_TCCL: { /* C closure */ - CClosure *f = clCvalue(fi); - api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index"); - return &f->upvalue[n - 1]; - } - default: { - api_check(L, 0, "closure expected"); - return NULL; - } - } -} - - -LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, - int fidx2, int n2) { - LClosure *f1; - UpVal **up1 = getupvalref(L, fidx1, n1, &f1); - UpVal **up2 = getupvalref(L, fidx2, n2, NULL); - *up1 = *up2; - luaC_objbarrier(L, f1, *up2); -} - diff --git a/contrib/lua/lua/src/lapi.h b/contrib/lua/lua/src/lapi.h deleted file mode 100644 index 0909a3911d2..00000000000 --- a/contrib/lua/lua/src/lapi.h +++ /dev/null @@ -1,24 +0,0 @@ -/* -** $Id: lapi.h,v 2.7 2009/11/27 15:37:59 roberto Exp $ -** Auxiliary functions from Lua API -** See Copyright Notice in lua.h -*/ - -#ifndef lapi_h -#define lapi_h - - -#include "llimits.h" -#include "lstate.h" - -#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \ - "stack overflow");} - -#define adjustresults(L,nres) \ - { if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; } - -#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \ - "not enough elements in the stack") - - -#endif diff --git a/contrib/lua/lua/src/lauxlib.c b/contrib/lua/lua/src/lauxlib.c deleted file mode 100644 index 2e989d661b8..00000000000 --- a/contrib/lua/lua/src/lauxlib.c +++ /dev/null @@ -1,959 +0,0 @@ -/* -** $Id: lauxlib.c,v 1.248 2013/03/21 13:54:57 roberto Exp $ -** Auxiliary functions for building Lua libraries -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include -#include -#include - - -/* This file uses only the official API of Lua. -** Any function declared here could be written as an application function. -*/ - -#define lauxlib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" - - -/* -** {====================================================== -** Traceback -** ======================================================= -*/ - - -#define LEVELS1 12 /* size of the first part of the stack */ -#define LEVELS2 10 /* size of the second part of the stack */ - - - -/* -** search for 'objidx' in table at index -1. -** return 1 + string at top if find a good name. -*/ -static int findfield (lua_State *L, int objidx, int level) { - if (level == 0 || !lua_istable(L, -1)) - return 0; /* not found */ - lua_pushnil(L); /* start 'next' loop */ - while (lua_next(L, -2)) { /* for each pair in table */ - if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ - if (lua_rawequal(L, objidx, -1)) { /* found object? */ - lua_pop(L, 1); /* remove value (but keep name) */ - return 1; - } - else if (findfield(L, objidx, level - 1)) { /* try recursively */ - lua_remove(L, -2); /* remove table (but keep name) */ - lua_pushliteral(L, "."); - lua_insert(L, -2); /* place '.' between the two names */ - lua_concat(L, 3); - return 1; - } - } - lua_pop(L, 1); /* remove value */ - } - return 0; /* not found */ -} - - -static int pushglobalfuncname (lua_State *L, lua_Debug *ar) { - int top = lua_gettop(L); - lua_getinfo(L, "f", ar); /* push function */ - lua_pushglobaltable(L); - if (findfield(L, top + 1, 2)) { - lua_copy(L, -1, top + 1); /* move name to proper place */ - lua_pop(L, 2); /* remove pushed values */ - return 1; - } - else { - lua_settop(L, top); /* remove function and global table */ - return 0; - } -} - - -static void pushfuncname (lua_State *L, lua_Debug *ar) { - if (*ar->namewhat != '\0') /* is there a name? */ - lua_pushfstring(L, "function " LUA_QS, ar->name); - else if (*ar->what == 'm') /* main? */ - lua_pushliteral(L, "main chunk"); - else if (*ar->what == 'C') { - if (pushglobalfuncname(L, ar)) { - lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1)); - lua_remove(L, -2); /* remove name */ - } - else - lua_pushliteral(L, "?"); - } - else - lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); -} - - -static int countlevels (lua_State *L) { - lua_Debug ar; - int li = 1, le = 1; - /* find an upper bound */ - while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } - /* do a binary search */ - while (li < le) { - int m = (li + le)/2; - if (lua_getstack(L, m, &ar)) li = m + 1; - else le = m; - } - return le - 1; -} - - -LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, - const char *msg, int level) { - lua_Debug ar; - int top = lua_gettop(L); - int numlevels = countlevels(L1); - int mark = (numlevels > LEVELS1 + LEVELS2) ? LEVELS1 : 0; - if (msg) lua_pushfstring(L, "%s\n", msg); - lua_pushliteral(L, "stack traceback:"); - while (lua_getstack(L1, level++, &ar)) { - if (level == mark) { /* too many levels? */ - lua_pushliteral(L, "\n\t..."); /* add a '...' */ - level = numlevels - LEVELS2; /* and skip to last ones */ - } - else { - lua_getinfo(L1, "Slnt", &ar); - lua_pushfstring(L, "\n\t%s:", ar.short_src); - if (ar.currentline > 0) - lua_pushfstring(L, "%d:", ar.currentline); - lua_pushliteral(L, " in "); - pushfuncname(L, &ar); - if (ar.istailcall) - lua_pushliteral(L, "\n\t(...tail calls...)"); - lua_concat(L, lua_gettop(L) - top); - } - } - lua_concat(L, lua_gettop(L) - top); -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Error-report functions -** ======================================================= -*/ - -LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { - lua_Debug ar; - if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ - return luaL_error(L, "bad argument #%d (%s)", narg, extramsg); - lua_getinfo(L, "n", &ar); - if (strcmp(ar.namewhat, "method") == 0) { - narg--; /* do not count `self' */ - if (narg == 0) /* error is in the self argument itself? */ - return luaL_error(L, "calling " LUA_QS " on bad self (%s)", - ar.name, extramsg); - } - if (ar.name == NULL) - ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?"; - return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", - narg, ar.name, extramsg); -} - - -static int typeerror (lua_State *L, int narg, const char *tname) { - const char *msg = lua_pushfstring(L, "%s expected, got %s", - tname, luaL_typename(L, narg)); - return luaL_argerror(L, narg, msg); -} - - -static void tag_error (lua_State *L, int narg, int tag) { - typeerror(L, narg, lua_typename(L, tag)); -} - - -LUALIB_API void luaL_where (lua_State *L, int level) { - lua_Debug ar; - if (lua_getstack(L, level, &ar)) { /* check function at level */ - lua_getinfo(L, "Sl", &ar); /* get info about it */ - if (ar.currentline > 0) { /* is there info? */ - lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); - return; - } - } - lua_pushliteral(L, ""); /* else, no information available... */ -} - - -LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { - va_list argp; - va_start(argp, fmt); - luaL_where(L, 1); - lua_pushvfstring(L, fmt, argp); - va_end(argp); - lua_concat(L, 2); - return lua_error(L); -} - - -LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { - int en = errno; /* calls to Lua API may change this value */ - if (stat) { - lua_pushboolean(L, 1); - return 1; - } - else { - lua_pushnil(L); - if (fname) - lua_pushfstring(L, "%s: %s", fname, strerror(en)); - else - lua_pushstring(L, strerror(en)); - lua_pushinteger(L, en); - return 3; - } -} - - -#if !defined(inspectstat) /* { */ - -#if defined(LUA_USE_POSIX) - -#include - -/* -** use appropriate macros to interpret 'pclose' return status -*/ -#define inspectstat(stat,what) \ - if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \ - else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; } - -#else - -#define inspectstat(stat,what) /* no op */ - -#endif - -#endif /* } */ - - -LUALIB_API int luaL_execresult (lua_State *L, int stat) { - const char *what = "exit"; /* type of termination */ - if (stat == -1) /* error? */ - return luaL_fileresult(L, 0, NULL); - else { - inspectstat(stat, what); /* interpret result */ - if (*what == 'e' && stat == 0) /* successful termination? */ - lua_pushboolean(L, 1); - else - lua_pushnil(L); - lua_pushstring(L, what); - lua_pushinteger(L, stat); - return 3; /* return true/nil,what,code */ - } -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Userdata's metatable manipulation -** ======================================================= -*/ - -LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { - luaL_getmetatable(L, tname); /* try to get metatable */ - if (!lua_isnil(L, -1)) /* name already in use? */ - return 0; /* leave previous value on top, but return 0 */ - lua_pop(L, 1); - lua_newtable(L); /* create metatable */ - lua_pushvalue(L, -1); - lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ - return 1; -} - - -LUALIB_API void luaL_setmetatable (lua_State *L, const char *tname) { - luaL_getmetatable(L, tname); - lua_setmetatable(L, -2); -} - - -LUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) { - void *p = lua_touserdata(L, ud); - if (p != NULL) { /* value is a userdata? */ - if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ - luaL_getmetatable(L, tname); /* get correct metatable */ - if (!lua_rawequal(L, -1, -2)) /* not the same? */ - p = NULL; /* value is a userdata with wrong metatable */ - lua_pop(L, 2); /* remove both metatables */ - return p; - } - } - return NULL; /* value is not a userdata with a metatable */ -} - - -LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { - void *p = luaL_testudata(L, ud, tname); - if (p == NULL) typeerror(L, ud, tname); - return p; -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Argument check functions -** ======================================================= -*/ - -LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, - const char *const lst[]) { - const char *name = (def) ? luaL_optstring(L, narg, def) : - luaL_checkstring(L, narg); - int i; - for (i=0; lst[i]; i++) - if (strcmp(lst[i], name) == 0) - return i; - return luaL_argerror(L, narg, - lua_pushfstring(L, "invalid option " LUA_QS, name)); -} - - -LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) { - /* keep some extra space to run error routines, if needed */ - const int extra = LUA_MINSTACK; - if (!lua_checkstack(L, space + extra)) { - if (msg) - luaL_error(L, "stack overflow (%s)", msg); - else - luaL_error(L, "stack overflow"); - } -} - - -LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { - if (lua_type(L, narg) != t) - tag_error(L, narg, t); -} - - -LUALIB_API void luaL_checkany (lua_State *L, int narg) { - if (lua_type(L, narg) == LUA_TNONE) - luaL_argerror(L, narg, "value expected"); -} - - -LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { - const char *s = lua_tolstring(L, narg, len); - if (!s) tag_error(L, narg, LUA_TSTRING); - return s; -} - - -LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, - const char *def, size_t *len) { - if (lua_isnoneornil(L, narg)) { - if (len) - *len = (def ? strlen(def) : 0); - return def; - } - else return luaL_checklstring(L, narg, len); -} - - -LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { - int isnum; - lua_Number d = lua_tonumberx(L, narg, &isnum); - if (!isnum) - tag_error(L, narg, LUA_TNUMBER); - return d; -} - - -LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { - return luaL_opt(L, luaL_checknumber, narg, def); -} - - -LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { - int isnum; - lua_Integer d = lua_tointegerx(L, narg, &isnum); - if (!isnum) - tag_error(L, narg, LUA_TNUMBER); - return d; -} - - -LUALIB_API lua_Unsigned luaL_checkunsigned (lua_State *L, int narg) { - int isnum; - lua_Unsigned d = lua_tounsignedx(L, narg, &isnum); - if (!isnum) - tag_error(L, narg, LUA_TNUMBER); - return d; -} - - -LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, - lua_Integer def) { - return luaL_opt(L, luaL_checkinteger, narg, def); -} - - -LUALIB_API lua_Unsigned luaL_optunsigned (lua_State *L, int narg, - lua_Unsigned def) { - return luaL_opt(L, luaL_checkunsigned, narg, def); -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Generic Buffer manipulation -** ======================================================= -*/ - -/* -** check whether buffer is using a userdata on the stack as a temporary -** buffer -*/ -#define buffonstack(B) ((B)->b != (B)->initb) - - -/* -** returns a pointer to a free area with at least 'sz' bytes -*/ -LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) { - lua_State *L = B->L; - if (B->size - B->n < sz) { /* not enough space? */ - char *newbuff; - size_t newsize = B->size * 2; /* double buffer size */ - if (newsize - B->n < sz) /* not big enough? */ - newsize = B->n + sz; - if (newsize < B->n || newsize - B->n < sz) - luaL_error(L, "buffer too large"); - /* create larger buffer */ - newbuff = (char *)lua_newuserdata(L, newsize * sizeof(char)); - /* move content to new buffer */ - memcpy(newbuff, B->b, B->n * sizeof(char)); - if (buffonstack(B)) - lua_remove(L, -2); /* remove old buffer */ - B->b = newbuff; - B->size = newsize; - } - return &B->b[B->n]; -} - - -LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { - char *b = luaL_prepbuffsize(B, l); - memcpy(b, s, l * sizeof(char)); - luaL_addsize(B, l); -} - - -LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { - luaL_addlstring(B, s, strlen(s)); -} - - -LUALIB_API void luaL_pushresult (luaL_Buffer *B) { - lua_State *L = B->L; - lua_pushlstring(L, B->b, B->n); - if (buffonstack(B)) - lua_remove(L, -2); /* remove old buffer */ -} - - -LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) { - luaL_addsize(B, sz); - luaL_pushresult(B); -} - - -LUALIB_API void luaL_addvalue (luaL_Buffer *B) { - lua_State *L = B->L; - size_t l; - const char *s = lua_tolstring(L, -1, &l); - if (buffonstack(B)) - lua_insert(L, -2); /* put value below buffer */ - luaL_addlstring(B, s, l); - lua_remove(L, (buffonstack(B)) ? -2 : -1); /* remove value */ -} - - -LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { - B->L = L; - B->b = B->initb; - B->n = 0; - B->size = LUAL_BUFFERSIZE; -} - - -LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) { - luaL_buffinit(L, B); - return luaL_prepbuffsize(B, sz); -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Reference system -** ======================================================= -*/ - -/* index of free-list header */ -#define freelist 0 - - -LUALIB_API int luaL_ref (lua_State *L, int t) { - int ref; - if (lua_isnil(L, -1)) { - lua_pop(L, 1); /* remove from stack */ - return LUA_REFNIL; /* `nil' has a unique fixed reference */ - } - t = lua_absindex(L, t); - lua_rawgeti(L, t, freelist); /* get first free element */ - ref = (int)lua_tointeger(L, -1); /* ref = t[freelist] */ - lua_pop(L, 1); /* remove it from stack */ - if (ref != 0) { /* any free element? */ - lua_rawgeti(L, t, ref); /* remove it from list */ - lua_rawseti(L, t, freelist); /* (t[freelist] = t[ref]) */ - } - else /* no free elements */ - ref = (int)lua_rawlen(L, t) + 1; /* get a new reference */ - lua_rawseti(L, t, ref); - return ref; -} - - -LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { - if (ref >= 0) { - t = lua_absindex(L, t); - lua_rawgeti(L, t, freelist); - lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */ - lua_pushinteger(L, ref); - lua_rawseti(L, t, freelist); /* t[freelist] = ref */ - } -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Load functions -** ======================================================= -*/ - -typedef struct LoadF { - int n; /* number of pre-read characters */ - FILE *f; /* file being read */ - char buff[LUAL_BUFFERSIZE]; /* area for reading file */ -} LoadF; - - -static const char *getF (lua_State *L, void *ud, size_t *size) { - LoadF *lf = (LoadF *)ud; - (void)L; /* not used */ - if (lf->n > 0) { /* are there pre-read characters to be read? */ - *size = lf->n; /* return them (chars already in buffer) */ - lf->n = 0; /* no more pre-read characters */ - } - else { /* read a block from file */ - /* 'fread' can return > 0 *and* set the EOF flag. If next call to - 'getF' called 'fread', it might still wait for user input. - The next check avoids this problem. */ - if (feof(lf->f)) return NULL; - *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); /* read block */ - } - return lf->buff; -} - - -static int errfile (lua_State *L, const char *what, int fnameindex) { - const char *serr = strerror(errno); - const char *filename = lua_tostring(L, fnameindex) + 1; - lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); - lua_remove(L, fnameindex); - return LUA_ERRFILE; -} - - -static int skipBOM (LoadF *lf) { - const char *p = "\xEF\xBB\xBF"; /* Utf8 BOM mark */ - int c; - lf->n = 0; - do { - c = getc(lf->f); - if (c == EOF || c != *(const unsigned char *)p++) return c; - lf->buff[lf->n++] = c; /* to be read by the parser */ - } while (*p != '\0'); - lf->n = 0; /* prefix matched; discard it */ - return getc(lf->f); /* return next character */ -} - - -/* -** reads the first character of file 'f' and skips an optional BOM mark -** in its beginning plus its first line if it starts with '#'. Returns -** true if it skipped the first line. In any case, '*cp' has the -** first "valid" character of the file (after the optional BOM and -** a first-line comment). -*/ -static int skipcomment (LoadF *lf, int *cp) { - int c = *cp = skipBOM(lf); - if (c == '#') { /* first line is a comment (Unix exec. file)? */ - do { /* skip first line */ - c = getc(lf->f); - } while (c != EOF && c != '\n') ; - *cp = getc(lf->f); /* skip end-of-line, if present */ - return 1; /* there was a comment */ - } - else return 0; /* no comment */ -} - - -LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, - const char *mode) { - LoadF lf; - int status, readstatus; - int c; - int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ - if (filename == NULL) { - lua_pushliteral(L, "=stdin"); - lf.f = stdin; - } - else { - lua_pushfstring(L, "@%s", filename); - lf.f = fopen(filename, "r"); - if (lf.f == NULL) return errfile(L, "open", fnameindex); - } - if (skipcomment(&lf, &c)) /* read initial portion */ - lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ - if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ - lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ - if (lf.f == NULL) return errfile(L, "reopen", fnameindex); - skipcomment(&lf, &c); /* re-read initial portion */ - } - if (c != EOF) - lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ - status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode); - readstatus = ferror(lf.f); - if (filename) fclose(lf.f); /* close file (even in case of errors) */ - if (readstatus) { - lua_settop(L, fnameindex); /* ignore results from `lua_load' */ - return errfile(L, "read", fnameindex); - } - lua_remove(L, fnameindex); - return status; -} - - -typedef struct LoadS { - const char *s; - size_t size; -} LoadS; - - -static const char *getS (lua_State *L, void *ud, size_t *size) { - LoadS *ls = (LoadS *)ud; - (void)L; /* not used */ - if (ls->size == 0) return NULL; - *size = ls->size; - ls->size = 0; - return ls->s; -} - - -LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size, - const char *name, const char *mode) { - LoadS ls; - ls.s = buff; - ls.size = size; - return lua_load(L, getS, &ls, name, mode); -} - - -LUALIB_API int luaL_loadstring (lua_State *L, const char *s) { - return luaL_loadbuffer(L, s, strlen(s), s); -} - -/* }====================================================== */ - - - -LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { - if (!lua_getmetatable(L, obj)) /* no metatable? */ - return 0; - lua_pushstring(L, event); - lua_rawget(L, -2); - if (lua_isnil(L, -1)) { - lua_pop(L, 2); /* remove metatable and metafield */ - return 0; - } - else { - lua_remove(L, -2); /* remove only metatable */ - return 1; - } -} - - -LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { - obj = lua_absindex(L, obj); - if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ - return 0; - lua_pushvalue(L, obj); - lua_call(L, 1, 1); - return 1; -} - - -LUALIB_API int luaL_len (lua_State *L, int idx) { - int l; - int isnum; - lua_len(L, idx); - l = (int)lua_tointegerx(L, -1, &isnum); - if (!isnum) - luaL_error(L, "object length is not a number"); - lua_pop(L, 1); /* remove object */ - return l; -} - - -LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { - if (!luaL_callmeta(L, idx, "__tostring")) { /* no metafield? */ - switch (lua_type(L, idx)) { - case LUA_TNUMBER: - case LUA_TSTRING: - lua_pushvalue(L, idx); - break; - case LUA_TBOOLEAN: - lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false")); - break; - case LUA_TNIL: - lua_pushliteral(L, "nil"); - break; - default: - lua_pushfstring(L, "%s: %p", luaL_typename(L, idx), - lua_topointer(L, idx)); - break; - } - } - return lua_tolstring(L, -1, len); -} - - -/* -** {====================================================== -** Compatibility with 5.1 module functions -** ======================================================= -*/ -#if defined(LUA_COMPAT_MODULE) - -static const char *luaL_findtable (lua_State *L, int idx, - const char *fname, int szhint) { - const char *e; - if (idx) lua_pushvalue(L, idx); - do { - e = strchr(fname, '.'); - if (e == NULL) e = fname + strlen(fname); - lua_pushlstring(L, fname, e - fname); - lua_rawget(L, -2); - if (lua_isnil(L, -1)) { /* no such field? */ - lua_pop(L, 1); /* remove this nil */ - lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ - lua_pushlstring(L, fname, e - fname); - lua_pushvalue(L, -2); - lua_settable(L, -4); /* set new table into field */ - } - else if (!lua_istable(L, -1)) { /* field has a non-table value? */ - lua_pop(L, 2); /* remove table and value */ - return fname; /* return problematic part of the name */ - } - lua_remove(L, -2); /* remove previous table */ - fname = e + 1; - } while (*e == '.'); - return NULL; -} - - -/* -** Count number of elements in a luaL_Reg list. -*/ -static int libsize (const luaL_Reg *l) { - int size = 0; - for (; l && l->name; l++) size++; - return size; -} - - -/* -** Find or create a module table with a given name. The function -** first looks at the _LOADED table and, if that fails, try a -** global variable with that name. In any case, leaves on the stack -** the module table. -*/ -LUALIB_API void luaL_pushmodule (lua_State *L, const char *modname, - int sizehint) { - luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); /* get _LOADED table */ - lua_getfield(L, -1, modname); /* get _LOADED[modname] */ - if (!lua_istable(L, -1)) { /* not found? */ - lua_pop(L, 1); /* remove previous result */ - /* try global variable (and create one if it does not exist) */ - lua_pushglobaltable(L); - if (luaL_findtable(L, 0, modname, sizehint) != NULL) - luaL_error(L, "name conflict for module " LUA_QS, modname); - lua_pushvalue(L, -1); - lua_setfield(L, -3, modname); /* _LOADED[modname] = new table */ - } - lua_remove(L, -2); /* remove _LOADED table */ -} - - -LUALIB_API void luaL_openlib (lua_State *L, const char *libname, - const luaL_Reg *l, int nup) { - luaL_checkversion(L); - if (libname) { - luaL_pushmodule(L, libname, libsize(l)); /* get/create library table */ - lua_insert(L, -(nup + 1)); /* move library table to below upvalues */ - } - if (l) - luaL_setfuncs(L, l, nup); - else - lua_pop(L, nup); /* remove upvalues */ -} - -#endif -/* }====================================================== */ - -/* -** set functions from list 'l' into table at top - 'nup'; each -** function gets the 'nup' elements at the top as upvalues. -** Returns with only the table at the stack. -*/ -LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { - luaL_checkversion(L); - luaL_checkstack(L, nup, "too many upvalues"); - for (; l->name != NULL; l++) { /* fill the table with given functions */ - int i; - for (i = 0; i < nup; i++) /* copy upvalues to the top */ - lua_pushvalue(L, -nup); - lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ - lua_setfield(L, -(nup + 2), l->name); - } - lua_pop(L, nup); /* remove upvalues */ -} - - -/* -** ensure that stack[idx][fname] has a table and push that table -** into the stack -*/ -LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) { - lua_getfield(L, idx, fname); - if (lua_istable(L, -1)) return 1; /* table already there */ - else { - lua_pop(L, 1); /* remove previous result */ - idx = lua_absindex(L, idx); - lua_newtable(L); - lua_pushvalue(L, -1); /* copy to be left at top */ - lua_setfield(L, idx, fname); /* assign new table to field */ - return 0; /* false, because did not find table there */ - } -} - - -/* -** stripped-down 'require'. Calls 'openf' to open a module, -** registers the result in 'package.loaded' table and, if 'glb' -** is true, also registers the result in the global table. -** Leaves resulting module on the top. -*/ -LUALIB_API void luaL_requiref (lua_State *L, const char *modname, - lua_CFunction openf, int glb) { - lua_pushcfunction(L, openf); - lua_pushstring(L, modname); /* argument to open function */ - lua_call(L, 1, 1); /* open module */ - luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); - lua_pushvalue(L, -2); /* make copy of module (call result) */ - lua_setfield(L, -2, modname); /* _LOADED[modname] = module */ - lua_pop(L, 1); /* remove _LOADED table */ - if (glb) { - lua_pushvalue(L, -1); /* copy of 'mod' */ - lua_setglobal(L, modname); /* _G[modname] = module */ - } -} - - -LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, - const char *r) { - const char *wild; - size_t l = strlen(p); - luaL_Buffer b; - luaL_buffinit(L, &b); - while ((wild = strstr(s, p)) != NULL) { - luaL_addlstring(&b, s, wild - s); /* push prefix */ - luaL_addstring(&b, r); /* push replacement in place of pattern */ - s = wild + l; /* continue after `p' */ - } - luaL_addstring(&b, s); /* push last suffix */ - luaL_pushresult(&b); - return lua_tostring(L, -1); -} - - -static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { - (void)ud; (void)osize; /* not used */ - if (nsize == 0) { - free(ptr); - return NULL; - } - else - return realloc(ptr, nsize); -} - - -static int panic (lua_State *L) { - luai_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n", - lua_tostring(L, -1)); - return 0; /* return to Lua to abort */ -} - - -LUALIB_API lua_State *luaL_newstate (void) { - lua_State *L = lua_newstate(l_alloc, NULL); - if (L) lua_atpanic(L, &panic); - return L; -} - - -LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver) { - const lua_Number *v = lua_version(L); - if (v != lua_version(NULL)) - luaL_error(L, "multiple Lua VMs detected"); - else if (*v != ver) - luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", - ver, *v); - /* check conversions number -> integer types */ - lua_pushnumber(L, -(lua_Number)0x1234); - if (lua_tointeger(L, -1) != -0x1234 || - lua_tounsigned(L, -1) != (lua_Unsigned)-0x1234) - luaL_error(L, "bad conversion number->int;" - " must recompile Lua with proper settings"); - lua_pop(L, 1); -} - diff --git a/contrib/lua/lua/src/lauxlib.h b/contrib/lua/lua/src/lauxlib.h deleted file mode 100644 index ac4d15fbb94..00000000000 --- a/contrib/lua/lua/src/lauxlib.h +++ /dev/null @@ -1,212 +0,0 @@ -/* -** $Id: lauxlib.h,v 1.120 2011/11/29 15:55:08 roberto Exp $ -** Auxiliary functions for building Lua libraries -** See Copyright Notice in lua.h -*/ - - -#ifndef lauxlib_h -#define lauxlib_h - - -#include -#include - -#include "lua.h" - - - -/* extra error code for `luaL_load' */ -#define LUA_ERRFILE (LUA_ERRERR+1) - - -typedef struct luaL_Reg { - const char *name; - lua_CFunction func; -} luaL_Reg; - - -LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver); -#define luaL_checkversion(L) luaL_checkversion_(L, LUA_VERSION_NUM) - -LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); -LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); -LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len); -LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); -LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, - size_t *l); -LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, - const char *def, size_t *l); -LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); -LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); - -LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); -LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, - lua_Integer def); -LUALIB_API lua_Unsigned (luaL_checkunsigned) (lua_State *L, int numArg); -LUALIB_API lua_Unsigned (luaL_optunsigned) (lua_State *L, int numArg, - lua_Unsigned def); - -LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); -LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); -LUALIB_API void (luaL_checkany) (lua_State *L, int narg); - -LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); -LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname); -LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname); -LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); - -LUALIB_API void (luaL_where) (lua_State *L, int lvl); -LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); - -LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, - const char *const lst[]); - -LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname); -LUALIB_API int (luaL_execresult) (lua_State *L, int stat); - -/* pre-defined references */ -#define LUA_NOREF (-2) -#define LUA_REFNIL (-1) - -LUALIB_API int (luaL_ref) (lua_State *L, int t); -LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); - -LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, - const char *mode); - -#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) - -LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, - const char *name, const char *mode); -LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); - -LUALIB_API lua_State *(luaL_newstate) (void); - -LUALIB_API int (luaL_len) (lua_State *L, int idx); - -LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, - const char *r); - -LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); - -LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname); - -LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1, - const char *msg, int level); - -LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, - lua_CFunction openf, int glb); - -/* -** =============================================================== -** some useful macros -** =============================================================== -*/ - - -#define luaL_newlibtable(L,l) \ - lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) - -#define luaL_newlib(L,l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) - -#define luaL_argcheck(L, cond,numarg,extramsg) \ - ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) -#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) -#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) -#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) -#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) -#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) -#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) - -#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) - -#define luaL_dofile(L, fn) \ - (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) - -#define luaL_dostring(L, s) \ - (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) - -#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) - -#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) - -#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) - - -/* -** {====================================================== -** Generic Buffer manipulation -** ======================================================= -*/ - -typedef struct luaL_Buffer { - char *b; /* buffer address */ - size_t size; /* buffer size */ - size_t n; /* number of characters in buffer */ - lua_State *L; - char initb[LUAL_BUFFERSIZE]; /* initial buffer */ -} luaL_Buffer; - - -#define luaL_addchar(B,c) \ - ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \ - ((B)->b[(B)->n++] = (c))) - -#define luaL_addsize(B,s) ((B)->n += (s)) - -LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); -LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); -LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); -LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); -LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); -LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); -LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz); -LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz); - -#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) - -/* }====================================================== */ - - - -/* -** {====================================================== -** File handles for IO library -** ======================================================= -*/ - -/* -** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and -** initial structure 'luaL_Stream' (it may contain other fields -** after that initial structure). -*/ - -#define LUA_FILEHANDLE "FILE*" - - -typedef struct luaL_Stream { - FILE *f; /* stream (NULL for incompletely created streams) */ - lua_CFunction closef; /* to close stream (NULL for closed streams) */ -} luaL_Stream; - -/* }====================================================== */ - - - -/* compatibility with old module system */ -#if defined(LUA_COMPAT_MODULE) - -LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname, - int sizehint); -LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname, - const luaL_Reg *l, int nup); - -#define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0)) - -#endif - - -#endif - - diff --git a/contrib/lua/lua/src/lbaselib.c b/contrib/lua/lua/src/lbaselib.c deleted file mode 100644 index 540e9a5cc03..00000000000 --- a/contrib/lua/lua/src/lbaselib.c +++ /dev/null @@ -1,458 +0,0 @@ -/* -** $Id: lbaselib.c,v 1.276 2013/02/21 13:44:53 roberto Exp $ -** Basic library -** See Copyright Notice in lua.h -*/ - - - -#include -#include -#include -#include - -#define lbaselib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -static int luaB_print (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - int i; - lua_getglobal(L, "tostring"); - for (i=1; i<=n; i++) { - const char *s; - size_t l; - lua_pushvalue(L, -1); /* function to be called */ - lua_pushvalue(L, i); /* value to print */ - lua_call(L, 1, 1); - s = lua_tolstring(L, -1, &l); /* get result */ - if (s == NULL) - return luaL_error(L, - LUA_QL("tostring") " must return a string to " LUA_QL("print")); - if (i>1) luai_writestring("\t", 1); - luai_writestring(s, l); - lua_pop(L, 1); /* pop result */ - } - luai_writeline(); - return 0; -} - - -#define SPACECHARS " \f\n\r\t\v" - -static int luaB_tonumber (lua_State *L) { - if (lua_isnoneornil(L, 2)) { /* standard conversion */ - int isnum; - lua_Number n = lua_tonumberx(L, 1, &isnum); - if (isnum) { - lua_pushnumber(L, n); - return 1; - } /* else not a number; must be something */ - luaL_checkany(L, 1); - } - else { - size_t l; - const char *s = luaL_checklstring(L, 1, &l); - const char *e = s + l; /* end point for 's' */ - int base = luaL_checkint(L, 2); - int neg = 0; - luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); - s += strspn(s, SPACECHARS); /* skip initial spaces */ - if (*s == '-') { s++; neg = 1; } /* handle signal */ - else if (*s == '+') s++; - if (isalnum((unsigned char)*s)) { - lua_Number n = 0; - do { - int digit = (isdigit((unsigned char)*s)) ? *s - '0' - : toupper((unsigned char)*s) - 'A' + 10; - if (digit >= base) break; /* invalid numeral; force a fail */ - n = n * (lua_Number)base + (lua_Number)digit; - s++; - } while (isalnum((unsigned char)*s)); - s += strspn(s, SPACECHARS); /* skip trailing spaces */ - if (s == e) { /* no invalid trailing characters? */ - lua_pushnumber(L, (neg) ? -n : n); - return 1; - } /* else not a number */ - } /* else not a number */ - } - lua_pushnil(L); /* not a number */ - return 1; -} - - -static int luaB_error (lua_State *L) { - int level = luaL_optint(L, 2, 1); - lua_settop(L, 1); - if (lua_isstring(L, 1) && level > 0) { /* add extra information? */ - luaL_where(L, level); - lua_pushvalue(L, 1); - lua_concat(L, 2); - } - return lua_error(L); -} - - -static int luaB_getmetatable (lua_State *L) { - luaL_checkany(L, 1); - if (!lua_getmetatable(L, 1)) { - lua_pushnil(L); - return 1; /* no metatable */ - } - luaL_getmetafield(L, 1, "__metatable"); - return 1; /* returns either __metatable field (if present) or metatable */ -} - - -static int luaB_setmetatable (lua_State *L) { - int t = lua_type(L, 2); - luaL_checktype(L, 1, LUA_TTABLE); - luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, - "nil or table expected"); - if (luaL_getmetafield(L, 1, "__metatable")) - return luaL_error(L, "cannot change a protected metatable"); - lua_settop(L, 2); - lua_setmetatable(L, 1); - return 1; -} - - -static int luaB_rawequal (lua_State *L) { - luaL_checkany(L, 1); - luaL_checkany(L, 2); - lua_pushboolean(L, lua_rawequal(L, 1, 2)); - return 1; -} - - -static int luaB_rawlen (lua_State *L) { - int t = lua_type(L, 1); - luaL_argcheck(L, t == LUA_TTABLE || t == LUA_TSTRING, 1, - "table or string expected"); - lua_pushinteger(L, lua_rawlen(L, 1)); - return 1; -} - - -static int luaB_rawget (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checkany(L, 2); - lua_settop(L, 2); - lua_rawget(L, 1); - return 1; -} - -static int luaB_rawset (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checkany(L, 2); - luaL_checkany(L, 3); - lua_settop(L, 3); - lua_rawset(L, 1); - return 1; -} - - -static int luaB_collectgarbage (lua_State *L) { - static const char *const opts[] = {"stop", "restart", "collect", - "count", "step", "setpause", "setstepmul", - "setmajorinc", "isrunning", "generational", "incremental", NULL}; - static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, - LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, - LUA_GCSETMAJORINC, LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC}; - int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; - int ex = luaL_optint(L, 2, 0); - int res = lua_gc(L, o, ex); - switch (o) { - case LUA_GCCOUNT: { - int b = lua_gc(L, LUA_GCCOUNTB, 0); - lua_pushnumber(L, res + ((lua_Number)b/1024)); - lua_pushinteger(L, b); - return 2; - } - case LUA_GCSTEP: case LUA_GCISRUNNING: { - lua_pushboolean(L, res); - return 1; - } - default: { - lua_pushinteger(L, res); - return 1; - } - } -} - - -static int luaB_type (lua_State *L) { - luaL_checkany(L, 1); - lua_pushstring(L, luaL_typename(L, 1)); - return 1; -} - - -static int pairsmeta (lua_State *L, const char *method, int iszero, - lua_CFunction iter) { - if (!luaL_getmetafield(L, 1, method)) { /* no metamethod? */ - luaL_checktype(L, 1, LUA_TTABLE); /* argument must be a table */ - lua_pushcfunction(L, iter); /* will return generator, */ - lua_pushvalue(L, 1); /* state, */ - if (iszero) lua_pushinteger(L, 0); /* and initial value */ - else lua_pushnil(L); - } - else { - lua_pushvalue(L, 1); /* argument 'self' to metamethod */ - lua_call(L, 1, 3); /* get 3 values from metamethod */ - } - return 3; -} - - -static int luaB_next (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - lua_settop(L, 2); /* create a 2nd argument if there isn't one */ - if (lua_next(L, 1)) - return 2; - else { - lua_pushnil(L); - return 1; - } -} - - -static int luaB_pairs (lua_State *L) { - return pairsmeta(L, "__pairs", 0, luaB_next); -} - - -static int ipairsaux (lua_State *L) { - int i = luaL_checkint(L, 2); - luaL_checktype(L, 1, LUA_TTABLE); - i++; /* next value */ - lua_pushinteger(L, i); - lua_rawgeti(L, 1, i); - return (lua_isnil(L, -1)) ? 1 : 2; -} - - -static int luaB_ipairs (lua_State *L) { - return pairsmeta(L, "__ipairs", 1, ipairsaux); -} - - -static int load_aux (lua_State *L, int status, int envidx) { - if (status == LUA_OK) { - if (envidx != 0) { /* 'env' parameter? */ - lua_pushvalue(L, envidx); /* environment for loaded function */ - if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */ - lua_pop(L, 1); /* remove 'env' if not used by previous call */ - } - return 1; - } - else { /* error (message is on top of the stack) */ - lua_pushnil(L); - lua_insert(L, -2); /* put before error message */ - return 2; /* return nil plus error message */ - } -} - - -static int luaB_loadfile (lua_State *L) { - const char *fname = luaL_optstring(L, 1, NULL); - const char *mode = luaL_optstring(L, 2, NULL); - int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */ - int status = luaL_loadfilex(L, fname, mode); - return load_aux(L, status, env); -} - - -/* -** {====================================================== -** Generic Read function -** ======================================================= -*/ - - -/* -** reserved slot, above all arguments, to hold a copy of the returned -** string to avoid it being collected while parsed. 'load' has four -** optional arguments (chunk, source name, mode, and environment). -*/ -#define RESERVEDSLOT 5 - - -/* -** Reader for generic `load' function: `lua_load' uses the -** stack for internal stuff, so the reader cannot change the -** stack top. Instead, it keeps its resulting string in a -** reserved slot inside the stack. -*/ -static const char *generic_reader (lua_State *L, void *ud, size_t *size) { - (void)(ud); /* not used */ - luaL_checkstack(L, 2, "too many nested functions"); - lua_pushvalue(L, 1); /* get function */ - lua_call(L, 0, 1); /* call it */ - if (lua_isnil(L, -1)) { - lua_pop(L, 1); /* pop result */ - *size = 0; - return NULL; - } - else if (!lua_isstring(L, -1)) - luaL_error(L, "reader function must return a string"); - lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ - return lua_tolstring(L, RESERVEDSLOT, size); -} - - -static int luaB_load (lua_State *L) { - int status; - size_t l; - const char *s = lua_tolstring(L, 1, &l); - const char *mode = luaL_optstring(L, 3, "bt"); - int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */ - if (s != NULL) { /* loading a string? */ - const char *chunkname = luaL_optstring(L, 2, s); - status = luaL_loadbufferx(L, s, l, chunkname, mode); - } - else { /* loading from a reader function */ - const char *chunkname = luaL_optstring(L, 2, "=(load)"); - luaL_checktype(L, 1, LUA_TFUNCTION); - lua_settop(L, RESERVEDSLOT); /* create reserved slot */ - status = lua_load(L, generic_reader, NULL, chunkname, mode); - } - return load_aux(L, status, env); -} - -/* }====================================================== */ - - -static int dofilecont (lua_State *L) { - return lua_gettop(L) - 1; -} - - -static int luaB_dofile (lua_State *L) { - const char *fname = luaL_optstring(L, 1, NULL); - lua_settop(L, 1); - if (luaL_loadfile(L, fname) != LUA_OK) - return lua_error(L); - lua_callk(L, 0, LUA_MULTRET, 0, dofilecont); - return dofilecont(L); -} - - -static int luaB_assert (lua_State *L) { - if (!lua_toboolean(L, 1)) - return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); - return lua_gettop(L); -} - - -static int luaB_select (lua_State *L) { - int n = lua_gettop(L); - if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { - lua_pushinteger(L, n-1); - return 1; - } - else { - int i = luaL_checkint(L, 1); - if (i < 0) i = n + i; - else if (i > n) i = n; - luaL_argcheck(L, 1 <= i, 1, "index out of range"); - return n - i; - } -} - - -static int finishpcall (lua_State *L, int status) { - if (!lua_checkstack(L, 1)) { /* no space for extra boolean? */ - lua_settop(L, 0); /* create space for return values */ - lua_pushboolean(L, 0); - lua_pushstring(L, "stack overflow"); - return 2; /* return false, msg */ - } - lua_pushboolean(L, status); /* first result (status) */ - lua_replace(L, 1); /* put first result in first slot */ - return lua_gettop(L); -} - - -static int pcallcont (lua_State *L) { - int status = lua_getctx(L, NULL); - return finishpcall(L, (status == LUA_YIELD)); -} - - -static int luaB_pcall (lua_State *L) { - int status; - luaL_checkany(L, 1); - lua_pushnil(L); - lua_insert(L, 1); /* create space for status result */ - status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, pcallcont); - return finishpcall(L, (status == LUA_OK)); -} - - -static int luaB_xpcall (lua_State *L) { - int status; - int n = lua_gettop(L); - luaL_argcheck(L, n >= 2, 2, "value expected"); - lua_pushvalue(L, 1); /* exchange function... */ - lua_copy(L, 2, 1); /* ...and error handler */ - lua_replace(L, 2); - status = lua_pcallk(L, n - 2, LUA_MULTRET, 1, 0, pcallcont); - return finishpcall(L, (status == LUA_OK)); -} - - -static int luaB_tostring (lua_State *L) { - luaL_checkany(L, 1); - luaL_tolstring(L, 1, NULL); - return 1; -} - - -static const luaL_Reg base_funcs[] = { - {"assert", luaB_assert}, - {"collectgarbage", luaB_collectgarbage}, - {"dofile", luaB_dofile}, - {"error", luaB_error}, - {"getmetatable", luaB_getmetatable}, - {"ipairs", luaB_ipairs}, - {"loadfile", luaB_loadfile}, - {"load", luaB_load}, -#if defined(LUA_COMPAT_LOADSTRING) - {"loadstring", luaB_load}, -#endif - {"next", luaB_next}, - {"pairs", luaB_pairs}, - {"pcall", luaB_pcall}, - {"print", luaB_print}, - {"rawequal", luaB_rawequal}, - {"rawlen", luaB_rawlen}, - {"rawget", luaB_rawget}, - {"rawset", luaB_rawset}, - {"select", luaB_select}, - {"setmetatable", luaB_setmetatable}, - {"tonumber", luaB_tonumber}, - {"tostring", luaB_tostring}, - {"type", luaB_type}, - {"xpcall", luaB_xpcall}, - {NULL, NULL} -}; - - -LUAMOD_API int luaopen_base (lua_State *L) { - /* set global _G */ - lua_pushglobaltable(L); - lua_pushglobaltable(L); - lua_setfield(L, -2, "_G"); - /* open lib into global table */ - luaL_setfuncs(L, base_funcs, 0); - lua_pushliteral(L, LUA_VERSION); - lua_setfield(L, -2, "_VERSION"); /* set global _VERSION */ - return 1; -} - diff --git a/contrib/lua/lua/src/lbitlib.c b/contrib/lua/lua/src/lbitlib.c deleted file mode 100644 index 9637532e3d8..00000000000 --- a/contrib/lua/lua/src/lbitlib.c +++ /dev/null @@ -1,211 +0,0 @@ -/* -** $Id: lbitlib.c,v 1.18 2013/03/19 13:19:12 roberto Exp $ -** Standard library for bitwise operations -** See Copyright Notice in lua.h -*/ - -#define lbitlib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -/* number of bits to consider in a number */ -#if !defined(LUA_NBITS) -#define LUA_NBITS 32 -#endif - - -#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1)) - -/* macro to trim extra bits */ -#define trim(x) ((x) & ALLONES) - - -/* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */ -#define mask(n) (~((ALLONES << 1) << ((n) - 1))) - - -typedef lua_Unsigned b_uint; - - - -static b_uint andaux (lua_State *L) { - int i, n = lua_gettop(L); - b_uint r = ~(b_uint)0; - for (i = 1; i <= n; i++) - r &= luaL_checkunsigned(L, i); - return trim(r); -} - - -static int b_and (lua_State *L) { - b_uint r = andaux(L); - lua_pushunsigned(L, r); - return 1; -} - - -static int b_test (lua_State *L) { - b_uint r = andaux(L); - lua_pushboolean(L, r != 0); - return 1; -} - - -static int b_or (lua_State *L) { - int i, n = lua_gettop(L); - b_uint r = 0; - for (i = 1; i <= n; i++) - r |= luaL_checkunsigned(L, i); - lua_pushunsigned(L, trim(r)); - return 1; -} - - -static int b_xor (lua_State *L) { - int i, n = lua_gettop(L); - b_uint r = 0; - for (i = 1; i <= n; i++) - r ^= luaL_checkunsigned(L, i); - lua_pushunsigned(L, trim(r)); - return 1; -} - - -static int b_not (lua_State *L) { - b_uint r = ~luaL_checkunsigned(L, 1); - lua_pushunsigned(L, trim(r)); - return 1; -} - - -static int b_shift (lua_State *L, b_uint r, int i) { - if (i < 0) { /* shift right? */ - i = -i; - r = trim(r); - if (i >= LUA_NBITS) r = 0; - else r >>= i; - } - else { /* shift left */ - if (i >= LUA_NBITS) r = 0; - else r <<= i; - r = trim(r); - } - lua_pushunsigned(L, r); - return 1; -} - - -static int b_lshift (lua_State *L) { - return b_shift(L, luaL_checkunsigned(L, 1), luaL_checkint(L, 2)); -} - - -static int b_rshift (lua_State *L) { - return b_shift(L, luaL_checkunsigned(L, 1), -luaL_checkint(L, 2)); -} - - -static int b_arshift (lua_State *L) { - b_uint r = luaL_checkunsigned(L, 1); - int i = luaL_checkint(L, 2); - if (i < 0 || !(r & ((b_uint)1 << (LUA_NBITS - 1)))) - return b_shift(L, r, -i); - else { /* arithmetic shift for 'negative' number */ - if (i >= LUA_NBITS) r = ALLONES; - else - r = trim((r >> i) | ~(~(b_uint)0 >> i)); /* add signal bit */ - lua_pushunsigned(L, r); - return 1; - } -} - - -static int b_rot (lua_State *L, int i) { - b_uint r = luaL_checkunsigned(L, 1); - i &= (LUA_NBITS - 1); /* i = i % NBITS */ - r = trim(r); - r = (r << i) | (r >> (LUA_NBITS - i)); - lua_pushunsigned(L, trim(r)); - return 1; -} - - -static int b_lrot (lua_State *L) { - return b_rot(L, luaL_checkint(L, 2)); -} - - -static int b_rrot (lua_State *L) { - return b_rot(L, -luaL_checkint(L, 2)); -} - - -/* -** get field and width arguments for field-manipulation functions, -** checking whether they are valid. -** ('luaL_error' called without 'return' to avoid later warnings about -** 'width' being used uninitialized.) -*/ -static int fieldargs (lua_State *L, int farg, int *width) { - int f = luaL_checkint(L, farg); - int w = luaL_optint(L, farg + 1, 1); - luaL_argcheck(L, 0 <= f, farg, "field cannot be negative"); - luaL_argcheck(L, 0 < w, farg + 1, "width must be positive"); - if (f + w > LUA_NBITS) - luaL_error(L, "trying to access non-existent bits"); - *width = w; - return f; -} - - -static int b_extract (lua_State *L) { - int w; - b_uint r = luaL_checkunsigned(L, 1); - int f = fieldargs(L, 2, &w); - r = (r >> f) & mask(w); - lua_pushunsigned(L, r); - return 1; -} - - -static int b_replace (lua_State *L) { - int w; - b_uint r = luaL_checkunsigned(L, 1); - b_uint v = luaL_checkunsigned(L, 2); - int f = fieldargs(L, 3, &w); - int m = mask(w); - v &= m; /* erase bits outside given width */ - r = (r & ~(m << f)) | (v << f); - lua_pushunsigned(L, r); - return 1; -} - - -static const luaL_Reg bitlib[] = { - {"arshift", b_arshift}, - {"band", b_and}, - {"bnot", b_not}, - {"bor", b_or}, - {"bxor", b_xor}, - {"btest", b_test}, - {"extract", b_extract}, - {"lrotate", b_lrot}, - {"lshift", b_lshift}, - {"replace", b_replace}, - {"rrotate", b_rrot}, - {"rshift", b_rshift}, - {NULL, NULL} -}; - - - -LUAMOD_API int luaopen_bit32 (lua_State *L) { - luaL_newlib(L, bitlib); - return 1; -} - diff --git a/contrib/lua/lua/src/lcode.c b/contrib/lua/lua/src/lcode.c deleted file mode 100644 index 56c26ac8aac..00000000000 --- a/contrib/lua/lua/src/lcode.c +++ /dev/null @@ -1,881 +0,0 @@ -/* -** $Id: lcode.c,v 2.62 2012/08/16 17:34:28 roberto Exp $ -** Code generator for Lua -** See Copyright Notice in lua.h -*/ - - -#include - -#define lcode_c -#define LUA_CORE - -#include "lua.h" - -#include "lcode.h" -#include "ldebug.h" -#include "ldo.h" -#include "lgc.h" -#include "llex.h" -#include "lmem.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" -#include "lstring.h" -#include "ltable.h" -#include "lvm.h" - - -#define hasjumps(e) ((e)->t != (e)->f) - - -static int isnumeral(expdesc *e) { - return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); -} - - -void luaK_nil (FuncState *fs, int from, int n) { - Instruction *previous; - int l = from + n - 1; /* last register to set nil */ - if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ - previous = &fs->f->code[fs->pc-1]; - if (GET_OPCODE(*previous) == OP_LOADNIL) { - int pfrom = GETARG_A(*previous); - int pl = pfrom + GETARG_B(*previous); - if ((pfrom <= from && from <= pl + 1) || - (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */ - if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */ - if (pl > l) l = pl; /* l = max(l, pl) */ - SETARG_A(*previous, from); - SETARG_B(*previous, l - from); - return; - } - } /* else go through */ - } - luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */ -} - - -int luaK_jump (FuncState *fs) { - int jpc = fs->jpc; /* save list of jumps to here */ - int j; - fs->jpc = NO_JUMP; - j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); - luaK_concat(fs, &j, jpc); /* keep them on hold */ - return j; -} - - -void luaK_ret (FuncState *fs, int first, int nret) { - luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); -} - - -static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { - luaK_codeABC(fs, op, A, B, C); - return luaK_jump(fs); -} - - -static void fixjump (FuncState *fs, int pc, int dest) { - Instruction *jmp = &fs->f->code[pc]; - int offset = dest-(pc+1); - lua_assert(dest != NO_JUMP); - if (abs(offset) > MAXARG_sBx) - luaX_syntaxerror(fs->ls, "control structure too long"); - SETARG_sBx(*jmp, offset); -} - - -/* -** returns current `pc' and marks it as a jump target (to avoid wrong -** optimizations with consecutive instructions not in the same basic block). -*/ -int luaK_getlabel (FuncState *fs) { - fs->lasttarget = fs->pc; - return fs->pc; -} - - -static int getjump (FuncState *fs, int pc) { - int offset = GETARG_sBx(fs->f->code[pc]); - if (offset == NO_JUMP) /* point to itself represents end of list */ - return NO_JUMP; /* end of list */ - else - return (pc+1)+offset; /* turn offset into absolute position */ -} - - -static Instruction *getjumpcontrol (FuncState *fs, int pc) { - Instruction *pi = &fs->f->code[pc]; - if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) - return pi-1; - else - return pi; -} - - -/* -** check whether list has any jump that do not produce a value -** (or produce an inverted value) -*/ -static int need_value (FuncState *fs, int list) { - for (; list != NO_JUMP; list = getjump(fs, list)) { - Instruction i = *getjumpcontrol(fs, list); - if (GET_OPCODE(i) != OP_TESTSET) return 1; - } - return 0; /* not found */ -} - - -static int patchtestreg (FuncState *fs, int node, int reg) { - Instruction *i = getjumpcontrol(fs, node); - if (GET_OPCODE(*i) != OP_TESTSET) - return 0; /* cannot patch other instructions */ - if (reg != NO_REG && reg != GETARG_B(*i)) - SETARG_A(*i, reg); - else /* no register to put value or register already has the value */ - *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); - - return 1; -} - - -static void removevalues (FuncState *fs, int list) { - for (; list != NO_JUMP; list = getjump(fs, list)) - patchtestreg(fs, list, NO_REG); -} - - -static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, - int dtarget) { - while (list != NO_JUMP) { - int next = getjump(fs, list); - if (patchtestreg(fs, list, reg)) - fixjump(fs, list, vtarget); - else - fixjump(fs, list, dtarget); /* jump to default target */ - list = next; - } -} - - -static void dischargejpc (FuncState *fs) { - patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); - fs->jpc = NO_JUMP; -} - - -void luaK_patchlist (FuncState *fs, int list, int target) { - if (target == fs->pc) - luaK_patchtohere(fs, list); - else { - lua_assert(target < fs->pc); - patchlistaux(fs, list, target, NO_REG, target); - } -} - - -LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level) { - level++; /* argument is +1 to reserve 0 as non-op */ - while (list != NO_JUMP) { - int next = getjump(fs, list); - lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP && - (GETARG_A(fs->f->code[list]) == 0 || - GETARG_A(fs->f->code[list]) >= level)); - SETARG_A(fs->f->code[list], level); - list = next; - } -} - - -void luaK_patchtohere (FuncState *fs, int list) { - luaK_getlabel(fs); - luaK_concat(fs, &fs->jpc, list); -} - - -void luaK_concat (FuncState *fs, int *l1, int l2) { - if (l2 == NO_JUMP) return; - else if (*l1 == NO_JUMP) - *l1 = l2; - else { - int list = *l1; - int next; - while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ - list = next; - fixjump(fs, list, l2); - } -} - - -static int luaK_code (FuncState *fs, Instruction i) { - Proto *f = fs->f; - dischargejpc(fs); /* `pc' will change */ - /* put new instruction in code array */ - luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, - MAX_INT, "opcodes"); - f->code[fs->pc] = i; - /* save corresponding line information */ - luaM_growvector(fs->ls->L, f->lineinfo, fs->pc, f->sizelineinfo, int, - MAX_INT, "opcodes"); - f->lineinfo[fs->pc] = fs->ls->lastline; - return fs->pc++; -} - - -int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { - lua_assert(getOpMode(o) == iABC); - lua_assert(getBMode(o) != OpArgN || b == 0); - lua_assert(getCMode(o) != OpArgN || c == 0); - lua_assert(a <= MAXARG_A && b <= MAXARG_B && c <= MAXARG_C); - return luaK_code(fs, CREATE_ABC(o, a, b, c)); -} - - -int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { - lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); - lua_assert(getCMode(o) == OpArgN); - lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx); - return luaK_code(fs, CREATE_ABx(o, a, bc)); -} - - -static int codeextraarg (FuncState *fs, int a) { - lua_assert(a <= MAXARG_Ax); - return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a)); -} - - -int luaK_codek (FuncState *fs, int reg, int k) { - if (k <= MAXARG_Bx) - return luaK_codeABx(fs, OP_LOADK, reg, k); - else { - int p = luaK_codeABx(fs, OP_LOADKX, reg, 0); - codeextraarg(fs, k); - return p; - } -} - - -void luaK_checkstack (FuncState *fs, int n) { - int newstack = fs->freereg + n; - if (newstack > fs->f->maxstacksize) { - if (newstack >= MAXSTACK) - luaX_syntaxerror(fs->ls, "function or expression too complex"); - fs->f->maxstacksize = cast_byte(newstack); - } -} - - -void luaK_reserveregs (FuncState *fs, int n) { - luaK_checkstack(fs, n); - fs->freereg += n; -} - - -static void freereg (FuncState *fs, int reg) { - if (!ISK(reg) && reg >= fs->nactvar) { - fs->freereg--; - lua_assert(reg == fs->freereg); - } -} - - -static void freeexp (FuncState *fs, expdesc *e) { - if (e->k == VNONRELOC) - freereg(fs, e->u.info); -} - - -static int addk (FuncState *fs, TValue *key, TValue *v) { - lua_State *L = fs->ls->L; - TValue *idx = luaH_set(L, fs->h, key); - Proto *f = fs->f; - int k, oldsize; - if (ttisnumber(idx)) { - lua_Number n = nvalue(idx); - lua_number2int(k, n); - if (luaV_rawequalobj(&f->k[k], v)) - return k; - /* else may be a collision (e.g., between 0.0 and "\0\0\0\0\0\0\0\0"); - go through and create a new entry for this value */ - } - /* constant not found; create a new entry */ - oldsize = f->sizek; - k = fs->nk; - /* numerical value does not need GC barrier; - table has no metatable, so it does not need to invalidate cache */ - setnvalue(idx, cast_num(k)); - luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); - while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); - setobj(L, &f->k[k], v); - fs->nk++; - luaC_barrier(L, f, v); - return k; -} - - -int luaK_stringK (FuncState *fs, TString *s) { - TValue o; - setsvalue(fs->ls->L, &o, s); - return addk(fs, &o, &o); -} - - -int luaK_numberK (FuncState *fs, lua_Number r) { - int n; - lua_State *L = fs->ls->L; - TValue o; - setnvalue(&o, r); - if (r == 0 || luai_numisnan(NULL, r)) { /* handle -0 and NaN */ - /* use raw representation as key to avoid numeric problems */ - setsvalue(L, L->top++, luaS_newlstr(L, (char *)&r, sizeof(r))); - n = addk(fs, L->top - 1, &o); - L->top--; - } - else - n = addk(fs, &o, &o); /* regular case */ - return n; -} - - -static int boolK (FuncState *fs, int b) { - TValue o; - setbvalue(&o, b); - return addk(fs, &o, &o); -} - - -static int nilK (FuncState *fs) { - TValue k, v; - setnilvalue(&v); - /* cannot use nil as key; instead use table itself to represent nil */ - sethvalue(fs->ls->L, &k, fs->h); - return addk(fs, &k, &v); -} - - -void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { - if (e->k == VCALL) { /* expression is an open function call? */ - SETARG_C(getcode(fs, e), nresults+1); - } - else if (e->k == VVARARG) { - SETARG_B(getcode(fs, e), nresults+1); - SETARG_A(getcode(fs, e), fs->freereg); - luaK_reserveregs(fs, 1); - } -} - - -void luaK_setoneret (FuncState *fs, expdesc *e) { - if (e->k == VCALL) { /* expression is an open function call? */ - e->k = VNONRELOC; - e->u.info = GETARG_A(getcode(fs, e)); - } - else if (e->k == VVARARG) { - SETARG_B(getcode(fs, e), 2); - e->k = VRELOCABLE; /* can relocate its simple result */ - } -} - - -void luaK_dischargevars (FuncState *fs, expdesc *e) { - switch (e->k) { - case VLOCAL: { - e->k = VNONRELOC; - break; - } - case VUPVAL: { - e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); - e->k = VRELOCABLE; - break; - } - case VINDEXED: { - OpCode op = OP_GETTABUP; /* assume 't' is in an upvalue */ - freereg(fs, e->u.ind.idx); - if (e->u.ind.vt == VLOCAL) { /* 't' is in a register? */ - freereg(fs, e->u.ind.t); - op = OP_GETTABLE; - } - e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx); - e->k = VRELOCABLE; - break; - } - case VVARARG: - case VCALL: { - luaK_setoneret(fs, e); - break; - } - default: break; /* there is one value available (somewhere) */ - } -} - - -static int code_label (FuncState *fs, int A, int b, int jump) { - luaK_getlabel(fs); /* those instructions may be jump targets */ - return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); -} - - -static void discharge2reg (FuncState *fs, expdesc *e, int reg) { - luaK_dischargevars(fs, e); - switch (e->k) { - case VNIL: { - luaK_nil(fs, reg, 1); - break; - } - case VFALSE: case VTRUE: { - luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); - break; - } - case VK: { - luaK_codek(fs, reg, e->u.info); - break; - } - case VKNUM: { - luaK_codek(fs, reg, luaK_numberK(fs, e->u.nval)); - break; - } - case VRELOCABLE: { - Instruction *pc = &getcode(fs, e); - SETARG_A(*pc, reg); - break; - } - case VNONRELOC: { - if (reg != e->u.info) - luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0); - break; - } - default: { - lua_assert(e->k == VVOID || e->k == VJMP); - return; /* nothing to do... */ - } - } - e->u.info = reg; - e->k = VNONRELOC; -} - - -static void discharge2anyreg (FuncState *fs, expdesc *e) { - if (e->k != VNONRELOC) { - luaK_reserveregs(fs, 1); - discharge2reg(fs, e, fs->freereg-1); - } -} - - -static void exp2reg (FuncState *fs, expdesc *e, int reg) { - discharge2reg(fs, e, reg); - if (e->k == VJMP) - luaK_concat(fs, &e->t, e->u.info); /* put this jump in `t' list */ - if (hasjumps(e)) { - int final; /* position after whole expression */ - int p_f = NO_JUMP; /* position of an eventual LOAD false */ - int p_t = NO_JUMP; /* position of an eventual LOAD true */ - if (need_value(fs, e->t) || need_value(fs, e->f)) { - int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); - p_f = code_label(fs, reg, 0, 1); - p_t = code_label(fs, reg, 1, 0); - luaK_patchtohere(fs, fj); - } - final = luaK_getlabel(fs); - patchlistaux(fs, e->f, final, reg, p_f); - patchlistaux(fs, e->t, final, reg, p_t); - } - e->f = e->t = NO_JUMP; - e->u.info = reg; - e->k = VNONRELOC; -} - - -void luaK_exp2nextreg (FuncState *fs, expdesc *e) { - luaK_dischargevars(fs, e); - freeexp(fs, e); - luaK_reserveregs(fs, 1); - exp2reg(fs, e, fs->freereg - 1); -} - - -int luaK_exp2anyreg (FuncState *fs, expdesc *e) { - luaK_dischargevars(fs, e); - if (e->k == VNONRELOC) { - if (!hasjumps(e)) return e->u.info; /* exp is already in a register */ - if (e->u.info >= fs->nactvar) { /* reg. is not a local? */ - exp2reg(fs, e, e->u.info); /* put value on it */ - return e->u.info; - } - } - luaK_exp2nextreg(fs, e); /* default */ - return e->u.info; -} - - -void luaK_exp2anyregup (FuncState *fs, expdesc *e) { - if (e->k != VUPVAL || hasjumps(e)) - luaK_exp2anyreg(fs, e); -} - - -void luaK_exp2val (FuncState *fs, expdesc *e) { - if (hasjumps(e)) - luaK_exp2anyreg(fs, e); - else - luaK_dischargevars(fs, e); -} - - -int luaK_exp2RK (FuncState *fs, expdesc *e) { - luaK_exp2val(fs, e); - switch (e->k) { - case VTRUE: - case VFALSE: - case VNIL: { - if (fs->nk <= MAXINDEXRK) { /* constant fits in RK operand? */ - e->u.info = (e->k == VNIL) ? nilK(fs) : boolK(fs, (e->k == VTRUE)); - e->k = VK; - return RKASK(e->u.info); - } - else break; - } - case VKNUM: { - e->u.info = luaK_numberK(fs, e->u.nval); - e->k = VK; - /* go through */ - } - case VK: { - if (e->u.info <= MAXINDEXRK) /* constant fits in argC? */ - return RKASK(e->u.info); - else break; - } - default: break; - } - /* not a constant in the right range: put it in a register */ - return luaK_exp2anyreg(fs, e); -} - - -void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { - switch (var->k) { - case VLOCAL: { - freeexp(fs, ex); - exp2reg(fs, ex, var->u.info); - return; - } - case VUPVAL: { - int e = luaK_exp2anyreg(fs, ex); - luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0); - break; - } - case VINDEXED: { - OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP; - int e = luaK_exp2RK(fs, ex); - luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e); - break; - } - default: { - lua_assert(0); /* invalid var kind to store */ - break; - } - } - freeexp(fs, ex); -} - - -void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { - int ereg; - luaK_exp2anyreg(fs, e); - ereg = e->u.info; /* register where 'e' was placed */ - freeexp(fs, e); - e->u.info = fs->freereg; /* base register for op_self */ - e->k = VNONRELOC; - luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */ - luaK_codeABC(fs, OP_SELF, e->u.info, ereg, luaK_exp2RK(fs, key)); - freeexp(fs, key); -} - - -static void invertjump (FuncState *fs, expdesc *e) { - Instruction *pc = getjumpcontrol(fs, e->u.info); - lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && - GET_OPCODE(*pc) != OP_TEST); - SETARG_A(*pc, !(GETARG_A(*pc))); -} - - -static int jumponcond (FuncState *fs, expdesc *e, int cond) { - if (e->k == VRELOCABLE) { - Instruction ie = getcode(fs, e); - if (GET_OPCODE(ie) == OP_NOT) { - fs->pc--; /* remove previous OP_NOT */ - return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); - } - /* else go through */ - } - discharge2anyreg(fs, e); - freeexp(fs, e); - return condjump(fs, OP_TESTSET, NO_REG, e->u.info, cond); -} - - -void luaK_goiftrue (FuncState *fs, expdesc *e) { - int pc; /* pc of last jump */ - luaK_dischargevars(fs, e); - switch (e->k) { - case VJMP: { - invertjump(fs, e); - pc = e->u.info; - break; - } - case VK: case VKNUM: case VTRUE: { - pc = NO_JUMP; /* always true; do nothing */ - break; - } - default: { - pc = jumponcond(fs, e, 0); - break; - } - } - luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ - luaK_patchtohere(fs, e->t); - e->t = NO_JUMP; -} - - -void luaK_goiffalse (FuncState *fs, expdesc *e) { - int pc; /* pc of last jump */ - luaK_dischargevars(fs, e); - switch (e->k) { - case VJMP: { - pc = e->u.info; - break; - } - case VNIL: case VFALSE: { - pc = NO_JUMP; /* always false; do nothing */ - break; - } - default: { - pc = jumponcond(fs, e, 1); - break; - } - } - luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ - luaK_patchtohere(fs, e->f); - e->f = NO_JUMP; -} - - -static void codenot (FuncState *fs, expdesc *e) { - luaK_dischargevars(fs, e); - switch (e->k) { - case VNIL: case VFALSE: { - e->k = VTRUE; - break; - } - case VK: case VKNUM: case VTRUE: { - e->k = VFALSE; - break; - } - case VJMP: { - invertjump(fs, e); - break; - } - case VRELOCABLE: - case VNONRELOC: { - discharge2anyreg(fs, e); - freeexp(fs, e); - e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0); - e->k = VRELOCABLE; - break; - } - default: { - lua_assert(0); /* cannot happen */ - break; - } - } - /* interchange true and false lists */ - { int temp = e->f; e->f = e->t; e->t = temp; } - removevalues(fs, e->f); - removevalues(fs, e->t); -} - - -void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { - lua_assert(!hasjumps(t)); - t->u.ind.t = t->u.info; - t->u.ind.idx = luaK_exp2RK(fs, k); - t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL - : check_exp(vkisinreg(t->k), VLOCAL); - t->k = VINDEXED; -} - - -static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { - lua_Number r; - if (!isnumeral(e1) || !isnumeral(e2)) return 0; - if ((op == OP_DIV || op == OP_MOD) && e2->u.nval == 0) - return 0; /* do not attempt to divide by 0 */ - r = luaO_arith(op - OP_ADD + LUA_OPADD, e1->u.nval, e2->u.nval); - e1->u.nval = r; - return 1; -} - - -static void codearith (FuncState *fs, OpCode op, - expdesc *e1, expdesc *e2, int line) { - if (constfolding(op, e1, e2)) - return; - else { - int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; - int o1 = luaK_exp2RK(fs, e1); - if (o1 > o2) { - freeexp(fs, e1); - freeexp(fs, e2); - } - else { - freeexp(fs, e2); - freeexp(fs, e1); - } - e1->u.info = luaK_codeABC(fs, op, 0, o1, o2); - e1->k = VRELOCABLE; - luaK_fixline(fs, line); - } -} - - -static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, - expdesc *e2) { - int o1 = luaK_exp2RK(fs, e1); - int o2 = luaK_exp2RK(fs, e2); - freeexp(fs, e2); - freeexp(fs, e1); - if (cond == 0 && op != OP_EQ) { - int temp; /* exchange args to replace by `<' or `<=' */ - temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ - cond = 1; - } - e1->u.info = condjump(fs, op, cond, o1, o2); - e1->k = VJMP; -} - - -void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { - expdesc e2; - e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; - switch (op) { - case OPR_MINUS: { - if (isnumeral(e)) /* minus constant? */ - e->u.nval = luai_numunm(NULL, e->u.nval); /* fold it */ - else { - luaK_exp2anyreg(fs, e); - codearith(fs, OP_UNM, e, &e2, line); - } - break; - } - case OPR_NOT: codenot(fs, e); break; - case OPR_LEN: { - luaK_exp2anyreg(fs, e); /* cannot operate on constants */ - codearith(fs, OP_LEN, e, &e2, line); - break; - } - default: lua_assert(0); - } -} - - -void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { - switch (op) { - case OPR_AND: { - luaK_goiftrue(fs, v); - break; - } - case OPR_OR: { - luaK_goiffalse(fs, v); - break; - } - case OPR_CONCAT: { - luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ - break; - } - case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: - case OPR_MOD: case OPR_POW: { - if (!isnumeral(v)) luaK_exp2RK(fs, v); - break; - } - default: { - luaK_exp2RK(fs, v); - break; - } - } -} - - -void luaK_posfix (FuncState *fs, BinOpr op, - expdesc *e1, expdesc *e2, int line) { - switch (op) { - case OPR_AND: { - lua_assert(e1->t == NO_JUMP); /* list must be closed */ - luaK_dischargevars(fs, e2); - luaK_concat(fs, &e2->f, e1->f); - *e1 = *e2; - break; - } - case OPR_OR: { - lua_assert(e1->f == NO_JUMP); /* list must be closed */ - luaK_dischargevars(fs, e2); - luaK_concat(fs, &e2->t, e1->t); - *e1 = *e2; - break; - } - case OPR_CONCAT: { - luaK_exp2val(fs, e2); - if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { - lua_assert(e1->u.info == GETARG_B(getcode(fs, e2))-1); - freeexp(fs, e1); - SETARG_B(getcode(fs, e2), e1->u.info); - e1->k = VRELOCABLE; e1->u.info = e2->u.info; - } - else { - luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ - codearith(fs, OP_CONCAT, e1, e2, line); - } - break; - } - case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: - case OPR_MOD: case OPR_POW: { - codearith(fs, cast(OpCode, op - OPR_ADD + OP_ADD), e1, e2, line); - break; - } - case OPR_EQ: case OPR_LT: case OPR_LE: { - codecomp(fs, cast(OpCode, op - OPR_EQ + OP_EQ), 1, e1, e2); - break; - } - case OPR_NE: case OPR_GT: case OPR_GE: { - codecomp(fs, cast(OpCode, op - OPR_NE + OP_EQ), 0, e1, e2); - break; - } - default: lua_assert(0); - } -} - - -void luaK_fixline (FuncState *fs, int line) { - fs->f->lineinfo[fs->pc - 1] = line; -} - - -void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { - int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; - int b = (tostore == LUA_MULTRET) ? 0 : tostore; - lua_assert(tostore != 0); - if (c <= MAXARG_C) - luaK_codeABC(fs, OP_SETLIST, base, b, c); - else if (c <= MAXARG_Ax) { - luaK_codeABC(fs, OP_SETLIST, base, b, 0); - codeextraarg(fs, c); - } - else - luaX_syntaxerror(fs->ls, "constructor too long"); - fs->freereg = base + 1; /* free registers with list values */ -} - diff --git a/contrib/lua/lua/src/lcode.h b/contrib/lua/lua/src/lcode.h deleted file mode 100644 index 5a1fa9feac6..00000000000 --- a/contrib/lua/lua/src/lcode.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -** $Id: lcode.h,v 1.58 2011/08/30 16:26:41 roberto Exp $ -** Code generator for Lua -** See Copyright Notice in lua.h -*/ - -#ifndef lcode_h -#define lcode_h - -#include "llex.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" - - -/* -** Marks the end of a patch list. It is an invalid value both as an absolute -** address, and as a list link (would link an element to itself). -*/ -#define NO_JUMP (-1) - - -/* -** grep "ORDER OPR" if you change these enums (ORDER OP) -*/ -typedef enum BinOpr { - OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, - OPR_CONCAT, - OPR_EQ, OPR_LT, OPR_LE, - OPR_NE, OPR_GT, OPR_GE, - OPR_AND, OPR_OR, - OPR_NOBINOPR -} BinOpr; - - -typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; - - -#define getcode(fs,e) ((fs)->f->code[(e)->u.info]) - -#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) - -#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) - -#define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t) - -LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); -LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); -LUAI_FUNC int luaK_codek (FuncState *fs, int reg, int k); -LUAI_FUNC void luaK_fixline (FuncState *fs, int line); -LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); -LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); -LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); -LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); -LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); -LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); -LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); -LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); -LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); -LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e); -LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); -LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); -LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); -LUAI_FUNC int luaK_jump (FuncState *fs); -LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); -LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); -LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); -LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level); -LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); -LUAI_FUNC int luaK_getlabel (FuncState *fs); -LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line); -LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); -LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, - expdesc *v2, int line); -LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); - - -#endif diff --git a/contrib/lua/lua/src/lcorolib.c b/contrib/lua/lua/src/lcorolib.c deleted file mode 100644 index 1326c8146c5..00000000000 --- a/contrib/lua/lua/src/lcorolib.c +++ /dev/null @@ -1,155 +0,0 @@ -/* -** $Id: lcorolib.c,v 1.5 2013/02/21 13:44:53 roberto Exp $ -** Coroutine Library -** See Copyright Notice in lua.h -*/ - - -#include - - -#define lcorolib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -static int auxresume (lua_State *L, lua_State *co, int narg) { - int status; - if (!lua_checkstack(co, narg)) { - lua_pushliteral(L, "too many arguments to resume"); - return -1; /* error flag */ - } - if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) { - lua_pushliteral(L, "cannot resume dead coroutine"); - return -1; /* error flag */ - } - lua_xmove(L, co, narg); - status = lua_resume(co, L, narg); - if (status == LUA_OK || status == LUA_YIELD) { - int nres = lua_gettop(co); - if (!lua_checkstack(L, nres + 1)) { - lua_pop(co, nres); /* remove results anyway */ - lua_pushliteral(L, "too many results to resume"); - return -1; /* error flag */ - } - lua_xmove(co, L, nres); /* move yielded values */ - return nres; - } - else { - lua_xmove(co, L, 1); /* move error message */ - return -1; /* error flag */ - } -} - - -static int luaB_coresume (lua_State *L) { - lua_State *co = lua_tothread(L, 1); - int r; - luaL_argcheck(L, co, 1, "coroutine expected"); - r = auxresume(L, co, lua_gettop(L) - 1); - if (r < 0) { - lua_pushboolean(L, 0); - lua_insert(L, -2); - return 2; /* return false + error message */ - } - else { - lua_pushboolean(L, 1); - lua_insert(L, -(r + 1)); - return r + 1; /* return true + `resume' returns */ - } -} - - -static int luaB_auxwrap (lua_State *L) { - lua_State *co = lua_tothread(L, lua_upvalueindex(1)); - int r = auxresume(L, co, lua_gettop(L)); - if (r < 0) { - if (lua_isstring(L, -1)) { /* error object is a string? */ - luaL_where(L, 1); /* add extra info */ - lua_insert(L, -2); - lua_concat(L, 2); - } - return lua_error(L); /* propagate error */ - } - return r; -} - - -static int luaB_cocreate (lua_State *L) { - lua_State *NL; - luaL_checktype(L, 1, LUA_TFUNCTION); - NL = lua_newthread(L); - lua_pushvalue(L, 1); /* move function to top */ - lua_xmove(L, NL, 1); /* move function from L to NL */ - return 1; -} - - -static int luaB_cowrap (lua_State *L) { - luaB_cocreate(L); - lua_pushcclosure(L, luaB_auxwrap, 1); - return 1; -} - - -static int luaB_yield (lua_State *L) { - return lua_yield(L, lua_gettop(L)); -} - - -static int luaB_costatus (lua_State *L) { - lua_State *co = lua_tothread(L, 1); - luaL_argcheck(L, co, 1, "coroutine expected"); - if (L == co) lua_pushliteral(L, "running"); - else { - switch (lua_status(co)) { - case LUA_YIELD: - lua_pushliteral(L, "suspended"); - break; - case LUA_OK: { - lua_Debug ar; - if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ - lua_pushliteral(L, "normal"); /* it is running */ - else if (lua_gettop(co) == 0) - lua_pushliteral(L, "dead"); - else - lua_pushliteral(L, "suspended"); /* initial state */ - break; - } - default: /* some error occurred */ - lua_pushliteral(L, "dead"); - break; - } - } - return 1; -} - - -static int luaB_corunning (lua_State *L) { - int ismain = lua_pushthread(L); - lua_pushboolean(L, ismain); - return 2; -} - - -static const luaL_Reg co_funcs[] = { - {"create", luaB_cocreate}, - {"resume", luaB_coresume}, - {"running", luaB_corunning}, - {"status", luaB_costatus}, - {"wrap", luaB_cowrap}, - {"yield", luaB_yield}, - {NULL, NULL} -}; - - - -LUAMOD_API int luaopen_coroutine (lua_State *L) { - luaL_newlib(L, co_funcs); - return 1; -} - diff --git a/contrib/lua/lua/src/lctype.c b/contrib/lua/lua/src/lctype.c deleted file mode 100644 index 55e433a5dd7..00000000000 --- a/contrib/lua/lua/src/lctype.c +++ /dev/null @@ -1,52 +0,0 @@ -/* -** $Id: lctype.c,v 1.11 2011/10/03 16:19:23 roberto Exp $ -** 'ctype' functions for Lua -** See Copyright Notice in lua.h -*/ - -#define lctype_c -#define LUA_CORE - -#include "lctype.h" - -#if !LUA_USE_CTYPE /* { */ - -#include - -LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = { - 0x00, /* EOZ */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */ - 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */ - 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */ - 0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */ - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */ - 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05, - 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */ - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */ - 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* e. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* f. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -#endif /* } */ diff --git a/contrib/lua/lua/src/lctype.h b/contrib/lua/lua/src/lctype.h deleted file mode 100644 index 99c7d122376..00000000000 --- a/contrib/lua/lua/src/lctype.h +++ /dev/null @@ -1,95 +0,0 @@ -/* -** $Id: lctype.h,v 1.12 2011/07/15 12:50:29 roberto Exp $ -** 'ctype' functions for Lua -** See Copyright Notice in lua.h -*/ - -#ifndef lctype_h -#define lctype_h - -#include "lua.h" - - -/* -** WARNING: the functions defined here do not necessarily correspond -** to the similar functions in the standard C ctype.h. They are -** optimized for the specific needs of Lua -*/ - -#if !defined(LUA_USE_CTYPE) - -#if 'A' == 65 && '0' == 48 -/* ASCII case: can use its own tables; faster and fixed */ -#define LUA_USE_CTYPE 0 -#else -/* must use standard C ctype */ -#define LUA_USE_CTYPE 1 -#endif - -#endif - - -#if !LUA_USE_CTYPE /* { */ - -#include - -#include "llimits.h" - - -#define ALPHABIT 0 -#define DIGITBIT 1 -#define PRINTBIT 2 -#define SPACEBIT 3 -#define XDIGITBIT 4 - - -#define MASK(B) (1 << (B)) - - -/* -** add 1 to char to allow index -1 (EOZ) -*/ -#define testprop(c,p) (luai_ctype_[(c)+1] & (p)) - -/* -** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_' -*/ -#define lislalpha(c) testprop(c, MASK(ALPHABIT)) -#define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT))) -#define lisdigit(c) testprop(c, MASK(DIGITBIT)) -#define lisspace(c) testprop(c, MASK(SPACEBIT)) -#define lisprint(c) testprop(c, MASK(PRINTBIT)) -#define lisxdigit(c) testprop(c, MASK(XDIGITBIT)) - -/* -** this 'ltolower' only works for alphabetic characters -*/ -#define ltolower(c) ((c) | ('A' ^ 'a')) - - -/* two more entries for 0 and -1 (EOZ) */ -LUAI_DDEC const lu_byte luai_ctype_[UCHAR_MAX + 2]; - - -#else /* }{ */ - -/* -** use standard C ctypes -*/ - -#include - - -#define lislalpha(c) (isalpha(c) || (c) == '_') -#define lislalnum(c) (isalnum(c) || (c) == '_') -#define lisdigit(c) (isdigit(c)) -#define lisspace(c) (isspace(c)) -#define lisprint(c) (isprint(c)) -#define lisxdigit(c) (isxdigit(c)) - -#define ltolower(c) (tolower(c)) - -#endif /* } */ - -#endif - diff --git a/contrib/lua/lua/src/ldblib.c b/contrib/lua/lua/src/ldblib.c deleted file mode 100644 index c0226945737..00000000000 --- a/contrib/lua/lua/src/ldblib.c +++ /dev/null @@ -1,398 +0,0 @@ -/* -** $Id: ldblib.c,v 1.132 2012/01/19 20:14:44 roberto Exp $ -** Interface from Lua to its debug API -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include - -#define ldblib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -#define HOOKKEY "_HKEY" - - - -static int db_getregistry (lua_State *L) { - lua_pushvalue(L, LUA_REGISTRYINDEX); - return 1; -} - - -static int db_getmetatable (lua_State *L) { - luaL_checkany(L, 1); - if (!lua_getmetatable(L, 1)) { - lua_pushnil(L); /* no metatable */ - } - return 1; -} - - -static int db_setmetatable (lua_State *L) { - int t = lua_type(L, 2); - luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, - "nil or table expected"); - lua_settop(L, 2); - lua_setmetatable(L, 1); - return 1; /* return 1st argument */ -} - - -static int db_getuservalue (lua_State *L) { - if (lua_type(L, 1) != LUA_TUSERDATA) - lua_pushnil(L); - else - lua_getuservalue(L, 1); - return 1; -} - - -static int db_setuservalue (lua_State *L) { - if (lua_type(L, 1) == LUA_TLIGHTUSERDATA) - luaL_argerror(L, 1, "full userdata expected, got light userdata"); - luaL_checktype(L, 1, LUA_TUSERDATA); - if (!lua_isnoneornil(L, 2)) - luaL_checktype(L, 2, LUA_TTABLE); - lua_settop(L, 2); - lua_setuservalue(L, 1); - return 1; -} - - -static void settabss (lua_State *L, const char *i, const char *v) { - lua_pushstring(L, v); - lua_setfield(L, -2, i); -} - - -static void settabsi (lua_State *L, const char *i, int v) { - lua_pushinteger(L, v); - lua_setfield(L, -2, i); -} - - -static void settabsb (lua_State *L, const char *i, int v) { - lua_pushboolean(L, v); - lua_setfield(L, -2, i); -} - - -static lua_State *getthread (lua_State *L, int *arg) { - if (lua_isthread(L, 1)) { - *arg = 1; - return lua_tothread(L, 1); - } - else { - *arg = 0; - return L; - } -} - - -static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { - if (L == L1) { - lua_pushvalue(L, -2); - lua_remove(L, -3); - } - else - lua_xmove(L1, L, 1); - lua_setfield(L, -2, fname); -} - - -static int db_getinfo (lua_State *L) { - lua_Debug ar; - int arg; - lua_State *L1 = getthread(L, &arg); - const char *options = luaL_optstring(L, arg+2, "flnStu"); - if (lua_isnumber(L, arg+1)) { - if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) { - lua_pushnil(L); /* level out of range */ - return 1; - } - } - else if (lua_isfunction(L, arg+1)) { - lua_pushfstring(L, ">%s", options); - options = lua_tostring(L, -1); - lua_pushvalue(L, arg+1); - lua_xmove(L, L1, 1); - } - else - return luaL_argerror(L, arg+1, "function or level expected"); - if (!lua_getinfo(L1, options, &ar)) - return luaL_argerror(L, arg+2, "invalid option"); - lua_createtable(L, 0, 2); - if (strchr(options, 'S')) { - settabss(L, "source", ar.source); - settabss(L, "short_src", ar.short_src); - settabsi(L, "linedefined", ar.linedefined); - settabsi(L, "lastlinedefined", ar.lastlinedefined); - settabss(L, "what", ar.what); - } - if (strchr(options, 'l')) - settabsi(L, "currentline", ar.currentline); - if (strchr(options, 'u')) { - settabsi(L, "nups", ar.nups); - settabsi(L, "nparams", ar.nparams); - settabsb(L, "isvararg", ar.isvararg); - } - if (strchr(options, 'n')) { - settabss(L, "name", ar.name); - settabss(L, "namewhat", ar.namewhat); - } - if (strchr(options, 't')) - settabsb(L, "istailcall", ar.istailcall); - if (strchr(options, 'L')) - treatstackoption(L, L1, "activelines"); - if (strchr(options, 'f')) - treatstackoption(L, L1, "func"); - return 1; /* return table */ -} - - -static int db_getlocal (lua_State *L) { - int arg; - lua_State *L1 = getthread(L, &arg); - lua_Debug ar; - const char *name; - int nvar = luaL_checkint(L, arg+2); /* local-variable index */ - if (lua_isfunction(L, arg + 1)) { /* function argument? */ - lua_pushvalue(L, arg + 1); /* push function */ - lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */ - return 1; - } - else { /* stack-level argument */ - if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ - return luaL_argerror(L, arg+1, "level out of range"); - name = lua_getlocal(L1, &ar, nvar); - if (name) { - lua_xmove(L1, L, 1); /* push local value */ - lua_pushstring(L, name); /* push name */ - lua_pushvalue(L, -2); /* re-order */ - return 2; - } - else { - lua_pushnil(L); /* no name (nor value) */ - return 1; - } - } -} - - -static int db_setlocal (lua_State *L) { - int arg; - lua_State *L1 = getthread(L, &arg); - lua_Debug ar; - if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ - return luaL_argerror(L, arg+1, "level out of range"); - luaL_checkany(L, arg+3); - lua_settop(L, arg+3); - lua_xmove(L, L1, 1); - lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2))); - return 1; -} - - -static int auxupvalue (lua_State *L, int get) { - const char *name; - int n = luaL_checkint(L, 2); - luaL_checktype(L, 1, LUA_TFUNCTION); - name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); - if (name == NULL) return 0; - lua_pushstring(L, name); - lua_insert(L, -(get+1)); - return get + 1; -} - - -static int db_getupvalue (lua_State *L) { - return auxupvalue(L, 1); -} - - -static int db_setupvalue (lua_State *L) { - luaL_checkany(L, 3); - return auxupvalue(L, 0); -} - - -static int checkupval (lua_State *L, int argf, int argnup) { - lua_Debug ar; - int nup = luaL_checkint(L, argnup); - luaL_checktype(L, argf, LUA_TFUNCTION); - lua_pushvalue(L, argf); - lua_getinfo(L, ">u", &ar); - luaL_argcheck(L, 1 <= nup && nup <= ar.nups, argnup, "invalid upvalue index"); - return nup; -} - - -static int db_upvalueid (lua_State *L) { - int n = checkupval(L, 1, 2); - lua_pushlightuserdata(L, lua_upvalueid(L, 1, n)); - return 1; -} - - -static int db_upvaluejoin (lua_State *L) { - int n1 = checkupval(L, 1, 2); - int n2 = checkupval(L, 3, 4); - luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected"); - luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected"); - lua_upvaluejoin(L, 1, n1, 3, n2); - return 0; -} - - -#define gethooktable(L) luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY) - - -static void hookf (lua_State *L, lua_Debug *ar) { - static const char *const hooknames[] = - {"call", "return", "line", "count", "tail call"}; - gethooktable(L); - lua_pushthread(L); - lua_rawget(L, -2); - if (lua_isfunction(L, -1)) { - lua_pushstring(L, hooknames[(int)ar->event]); - if (ar->currentline >= 0) - lua_pushinteger(L, ar->currentline); - else lua_pushnil(L); - lua_assert(lua_getinfo(L, "lS", ar)); - lua_call(L, 2, 0); - } -} - - -static int makemask (const char *smask, int count) { - int mask = 0; - if (strchr(smask, 'c')) mask |= LUA_MASKCALL; - if (strchr(smask, 'r')) mask |= LUA_MASKRET; - if (strchr(smask, 'l')) mask |= LUA_MASKLINE; - if (count > 0) mask |= LUA_MASKCOUNT; - return mask; -} - - -static char *unmakemask (int mask, char *smask) { - int i = 0; - if (mask & LUA_MASKCALL) smask[i++] = 'c'; - if (mask & LUA_MASKRET) smask[i++] = 'r'; - if (mask & LUA_MASKLINE) smask[i++] = 'l'; - smask[i] = '\0'; - return smask; -} - - -static int db_sethook (lua_State *L) { - int arg, mask, count; - lua_Hook func; - lua_State *L1 = getthread(L, &arg); - if (lua_isnoneornil(L, arg+1)) { - lua_settop(L, arg+1); - func = NULL; mask = 0; count = 0; /* turn off hooks */ - } - else { - const char *smask = luaL_checkstring(L, arg+2); - luaL_checktype(L, arg+1, LUA_TFUNCTION); - count = luaL_optint(L, arg+3, 0); - func = hookf; mask = makemask(smask, count); - } - if (gethooktable(L) == 0) { /* creating hook table? */ - lua_pushstring(L, "k"); - lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */ - lua_pushvalue(L, -1); - lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */ - } - lua_pushthread(L1); lua_xmove(L1, L, 1); - lua_pushvalue(L, arg+1); - lua_rawset(L, -3); /* set new hook */ - lua_sethook(L1, func, mask, count); /* set hooks */ - return 0; -} - - -static int db_gethook (lua_State *L) { - int arg; - lua_State *L1 = getthread(L, &arg); - char buff[5]; - int mask = lua_gethookmask(L1); - lua_Hook hook = lua_gethook(L1); - if (hook != NULL && hook != hookf) /* external hook? */ - lua_pushliteral(L, "external hook"); - else { - gethooktable(L); - lua_pushthread(L1); lua_xmove(L1, L, 1); - lua_rawget(L, -2); /* get hook */ - lua_remove(L, -2); /* remove hook table */ - } - lua_pushstring(L, unmakemask(mask, buff)); - lua_pushinteger(L, lua_gethookcount(L1)); - return 3; -} - - -static int db_debug (lua_State *L) { - for (;;) { - char buffer[250]; - luai_writestringerror("%s", "lua_debug> "); - if (fgets(buffer, sizeof(buffer), stdin) == 0 || - strcmp(buffer, "cont\n") == 0) - return 0; - if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || - lua_pcall(L, 0, 0, 0)) - luai_writestringerror("%s\n", lua_tostring(L, -1)); - lua_settop(L, 0); /* remove eventual returns */ - } -} - - -static int db_traceback (lua_State *L) { - int arg; - lua_State *L1 = getthread(L, &arg); - const char *msg = lua_tostring(L, arg + 1); - if (msg == NULL && !lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */ - lua_pushvalue(L, arg + 1); /* return it untouched */ - else { - int level = luaL_optint(L, arg + 2, (L == L1) ? 1 : 0); - luaL_traceback(L, L1, msg, level); - } - return 1; -} - - -static const luaL_Reg dblib[] = { - {"debug", db_debug}, - {"getuservalue", db_getuservalue}, - {"gethook", db_gethook}, - {"getinfo", db_getinfo}, - {"getlocal", db_getlocal}, - {"getregistry", db_getregistry}, - {"getmetatable", db_getmetatable}, - {"getupvalue", db_getupvalue}, - {"upvaluejoin", db_upvaluejoin}, - {"upvalueid", db_upvalueid}, - {"setuservalue", db_setuservalue}, - {"sethook", db_sethook}, - {"setlocal", db_setlocal}, - {"setmetatable", db_setmetatable}, - {"setupvalue", db_setupvalue}, - {"traceback", db_traceback}, - {NULL, NULL} -}; - - -LUAMOD_API int luaopen_debug (lua_State *L) { - luaL_newlib(L, dblib); - return 1; -} - diff --git a/contrib/lua/lua/src/ldebug.c b/contrib/lua/lua/src/ldebug.c deleted file mode 100644 index 7e04f9d09f8..00000000000 --- a/contrib/lua/lua/src/ldebug.c +++ /dev/null @@ -1,580 +0,0 @@ -/* -** $Id: ldebug.c,v 2.90 2012/08/16 17:34:28 roberto Exp $ -** Debug Interface -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include - - -#define ldebug_c -#define LUA_CORE - -#include "lua.h" - -#include "lapi.h" -#include "lcode.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lvm.h" - - - -#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_TCCL) - - -static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); - - -static int currentpc (CallInfo *ci) { - lua_assert(isLua(ci)); - return pcRel(ci->u.l.savedpc, ci_func(ci)->p); -} - - -static int currentline (CallInfo *ci) { - return getfuncline(ci_func(ci)->p, currentpc(ci)); -} - - -/* -** this function can be called asynchronous (e.g. during a signal) -*/ -LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { - if (func == NULL || mask == 0) { /* turn off hooks? */ - mask = 0; - func = NULL; - } - if (isLua(L->ci)) - L->oldpc = L->ci->u.l.savedpc; - L->hook = func; - L->basehookcount = count; - resethookcount(L); - L->hookmask = cast_byte(mask); - return 1; -} - - -LUA_API lua_Hook lua_gethook (lua_State *L) { - return L->hook; -} - - -LUA_API int lua_gethookmask (lua_State *L) { - return L->hookmask; -} - - -LUA_API int lua_gethookcount (lua_State *L) { - return L->basehookcount; -} - - -LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { - int status; - CallInfo *ci; - if (level < 0) return 0; /* invalid (negative) level */ - lua_lock(L); - for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous) - level--; - if (level == 0 && ci != &L->base_ci) { /* level found? */ - status = 1; - ar->i_ci = ci; - } - else status = 0; /* no such level */ - lua_unlock(L); - return status; -} - - -static const char *upvalname (Proto *p, int uv) { - TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name); - if (s == NULL) return "?"; - else return getstr(s); -} - - -static const char *findvararg (CallInfo *ci, int n, StkId *pos) { - int nparams = clLvalue(ci->func)->p->numparams; - if (n >= ci->u.l.base - ci->func - nparams) - return NULL; /* no such vararg */ - else { - *pos = ci->func + nparams + n; - return "(*vararg)"; /* generic name for any vararg */ - } -} - - -static const char *findlocal (lua_State *L, CallInfo *ci, int n, - StkId *pos) { - const char *name = NULL; - StkId base; - if (isLua(ci)) { - if (n < 0) /* access to vararg values? */ - return findvararg(ci, -n, pos); - else { - base = ci->u.l.base; - name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); - } - } - else - base = ci->func + 1; - if (name == NULL) { /* no 'standard' name? */ - StkId limit = (ci == L->ci) ? L->top : ci->next->func; - if (limit - base >= n && n > 0) /* is 'n' inside 'ci' stack? */ - name = "(*temporary)"; /* generic name for any valid slot */ - else - return NULL; /* no name */ - } - *pos = base + (n - 1); - return name; -} - - -LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { - const char *name; - lua_lock(L); - if (ar == NULL) { /* information about non-active function? */ - if (!isLfunction(L->top - 1)) /* not a Lua function? */ - name = NULL; - else /* consider live variables at function start (parameters) */ - name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0); - } - else { /* active function; get information through 'ar' */ - StkId pos = 0; /* to avoid warnings */ - name = findlocal(L, ar->i_ci, n, &pos); - if (name) { - setobj2s(L, L->top, pos); - api_incr_top(L); - } - } - lua_unlock(L); - return name; -} - - -LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { - StkId pos = 0; /* to avoid warnings */ - const char *name = findlocal(L, ar->i_ci, n, &pos); - lua_lock(L); - if (name) - setobjs2s(L, pos, L->top - 1); - L->top--; /* pop value */ - lua_unlock(L); - return name; -} - - -static void funcinfo (lua_Debug *ar, Closure *cl) { - if (noLuaClosure(cl)) { - ar->source = "=[C]"; - ar->linedefined = -1; - ar->lastlinedefined = -1; - ar->what = "C"; - } - else { - Proto *p = cl->l.p; - ar->source = p->source ? getstr(p->source) : "=?"; - ar->linedefined = p->linedefined; - ar->lastlinedefined = p->lastlinedefined; - ar->what = (ar->linedefined == 0) ? "main" : "Lua"; - } - luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); -} - - -static void collectvalidlines (lua_State *L, Closure *f) { - if (noLuaClosure(f)) { - setnilvalue(L->top); - api_incr_top(L); - } - else { - int i; - TValue v; - int *lineinfo = f->l.p->lineinfo; - Table *t = luaH_new(L); /* new table to store active lines */ - sethvalue(L, L->top, t); /* push it on stack */ - api_incr_top(L); - setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */ - for (i = 0; i < f->l.p->sizelineinfo; i++) /* for all lines with code */ - luaH_setint(L, t, lineinfo[i], &v); /* table[line] = true */ - } -} - - -static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, - Closure *f, CallInfo *ci) { - int status = 1; - for (; *what; what++) { - switch (*what) { - case 'S': { - funcinfo(ar, f); - break; - } - case 'l': { - ar->currentline = (ci && isLua(ci)) ? currentline(ci) : -1; - break; - } - case 'u': { - ar->nups = (f == NULL) ? 0 : f->c.nupvalues; - if (noLuaClosure(f)) { - ar->isvararg = 1; - ar->nparams = 0; - } - else { - ar->isvararg = f->l.p->is_vararg; - ar->nparams = f->l.p->numparams; - } - break; - } - case 't': { - ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0; - break; - } - case 'n': { - /* calling function is a known Lua function? */ - if (ci && !(ci->callstatus & CIST_TAIL) && isLua(ci->previous)) - ar->namewhat = getfuncname(L, ci->previous, &ar->name); - else - ar->namewhat = NULL; - if (ar->namewhat == NULL) { - ar->namewhat = ""; /* not found */ - ar->name = NULL; - } - break; - } - case 'L': - case 'f': /* handled by lua_getinfo */ - break; - default: status = 0; /* invalid option */ - } - } - return status; -} - - -LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { - int status; - Closure *cl; - CallInfo *ci; - StkId func; - lua_lock(L); - if (*what == '>') { - ci = NULL; - func = L->top - 1; - api_check(L, ttisfunction(func), "function expected"); - what++; /* skip the '>' */ - L->top--; /* pop function */ - } - else { - ci = ar->i_ci; - func = ci->func; - lua_assert(ttisfunction(ci->func)); - } - cl = ttisclosure(func) ? clvalue(func) : NULL; - status = auxgetinfo(L, what, ar, cl, ci); - if (strchr(what, 'f')) { - setobjs2s(L, L->top, func); - api_incr_top(L); - } - if (strchr(what, 'L')) - collectvalidlines(L, cl); - lua_unlock(L); - return status; -} - - -/* -** {====================================================== -** Symbolic Execution -** ======================================================= -*/ - -static const char *getobjname (Proto *p, int lastpc, int reg, - const char **name); - - -/* -** find a "name" for the RK value 'c' -*/ -static void kname (Proto *p, int pc, int c, const char **name) { - if (ISK(c)) { /* is 'c' a constant? */ - TValue *kvalue = &p->k[INDEXK(c)]; - if (ttisstring(kvalue)) { /* literal constant? */ - *name = svalue(kvalue); /* it is its own name */ - return; - } - /* else no reasonable name found */ - } - else { /* 'c' is a register */ - const char *what = getobjname(p, pc, c, name); /* search for 'c' */ - if (what && *what == 'c') { /* found a constant name? */ - return; /* 'name' already filled */ - } - /* else no reasonable name found */ - } - *name = "?"; /* no reasonable name found */ -} - - -/* -** try to find last instruction before 'lastpc' that modified register 'reg' -*/ -static int findsetreg (Proto *p, int lastpc, int reg) { - int pc; - int setreg = -1; /* keep last instruction that changed 'reg' */ - for (pc = 0; pc < lastpc; pc++) { - Instruction i = p->code[pc]; - OpCode op = GET_OPCODE(i); - int a = GETARG_A(i); - switch (op) { - case OP_LOADNIL: { - int b = GETARG_B(i); - if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */ - setreg = pc; - break; - } - case OP_TFORCALL: { - if (reg >= a + 2) setreg = pc; /* affect all regs above its base */ - break; - } - case OP_CALL: - case OP_TAILCALL: { - if (reg >= a) setreg = pc; /* affect all registers above base */ - break; - } - case OP_JMP: { - int b = GETARG_sBx(i); - int dest = pc + 1 + b; - /* jump is forward and do not skip `lastpc'? */ - if (pc < dest && dest <= lastpc) - pc += b; /* do the jump */ - break; - } - case OP_TEST: { - if (reg == a) setreg = pc; /* jumped code can change 'a' */ - break; - } - default: - if (testAMode(op) && reg == a) /* any instruction that set A */ - setreg = pc; - break; - } - } - return setreg; -} - - -static const char *getobjname (Proto *p, int lastpc, int reg, - const char **name) { - int pc; - *name = luaF_getlocalname(p, reg + 1, lastpc); - if (*name) /* is a local? */ - return "local"; - /* else try symbolic execution */ - pc = findsetreg(p, lastpc, reg); - if (pc != -1) { /* could find instruction? */ - Instruction i = p->code[pc]; - OpCode op = GET_OPCODE(i); - switch (op) { - case OP_MOVE: { - int b = GETARG_B(i); /* move from 'b' to 'a' */ - if (b < GETARG_A(i)) - return getobjname(p, pc, b, name); /* get name for 'b' */ - break; - } - case OP_GETTABUP: - case OP_GETTABLE: { - int k = GETARG_C(i); /* key index */ - int t = GETARG_B(i); /* table index */ - const char *vn = (op == OP_GETTABLE) /* name of indexed variable */ - ? luaF_getlocalname(p, t + 1, pc) - : upvalname(p, t); - kname(p, pc, k, name); - return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field"; - } - case OP_GETUPVAL: { - *name = upvalname(p, GETARG_B(i)); - return "upvalue"; - } - case OP_LOADK: - case OP_LOADKX: { - int b = (op == OP_LOADK) ? GETARG_Bx(i) - : GETARG_Ax(p->code[pc + 1]); - if (ttisstring(&p->k[b])) { - *name = svalue(&p->k[b]); - return "constant"; - } - break; - } - case OP_SELF: { - int k = GETARG_C(i); /* key index */ - kname(p, pc, k, name); - return "method"; - } - default: break; /* go through to return NULL */ - } - } - return NULL; /* could not find reasonable name */ -} - - -static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { - TMS tm; - Proto *p = ci_func(ci)->p; /* calling function */ - int pc = currentpc(ci); /* calling instruction index */ - Instruction i = p->code[pc]; /* calling instruction */ - switch (GET_OPCODE(i)) { - case OP_CALL: - case OP_TAILCALL: /* get function name */ - return getobjname(p, pc, GETARG_A(i), name); - case OP_TFORCALL: { /* for iterator */ - *name = "for iterator"; - return "for iterator"; - } - /* all other instructions can call only through metamethods */ - case OP_SELF: - case OP_GETTABUP: - case OP_GETTABLE: tm = TM_INDEX; break; - case OP_SETTABUP: - case OP_SETTABLE: tm = TM_NEWINDEX; break; - case OP_EQ: tm = TM_EQ; break; - case OP_ADD: tm = TM_ADD; break; - case OP_SUB: tm = TM_SUB; break; - case OP_MUL: tm = TM_MUL; break; - case OP_DIV: tm = TM_DIV; break; - case OP_MOD: tm = TM_MOD; break; - case OP_POW: tm = TM_POW; break; - case OP_UNM: tm = TM_UNM; break; - case OP_LEN: tm = TM_LEN; break; - case OP_LT: tm = TM_LT; break; - case OP_LE: tm = TM_LE; break; - case OP_CONCAT: tm = TM_CONCAT; break; - default: - return NULL; /* else no useful name can be found */ - } - *name = getstr(G(L)->tmname[tm]); - return "metamethod"; -} - -/* }====================================================== */ - - - -/* -** only ANSI way to check whether a pointer points to an array -** (used only for error messages, so efficiency is not a big concern) -*/ -static int isinstack (CallInfo *ci, const TValue *o) { - StkId p; - for (p = ci->u.l.base; p < ci->top; p++) - if (o == p) return 1; - return 0; -} - - -static const char *getupvalname (CallInfo *ci, const TValue *o, - const char **name) { - LClosure *c = ci_func(ci); - int i; - for (i = 0; i < c->nupvalues; i++) { - if (c->upvals[i]->v == o) { - *name = upvalname(c->p, i); - return "upvalue"; - } - } - return NULL; -} - - -l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { - CallInfo *ci = L->ci; - const char *name = NULL; - const char *t = objtypename(o); - const char *kind = NULL; - if (isLua(ci)) { - kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ - if (!kind && isinstack(ci, o)) /* no? try a register */ - kind = getobjname(ci_func(ci)->p, currentpc(ci), - cast_int(o - ci->u.l.base), &name); - } - if (kind) - luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", - op, kind, name, t); - else - luaG_runerror(L, "attempt to %s a %s value", op, t); -} - - -l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2) { - if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; - lua_assert(!ttisstring(p1) && !ttisnumber(p2)); - luaG_typeerror(L, p1, "concatenate"); -} - - -l_noret luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { - TValue temp; - if (luaV_tonumber(p1, &temp) == NULL) - p2 = p1; /* first operand is wrong */ - luaG_typeerror(L, p2, "perform arithmetic on"); -} - - -l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { - const char *t1 = objtypename(p1); - const char *t2 = objtypename(p2); - if (t1 == t2) - luaG_runerror(L, "attempt to compare two %s values", t1); - else - luaG_runerror(L, "attempt to compare %s with %s", t1, t2); -} - - -static void addinfo (lua_State *L, const char *msg) { - CallInfo *ci = L->ci; - if (isLua(ci)) { /* is Lua code? */ - char buff[LUA_IDSIZE]; /* add file:line information */ - int line = currentline(ci); - TString *src = ci_func(ci)->p->source; - if (src) - luaO_chunkid(buff, getstr(src), LUA_IDSIZE); - else { /* no source available; use "?" instead */ - buff[0] = '?'; buff[1] = '\0'; - } - luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); - } -} - - -l_noret luaG_errormsg (lua_State *L) { - if (L->errfunc != 0) { /* is there an error handling function? */ - StkId errfunc = restorestack(L, L->errfunc); - if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); - setobjs2s(L, L->top, L->top - 1); /* move argument */ - setobjs2s(L, L->top - 1, errfunc); /* push function */ - L->top++; - luaD_call(L, L->top - 2, 1, 0); /* call it */ - } - luaD_throw(L, LUA_ERRRUN); -} - - -l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { - va_list argp; - va_start(argp, fmt); - addinfo(L, luaO_pushvfstring(L, fmt, argp)); - va_end(argp); - luaG_errormsg(L); -} - diff --git a/contrib/lua/lua/src/ldebug.h b/contrib/lua/lua/src/ldebug.h deleted file mode 100644 index fe39556b062..00000000000 --- a/contrib/lua/lua/src/ldebug.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -** $Id: ldebug.h,v 2.7 2011/10/07 20:45:19 roberto Exp $ -** Auxiliary functions from Debug Interface module -** See Copyright Notice in lua.h -*/ - -#ifndef ldebug_h -#define ldebug_h - - -#include "lstate.h" - - -#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) - -#define getfuncline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) - -#define resethookcount(L) (L->hookcount = L->basehookcount) - -/* Active Lua function (given call info) */ -#define ci_func(ci) (clLvalue((ci)->func)) - - -LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, - const char *opname); -LUAI_FUNC l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2); -LUAI_FUNC l_noret luaG_aritherror (lua_State *L, const TValue *p1, - const TValue *p2); -LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1, - const TValue *p2); -LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...); -LUAI_FUNC l_noret luaG_errormsg (lua_State *L); - -#endif diff --git a/contrib/lua/lua/src/ldo.c b/contrib/lua/lua/src/ldo.c deleted file mode 100644 index aafa3dca234..00000000000 --- a/contrib/lua/lua/src/ldo.c +++ /dev/null @@ -1,673 +0,0 @@ -/* -** $Id: ldo.c,v 2.108 2012/10/01 14:05:04 roberto Exp $ -** Stack and Call structure of Lua -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include - -#define ldo_c -#define LUA_CORE - -#include "lua.h" - -#include "lapi.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lundump.h" -#include "lvm.h" -#include "lzio.h" - - - - -/* -** {====================================================== -** Error-recovery functions -** ======================================================= -*/ - -/* -** LUAI_THROW/LUAI_TRY define how Lua does exception handling. By -** default, Lua handles errors with exceptions when compiling as -** C++ code, with _longjmp/_setjmp when asked to use them, and with -** longjmp/setjmp otherwise. -*/ -#if !defined(LUAI_THROW) - -#if defined(__cplusplus) && !defined(LUA_USE_LONGJMP) -/* C++ exceptions */ -#define LUAI_THROW(L,c) throw(c) -#define LUAI_TRY(L,c,a) \ - try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; } -#define luai_jmpbuf int /* dummy variable */ - -#elif defined(LUA_USE_ULONGJMP) -/* in Unix, try _longjmp/_setjmp (more efficient) */ -#define LUAI_THROW(L,c) _longjmp((c)->b, 1) -#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } -#define luai_jmpbuf jmp_buf - -#else -/* default handling with long jumps */ -#define LUAI_THROW(L,c) longjmp((c)->b, 1) -#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } -#define luai_jmpbuf jmp_buf - -#endif - -#endif - - - -/* chain list of long jump buffers */ -struct lua_longjmp { - struct lua_longjmp *previous; - luai_jmpbuf b; - volatile int status; /* error code */ -}; - - -static void seterrorobj (lua_State *L, int errcode, StkId oldtop) { - switch (errcode) { - case LUA_ERRMEM: { /* memory error? */ - setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ - break; - } - case LUA_ERRERR: { - setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); - break; - } - default: { - setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ - break; - } - } - L->top = oldtop + 1; -} - - -l_noret luaD_throw (lua_State *L, int errcode) { - if (L->errorJmp) { /* thread has an error handler? */ - L->errorJmp->status = errcode; /* set status */ - LUAI_THROW(L, L->errorJmp); /* jump to it */ - } - else { /* thread has no error handler */ - L->status = cast_byte(errcode); /* mark it as dead */ - if (G(L)->mainthread->errorJmp) { /* main thread has a handler? */ - setobjs2s(L, G(L)->mainthread->top++, L->top - 1); /* copy error obj. */ - luaD_throw(G(L)->mainthread, errcode); /* re-throw in main thread */ - } - else { /* no handler at all; abort */ - if (G(L)->panic) { /* panic function? */ - lua_unlock(L); - G(L)->panic(L); /* call it (last chance to jump out) */ - } - abort(); - } - } -} - - -int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { - unsigned short oldnCcalls = L->nCcalls; - struct lua_longjmp lj; - lj.status = LUA_OK; - lj.previous = L->errorJmp; /* chain new error handler */ - L->errorJmp = &lj; - LUAI_TRY(L, &lj, - (*f)(L, ud); - ); - L->errorJmp = lj.previous; /* restore old error handler */ - L->nCcalls = oldnCcalls; - return lj.status; -} - -/* }====================================================== */ - - -static void correctstack (lua_State *L, TValue *oldstack) { - CallInfo *ci; - GCObject *up; - L->top = (L->top - oldstack) + L->stack; - for (up = L->openupval; up != NULL; up = up->gch.next) - gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; - for (ci = L->ci; ci != NULL; ci = ci->previous) { - ci->top = (ci->top - oldstack) + L->stack; - ci->func = (ci->func - oldstack) + L->stack; - if (isLua(ci)) - ci->u.l.base = (ci->u.l.base - oldstack) + L->stack; - } -} - - -/* some space for error handling */ -#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) - - -void luaD_reallocstack (lua_State *L, int newsize) { - TValue *oldstack = L->stack; - int lim = L->stacksize; - lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); - lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); - luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue); - for (; lim < newsize; lim++) - setnilvalue(L->stack + lim); /* erase new segment */ - L->stacksize = newsize; - L->stack_last = L->stack + newsize - EXTRA_STACK; - correctstack(L, oldstack); -} - - -void luaD_growstack (lua_State *L, int n) { - int size = L->stacksize; - if (size > LUAI_MAXSTACK) /* error after extra size? */ - luaD_throw(L, LUA_ERRERR); - else { - int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK; - int newsize = 2 * size; - if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK; - if (newsize < needed) newsize = needed; - if (newsize > LUAI_MAXSTACK) { /* stack overflow? */ - luaD_reallocstack(L, ERRORSTACKSIZE); - luaG_runerror(L, "stack overflow"); - } - else - luaD_reallocstack(L, newsize); - } -} - - -static int stackinuse (lua_State *L) { - CallInfo *ci; - StkId lim = L->top; - for (ci = L->ci; ci != NULL; ci = ci->previous) { - lua_assert(ci->top <= L->stack_last); - if (lim < ci->top) lim = ci->top; - } - return cast_int(lim - L->stack) + 1; /* part of stack in use */ -} - - -void luaD_shrinkstack (lua_State *L) { - int inuse = stackinuse(L); - int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK; - if (goodsize > LUAI_MAXSTACK) goodsize = LUAI_MAXSTACK; - if (inuse > LUAI_MAXSTACK || /* handling stack overflow? */ - goodsize >= L->stacksize) /* would grow instead of shrink? */ - condmovestack(L); /* don't change stack (change only for debugging) */ - else - luaD_reallocstack(L, goodsize); /* shrink it */ -} - - -void luaD_hook (lua_State *L, int event, int line) { - lua_Hook hook = L->hook; - if (hook && L->allowhook) { - CallInfo *ci = L->ci; - ptrdiff_t top = savestack(L, L->top); - ptrdiff_t ci_top = savestack(L, ci->top); - lua_Debug ar; - ar.event = event; - ar.currentline = line; - ar.i_ci = ci; - luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ - ci->top = L->top + LUA_MINSTACK; - lua_assert(ci->top <= L->stack_last); - L->allowhook = 0; /* cannot call hooks inside a hook */ - ci->callstatus |= CIST_HOOKED; - lua_unlock(L); - (*hook)(L, &ar); - lua_lock(L); - lua_assert(!L->allowhook); - L->allowhook = 1; - ci->top = restorestack(L, ci_top); - L->top = restorestack(L, top); - ci->callstatus &= ~CIST_HOOKED; - } -} - - -static void callhook (lua_State *L, CallInfo *ci) { - int hook = LUA_HOOKCALL; - ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ - if (isLua(ci->previous) && - GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) { - ci->callstatus |= CIST_TAIL; - hook = LUA_HOOKTAILCALL; - } - luaD_hook(L, hook, -1); - ci->u.l.savedpc--; /* correct 'pc' */ -} - - -static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { - int i; - int nfixargs = p->numparams; - StkId base, fixed; - lua_assert(actual >= nfixargs); - /* move fixed parameters to final position */ - fixed = L->top - actual; /* first fixed argument */ - base = L->top; /* final position of first argument */ - for (i=0; itop++, fixed + i); - setnilvalue(fixed + i); - } - return base; -} - - -static StkId tryfuncTM (lua_State *L, StkId func) { - const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL); - StkId p; - ptrdiff_t funcr = savestack(L, func); - if (!ttisfunction(tm)) - luaG_typeerror(L, func, "call"); - /* Open a hole inside the stack at `func' */ - for (p = L->top; p > func; p--) setobjs2s(L, p, p-1); - incr_top(L); - func = restorestack(L, funcr); /* previous call may change stack */ - setobj2s(L, func, tm); /* tag method is the new function to be called */ - return func; -} - - - -#define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L))) - - -/* -** returns true if function has been executed (C function) -*/ -int luaD_precall (lua_State *L, StkId func, int nresults) { - lua_CFunction f; - CallInfo *ci; - int n; /* number of arguments (Lua) or returns (C) */ - ptrdiff_t funcr = savestack(L, func); - switch (ttype(func)) { - case LUA_TLCF: /* light C function */ - f = fvalue(func); - goto Cfunc; - case LUA_TCCL: { /* C closure */ - f = clCvalue(func)->f; - Cfunc: - luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ - ci = next_ci(L); /* now 'enter' new function */ - ci->nresults = nresults; - ci->func = restorestack(L, funcr); - ci->top = L->top + LUA_MINSTACK; - lua_assert(ci->top <= L->stack_last); - ci->callstatus = 0; - luaC_checkGC(L); /* stack grow uses memory */ - if (L->hookmask & LUA_MASKCALL) - luaD_hook(L, LUA_HOOKCALL, -1); - lua_unlock(L); - n = (*f)(L); /* do the actual call */ - lua_lock(L); - api_checknelems(L, n); - luaD_poscall(L, L->top - n); - return 1; - } - case LUA_TLCL: { /* Lua function: prepare its call */ - StkId base; - Proto *p = clLvalue(func)->p; - luaD_checkstack(L, p->maxstacksize); - func = restorestack(L, funcr); - n = cast_int(L->top - func) - 1; /* number of real arguments */ - for (; n < p->numparams; n++) - setnilvalue(L->top++); /* complete missing arguments */ - base = (!p->is_vararg) ? func + 1 : adjust_varargs(L, p, n); - ci = next_ci(L); /* now 'enter' new function */ - ci->nresults = nresults; - ci->func = func; - ci->u.l.base = base; - ci->top = base + p->maxstacksize; - lua_assert(ci->top <= L->stack_last); - ci->u.l.savedpc = p->code; /* starting point */ - ci->callstatus = CIST_LUA; - L->top = ci->top; - luaC_checkGC(L); /* stack grow uses memory */ - if (L->hookmask & LUA_MASKCALL) - callhook(L, ci); - return 0; - } - default: { /* not a function */ - func = tryfuncTM(L, func); /* retry with 'function' tag method */ - return luaD_precall(L, func, nresults); /* now it must be a function */ - } - } -} - - -int luaD_poscall (lua_State *L, StkId firstResult) { - StkId res; - int wanted, i; - CallInfo *ci = L->ci; - if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { - if (L->hookmask & LUA_MASKRET) { - ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ - luaD_hook(L, LUA_HOOKRET, -1); - firstResult = restorestack(L, fr); - } - L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */ - } - res = ci->func; /* res == final position of 1st result */ - wanted = ci->nresults; - L->ci = ci = ci->previous; /* back to caller */ - /* move results to correct place */ - for (i = wanted; i != 0 && firstResult < L->top; i--) - setobjs2s(L, res++, firstResult++); - while (i-- > 0) - setnilvalue(res++); - L->top = res; - return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */ -} - - -/* -** Call a function (C or Lua). The function to be called is at *func. -** The arguments are on the stack, right after the function. -** When returns, all the results are on the stack, starting at the original -** function position. -*/ -void luaD_call (lua_State *L, StkId func, int nResults, int allowyield) { - if (++L->nCcalls >= LUAI_MAXCCALLS) { - if (L->nCcalls == LUAI_MAXCCALLS) - luaG_runerror(L, "C stack overflow"); - else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) - luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ - } - if (!allowyield) L->nny++; - if (!luaD_precall(L, func, nResults)) /* is a Lua function? */ - luaV_execute(L); /* call it */ - if (!allowyield) L->nny--; - L->nCcalls--; -} - - -static void finishCcall (lua_State *L) { - CallInfo *ci = L->ci; - int n; - lua_assert(ci->u.c.k != NULL); /* must have a continuation */ - lua_assert(L->nny == 0); - if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */ - ci->callstatus &= ~CIST_YPCALL; /* finish 'lua_pcall' */ - L->errfunc = ci->u.c.old_errfunc; - } - /* finish 'lua_callk'/'lua_pcall' */ - adjustresults(L, ci->nresults); - /* call continuation function */ - if (!(ci->callstatus & CIST_STAT)) /* no call status? */ - ci->u.c.status = LUA_YIELD; /* 'default' status */ - lua_assert(ci->u.c.status != LUA_OK); - ci->callstatus = (ci->callstatus & ~(CIST_YPCALL | CIST_STAT)) | CIST_YIELDED; - lua_unlock(L); - n = (*ci->u.c.k)(L); - lua_lock(L); - api_checknelems(L, n); - /* finish 'luaD_precall' */ - luaD_poscall(L, L->top - n); -} - - -static void unroll (lua_State *L, void *ud) { - UNUSED(ud); - for (;;) { - if (L->ci == &L->base_ci) /* stack is empty? */ - return; /* coroutine finished normally */ - if (!isLua(L->ci)) /* C function? */ - finishCcall(L); - else { /* Lua function */ - luaV_finishOp(L); /* finish interrupted instruction */ - luaV_execute(L); /* execute down to higher C 'boundary' */ - } - } -} - - -/* -** check whether thread has a suspended protected call -*/ -static CallInfo *findpcall (lua_State *L) { - CallInfo *ci; - for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */ - if (ci->callstatus & CIST_YPCALL) - return ci; - } - return NULL; /* no pending pcall */ -} - - -static int recover (lua_State *L, int status) { - StkId oldtop; - CallInfo *ci = findpcall(L); - if (ci == NULL) return 0; /* no recovery point */ - /* "finish" luaD_pcall */ - oldtop = restorestack(L, ci->extra); - luaF_close(L, oldtop); - seterrorobj(L, status, oldtop); - L->ci = ci; - L->allowhook = ci->u.c.old_allowhook; - L->nny = 0; /* should be zero to be yieldable */ - luaD_shrinkstack(L); - L->errfunc = ci->u.c.old_errfunc; - ci->callstatus |= CIST_STAT; /* call has error status */ - ci->u.c.status = status; /* (here it is) */ - return 1; /* continue running the coroutine */ -} - - -/* -** signal an error in the call to 'resume', not in the execution of the -** coroutine itself. (Such errors should not be handled by any coroutine -** error handler and should not kill the coroutine.) -*/ -static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) { - L->top = firstArg; /* remove args from the stack */ - setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */ - api_incr_top(L); - luaD_throw(L, -1); /* jump back to 'lua_resume' */ -} - - -/* -** do the work for 'lua_resume' in protected mode -*/ -static void resume (lua_State *L, void *ud) { - int nCcalls = L->nCcalls; - StkId firstArg = cast(StkId, ud); - CallInfo *ci = L->ci; - if (nCcalls >= LUAI_MAXCCALLS) - resume_error(L, "C stack overflow", firstArg); - if (L->status == LUA_OK) { /* may be starting a coroutine */ - if (ci != &L->base_ci) /* not in base level? */ - resume_error(L, "cannot resume non-suspended coroutine", firstArg); - /* coroutine is in base level; start running it */ - if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */ - luaV_execute(L); /* call it */ - } - else if (L->status != LUA_YIELD) - resume_error(L, "cannot resume dead coroutine", firstArg); - else { /* resuming from previous yield */ - L->status = LUA_OK; - ci->func = restorestack(L, ci->extra); - if (isLua(ci)) /* yielded inside a hook? */ - luaV_execute(L); /* just continue running Lua code */ - else { /* 'common' yield */ - if (ci->u.c.k != NULL) { /* does it have a continuation? */ - int n; - ci->u.c.status = LUA_YIELD; /* 'default' status */ - ci->callstatus |= CIST_YIELDED; - lua_unlock(L); - n = (*ci->u.c.k)(L); /* call continuation */ - lua_lock(L); - api_checknelems(L, n); - firstArg = L->top - n; /* yield results come from continuation */ - } - luaD_poscall(L, firstArg); /* finish 'luaD_precall' */ - } - unroll(L, NULL); - } - lua_assert(nCcalls == L->nCcalls); -} - - -LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) { - int status; - lua_lock(L); - luai_userstateresume(L, nargs); - L->nCcalls = (from) ? from->nCcalls + 1 : 1; - L->nny = 0; /* allow yields */ - api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); - status = luaD_rawrunprotected(L, resume, L->top - nargs); - if (status == -1) /* error calling 'lua_resume'? */ - status = LUA_ERRRUN; - else { /* yield or regular error */ - while (status != LUA_OK && status != LUA_YIELD) { /* error? */ - if (recover(L, status)) /* recover point? */ - status = luaD_rawrunprotected(L, unroll, NULL); /* run continuation */ - else { /* unrecoverable error */ - L->status = cast_byte(status); /* mark thread as `dead' */ - seterrorobj(L, status, L->top); - L->ci->top = L->top; - break; - } - } - lua_assert(status == L->status); - } - L->nny = 1; /* do not allow yields */ - L->nCcalls--; - lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0)); - lua_unlock(L); - return status; -} - - -LUA_API int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k) { - CallInfo *ci = L->ci; - luai_userstateyield(L, nresults); - lua_lock(L); - api_checknelems(L, nresults); - if (L->nny > 0) { - if (L != G(L)->mainthread) - luaG_runerror(L, "attempt to yield across a C-call boundary"); - else - luaG_runerror(L, "attempt to yield from outside a coroutine"); - } - L->status = LUA_YIELD; - ci->extra = savestack(L, ci->func); /* save current 'func' */ - if (isLua(ci)) { /* inside a hook? */ - api_check(L, k == NULL, "hooks cannot continue after yielding"); - } - else { - if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ - ci->u.c.ctx = ctx; /* save context */ - ci->func = L->top - nresults - 1; /* protect stack below results */ - luaD_throw(L, LUA_YIELD); - } - lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ - lua_unlock(L); - return 0; /* return to 'luaD_hook' */ -} - - -int luaD_pcall (lua_State *L, Pfunc func, void *u, - ptrdiff_t old_top, ptrdiff_t ef) { - int status; - CallInfo *old_ci = L->ci; - lu_byte old_allowhooks = L->allowhook; - unsigned short old_nny = L->nny; - ptrdiff_t old_errfunc = L->errfunc; - L->errfunc = ef; - status = luaD_rawrunprotected(L, func, u); - if (status != LUA_OK) { /* an error occurred? */ - StkId oldtop = restorestack(L, old_top); - luaF_close(L, oldtop); /* close possible pending closures */ - seterrorobj(L, status, oldtop); - L->ci = old_ci; - L->allowhook = old_allowhooks; - L->nny = old_nny; - luaD_shrinkstack(L); - } - L->errfunc = old_errfunc; - return status; -} - - - -/* -** Execute a protected parser. -*/ -struct SParser { /* data to `f_parser' */ - ZIO *z; - Mbuffer buff; /* dynamic structure used by the scanner */ - Dyndata dyd; /* dynamic structures used by the parser */ - const char *mode; - const char *name; -}; - - -static void checkmode (lua_State *L, const char *mode, const char *x) { - if (mode && strchr(mode, x[0]) == NULL) { - luaO_pushfstring(L, - "attempt to load a %s chunk (mode is " LUA_QS ")", x, mode); - luaD_throw(L, LUA_ERRSYNTAX); - } -} - - -static void f_parser (lua_State *L, void *ud) { - int i; - Closure *cl; - struct SParser *p = cast(struct SParser *, ud); - int c = zgetc(p->z); /* read first character */ - if (c == LUA_SIGNATURE[0]) { - checkmode(L, p->mode, "binary"); - cl = luaU_undump(L, p->z, &p->buff, p->name); - } - else { - checkmode(L, p->mode, "text"); - cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); - } - lua_assert(cl->l.nupvalues == cl->l.p->sizeupvalues); - for (i = 0; i < cl->l.nupvalues; i++) { /* initialize upvalues */ - UpVal *up = luaF_newupval(L); - cl->l.upvals[i] = up; - luaC_objbarrier(L, cl, up); - } -} - - -int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, - const char *mode) { - struct SParser p; - int status; - L->nny++; /* cannot yield during parsing */ - p.z = z; p.name = name; p.mode = mode; - p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0; - p.dyd.gt.arr = NULL; p.dyd.gt.size = 0; - p.dyd.label.arr = NULL; p.dyd.label.size = 0; - luaZ_initbuffer(L, &p.buff); - status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); - luaZ_freebuffer(L, &p.buff); - luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size); - luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size); - luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size); - L->nny--; - return status; -} - - diff --git a/contrib/lua/lua/src/ldo.h b/contrib/lua/lua/src/ldo.h deleted file mode 100644 index 27b837d999e..00000000000 --- a/contrib/lua/lua/src/ldo.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -** $Id: ldo.h,v 2.20 2011/11/29 15:55:08 roberto Exp $ -** Stack and Call structure of Lua -** See Copyright Notice in lua.h -*/ - -#ifndef ldo_h -#define ldo_h - - -#include "lobject.h" -#include "lstate.h" -#include "lzio.h" - - -#define luaD_checkstack(L,n) if (L->stack_last - L->top <= (n)) \ - luaD_growstack(L, n); else condmovestack(L); - - -#define incr_top(L) {L->top++; luaD_checkstack(L,0);} - -#define savestack(L,p) ((char *)(p) - (char *)L->stack) -#define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) - - -/* type of protected functions, to be ran by `runprotected' */ -typedef void (*Pfunc) (lua_State *L, void *ud); - -LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, - const char *mode); -LUAI_FUNC void luaD_hook (lua_State *L, int event, int line); -LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); -LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults, - int allowyield); -LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, - ptrdiff_t oldtop, ptrdiff_t ef); -LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); -LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); -LUAI_FUNC void luaD_growstack (lua_State *L, int n); -LUAI_FUNC void luaD_shrinkstack (lua_State *L); - -LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode); -LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); - -#endif - diff --git a/contrib/lua/lua/src/ldump.c b/contrib/lua/lua/src/ldump.c deleted file mode 100644 index d5e6a47cb38..00000000000 --- a/contrib/lua/lua/src/ldump.c +++ /dev/null @@ -1,173 +0,0 @@ -/* -** $Id: ldump.c,v 2.17 2012/01/23 23:02:10 roberto Exp $ -** save precompiled Lua chunks -** See Copyright Notice in lua.h -*/ - -#include - -#define ldump_c -#define LUA_CORE - -#include "lua.h" - -#include "lobject.h" -#include "lstate.h" -#include "lundump.h" - -typedef struct { - lua_State* L; - lua_Writer writer; - void* data; - int strip; - int status; -} DumpState; - -#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) -#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) - -static void DumpBlock(const void* b, size_t size, DumpState* D) -{ - if (D->status==0) - { - lua_unlock(D->L); - D->status=(*D->writer)(D->L,b,size,D->data); - lua_lock(D->L); - } -} - -static void DumpChar(int y, DumpState* D) -{ - char x=(char)y; - DumpVar(x,D); -} - -static void DumpInt(int x, DumpState* D) -{ - DumpVar(x,D); -} - -static void DumpNumber(lua_Number x, DumpState* D) -{ - DumpVar(x,D); -} - -static void DumpVector(const void* b, int n, size_t size, DumpState* D) -{ - DumpInt(n,D); - DumpMem(b,n,size,D); -} - -static void DumpString(const TString* s, DumpState* D) -{ - if (s==NULL) - { - size_t size=0; - DumpVar(size,D); - } - else - { - size_t size=s->tsv.len+1; /* include trailing '\0' */ - DumpVar(size,D); - DumpBlock(getstr(s),size*sizeof(char),D); - } -} - -#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) - -static void DumpFunction(const Proto* f, DumpState* D); - -static void DumpConstants(const Proto* f, DumpState* D) -{ - int i,n=f->sizek; - DumpInt(n,D); - for (i=0; ik[i]; - DumpChar(ttypenv(o),D); - switch (ttypenv(o)) - { - case LUA_TNIL: - break; - case LUA_TBOOLEAN: - DumpChar(bvalue(o),D); - break; - case LUA_TNUMBER: - DumpNumber(nvalue(o),D); - break; - case LUA_TSTRING: - DumpString(rawtsvalue(o),D); - break; - default: lua_assert(0); - } - } - n=f->sizep; - DumpInt(n,D); - for (i=0; ip[i],D); -} - -static void DumpUpvalues(const Proto* f, DumpState* D) -{ - int i,n=f->sizeupvalues; - DumpInt(n,D); - for (i=0; iupvalues[i].instack,D); - DumpChar(f->upvalues[i].idx,D); - } -} - -static void DumpDebug(const Proto* f, DumpState* D) -{ - int i,n; - DumpString((D->strip) ? NULL : f->source,D); - n= (D->strip) ? 0 : f->sizelineinfo; - DumpVector(f->lineinfo,n,sizeof(int),D); - n= (D->strip) ? 0 : f->sizelocvars; - DumpInt(n,D); - for (i=0; ilocvars[i].varname,D); - DumpInt(f->locvars[i].startpc,D); - DumpInt(f->locvars[i].endpc,D); - } - n= (D->strip) ? 0 : f->sizeupvalues; - DumpInt(n,D); - for (i=0; iupvalues[i].name,D); -} - -static void DumpFunction(const Proto* f, DumpState* D) -{ - DumpInt(f->linedefined,D); - DumpInt(f->lastlinedefined,D); - DumpChar(f->numparams,D); - DumpChar(f->is_vararg,D); - DumpChar(f->maxstacksize,D); - DumpCode(f,D); - DumpConstants(f,D); - DumpUpvalues(f,D); - DumpDebug(f,D); -} - -static void DumpHeader(DumpState* D) -{ - lu_byte h[LUAC_HEADERSIZE]; - luaU_header(h); - DumpBlock(h,LUAC_HEADERSIZE,D); -} - -/* -** dump Lua function as precompiled chunk -*/ -int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) -{ - DumpState D; - D.L=L; - D.writer=w; - D.data=data; - D.strip=strip; - D.status=0; - DumpHeader(&D); - DumpFunction(f,&D); - return D.status; -} diff --git a/contrib/lua/lua/src/lfunc.c b/contrib/lua/lua/src/lfunc.c deleted file mode 100644 index c2128405b9a..00000000000 --- a/contrib/lua/lua/src/lfunc.c +++ /dev/null @@ -1,161 +0,0 @@ -/* -** $Id: lfunc.c,v 2.30 2012/10/03 12:36:46 roberto Exp $ -** Auxiliary functions to manipulate prototypes and closures -** See Copyright Notice in lua.h -*/ - - -#include - -#define lfunc_c -#define LUA_CORE - -#include "lua.h" - -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" - - - -Closure *luaF_newCclosure (lua_State *L, int n) { - Closure *c = &luaC_newobj(L, LUA_TCCL, sizeCclosure(n), NULL, 0)->cl; - c->c.nupvalues = cast_byte(n); - return c; -} - - -Closure *luaF_newLclosure (lua_State *L, int n) { - Closure *c = &luaC_newobj(L, LUA_TLCL, sizeLclosure(n), NULL, 0)->cl; - c->l.p = NULL; - c->l.nupvalues = cast_byte(n); - while (n--) c->l.upvals[n] = NULL; - return c; -} - - -UpVal *luaF_newupval (lua_State *L) { - UpVal *uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), NULL, 0)->uv; - uv->v = &uv->u.value; - setnilvalue(uv->v); - return uv; -} - - -UpVal *luaF_findupval (lua_State *L, StkId level) { - global_State *g = G(L); - GCObject **pp = &L->openupval; - UpVal *p; - UpVal *uv; - while (*pp != NULL && (p = gco2uv(*pp))->v >= level) { - GCObject *o = obj2gco(p); - lua_assert(p->v != &p->u.value); - lua_assert(!isold(o) || isold(obj2gco(L))); - if (p->v == level) { /* found a corresponding upvalue? */ - if (isdead(g, o)) /* is it dead? */ - changewhite(o); /* resurrect it */ - return p; - } - pp = &p->next; - } - /* not found: create a new one */ - uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), pp, 0)->uv; - uv->v = level; /* current value lives in the stack */ - uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ - uv->u.l.next = g->uvhead.u.l.next; - uv->u.l.next->u.l.prev = uv; - g->uvhead.u.l.next = uv; - lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); - return uv; -} - - -static void unlinkupval (UpVal *uv) { - lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); - uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */ - uv->u.l.prev->u.l.next = uv->u.l.next; -} - - -void luaF_freeupval (lua_State *L, UpVal *uv) { - if (uv->v != &uv->u.value) /* is it open? */ - unlinkupval(uv); /* remove from open list */ - luaM_free(L, uv); /* free upvalue */ -} - - -void luaF_close (lua_State *L, StkId level) { - UpVal *uv; - global_State *g = G(L); - while (L->openupval != NULL && (uv = gco2uv(L->openupval))->v >= level) { - GCObject *o = obj2gco(uv); - lua_assert(!isblack(o) && uv->v != &uv->u.value); - L->openupval = uv->next; /* remove from `open' list */ - if (isdead(g, o)) - luaF_freeupval(L, uv); /* free upvalue */ - else { - unlinkupval(uv); /* remove upvalue from 'uvhead' list */ - setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */ - uv->v = &uv->u.value; /* now current value lives here */ - gch(o)->next = g->allgc; /* link upvalue into 'allgc' list */ - g->allgc = o; - luaC_checkupvalcolor(g, uv); - } - } -} - - -Proto *luaF_newproto (lua_State *L) { - Proto *f = &luaC_newobj(L, LUA_TPROTO, sizeof(Proto), NULL, 0)->p; - f->k = NULL; - f->sizek = 0; - f->p = NULL; - f->sizep = 0; - f->code = NULL; - f->cache = NULL; - f->sizecode = 0; - f->lineinfo = NULL; - f->sizelineinfo = 0; - f->upvalues = NULL; - f->sizeupvalues = 0; - f->numparams = 0; - f->is_vararg = 0; - f->maxstacksize = 0; - f->locvars = NULL; - f->sizelocvars = 0; - f->linedefined = 0; - f->lastlinedefined = 0; - f->source = NULL; - return f; -} - - -void luaF_freeproto (lua_State *L, Proto *f) { - luaM_freearray(L, f->code, f->sizecode); - luaM_freearray(L, f->p, f->sizep); - luaM_freearray(L, f->k, f->sizek); - luaM_freearray(L, f->lineinfo, f->sizelineinfo); - luaM_freearray(L, f->locvars, f->sizelocvars); - luaM_freearray(L, f->upvalues, f->sizeupvalues); - luaM_free(L, f); -} - - -/* -** Look for n-th local variable at line `line' in function `func'. -** Returns NULL if not found. -*/ -const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { - int i; - for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { - if (pc < f->locvars[i].endpc) { /* is variable active? */ - local_number--; - if (local_number == 0) - return getstr(f->locvars[i].varname); - } - } - return NULL; /* not found */ -} - diff --git a/contrib/lua/lua/src/lfunc.h b/contrib/lua/lua/src/lfunc.h deleted file mode 100644 index e236a717c65..00000000000 --- a/contrib/lua/lua/src/lfunc.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -** $Id: lfunc.h,v 2.8 2012/05/08 13:53:33 roberto Exp $ -** Auxiliary functions to manipulate prototypes and closures -** See Copyright Notice in lua.h -*/ - -#ifndef lfunc_h -#define lfunc_h - - -#include "lobject.h" - - -#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ - cast(int, sizeof(TValue)*((n)-1))) - -#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ - cast(int, sizeof(TValue *)*((n)-1))) - - -LUAI_FUNC Proto *luaF_newproto (lua_State *L); -LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems); -LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems); -LUAI_FUNC UpVal *luaF_newupval (lua_State *L); -LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); -LUAI_FUNC void luaF_close (lua_State *L, StkId level); -LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); -LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv); -LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, - int pc); - - -#endif diff --git a/contrib/lua/lua/src/lgc.c b/contrib/lua/lua/src/lgc.c deleted file mode 100644 index 535e988ae02..00000000000 --- a/contrib/lua/lua/src/lgc.c +++ /dev/null @@ -1,1213 +0,0 @@ -/* -** $Id: lgc.c,v 2.140 2013/03/16 21:10:18 roberto Exp $ -** Garbage Collector -** See Copyright Notice in lua.h -*/ - -#include - -#define lgc_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" - - - -/* -** cost of sweeping one element (the size of a small object divided -** by some adjust for the sweep speed) -*/ -#define GCSWEEPCOST ((sizeof(TString) + 4) / 4) - -/* maximum number of elements to sweep in each single step */ -#define GCSWEEPMAX (cast_int((GCSTEPSIZE / GCSWEEPCOST) / 4)) - -/* maximum number of finalizers to call in each GC step */ -#define GCFINALIZENUM 4 - - -/* -** macro to adjust 'stepmul': 'stepmul' is actually used like -** 'stepmul / STEPMULADJ' (value chosen by tests) -*/ -#define STEPMULADJ 200 - - -/* -** macro to adjust 'pause': 'pause' is actually used like -** 'pause / PAUSEADJ' (value chosen by tests) -*/ -#define PAUSEADJ 100 - - -/* -** 'makewhite' erases all color bits plus the old bit and then -** sets only the current white bit -*/ -#define maskcolors (~(bit2mask(BLACKBIT, OLDBIT) | WHITEBITS)) -#define makewhite(g,x) \ - (gch(x)->marked = cast_byte((gch(x)->marked & maskcolors) | luaC_white(g))) - -#define white2gray(x) resetbits(gch(x)->marked, WHITEBITS) -#define black2gray(x) resetbit(gch(x)->marked, BLACKBIT) - - -#define isfinalized(x) testbit(gch(x)->marked, FINALIZEDBIT) - -#define checkdeadkey(n) lua_assert(!ttisdeadkey(gkey(n)) || ttisnil(gval(n))) - - -#define checkconsistency(obj) \ - lua_longassert(!iscollectable(obj) || righttt(obj)) - - -#define markvalue(g,o) { checkconsistency(o); \ - if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } - -#define markobject(g,t) { if ((t) && iswhite(obj2gco(t))) \ - reallymarkobject(g, obj2gco(t)); } - -static void reallymarkobject (global_State *g, GCObject *o); - - -/* -** {====================================================== -** Generic functions -** ======================================================= -*/ - - -/* -** one after last element in a hash array -*/ -#define gnodelast(h) gnode(h, cast(size_t, sizenode(h))) - - -/* -** link table 'h' into list pointed by 'p' -*/ -#define linktable(h,p) ((h)->gclist = *(p), *(p) = obj2gco(h)) - - -/* -** if key is not marked, mark its entry as dead (therefore removing it -** from the table) -*/ -static void removeentry (Node *n) { - lua_assert(ttisnil(gval(n))); - if (valiswhite(gkey(n))) - setdeadvalue(gkey(n)); /* unused and unmarked key; remove it */ -} - - -/* -** tells whether a key or value can be cleared from a weak -** table. Non-collectable objects are never removed from weak -** tables. Strings behave as `values', so are never removed too. for -** other objects: if really collected, cannot keep them; for objects -** being finalized, keep them in keys, but not in values -*/ -static int iscleared (global_State *g, const TValue *o) { - if (!iscollectable(o)) return 0; - else if (ttisstring(o)) { - markobject(g, rawtsvalue(o)); /* strings are `values', so are never weak */ - return 0; - } - else return iswhite(gcvalue(o)); -} - - -/* -** barrier that moves collector forward, that is, mark the white object -** being pointed by a black object. -*/ -void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { - global_State *g = G(L); - lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); - lua_assert(g->gcstate != GCSpause); - lua_assert(gch(o)->tt != LUA_TTABLE); - if (keepinvariantout(g)) /* must keep invariant? */ - reallymarkobject(g, v); /* restore invariant */ - else { /* sweep phase */ - lua_assert(issweepphase(g)); - makewhite(g, o); /* mark main obj. as white to avoid other barriers */ - } -} - - -/* -** barrier that moves collector backward, that is, mark the black object -** pointing to a white object as gray again. (Current implementation -** only works for tables; access to 'gclist' is not uniform across -** different types.) -*/ -void luaC_barrierback_ (lua_State *L, GCObject *o) { - global_State *g = G(L); - lua_assert(isblack(o) && !isdead(g, o) && gch(o)->tt == LUA_TTABLE); - black2gray(o); /* make object gray (again) */ - gco2t(o)->gclist = g->grayagain; - g->grayagain = o; -} - - -/* -** barrier for prototypes. When creating first closure (cache is -** NULL), use a forward barrier; this may be the only closure of the -** prototype (if it is a "regular" function, with a single instance) -** and the prototype may be big, so it is better to avoid traversing -** it again. Otherwise, use a backward barrier, to avoid marking all -** possible instances. -*/ -LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c) { - global_State *g = G(L); - lua_assert(isblack(obj2gco(p))); - if (p->cache == NULL) { /* first time? */ - luaC_objbarrier(L, p, c); - } - else { /* use a backward barrier */ - black2gray(obj2gco(p)); /* make prototype gray (again) */ - p->gclist = g->grayagain; - g->grayagain = obj2gco(p); - } -} - - -/* -** check color (and invariants) for an upvalue that was closed, -** i.e., moved into the 'allgc' list -*/ -void luaC_checkupvalcolor (global_State *g, UpVal *uv) { - GCObject *o = obj2gco(uv); - lua_assert(!isblack(o)); /* open upvalues are never black */ - if (isgray(o)) { - if (keepinvariant(g)) { - resetoldbit(o); /* see MOVE OLD rule */ - gray2black(o); /* it is being visited now */ - markvalue(g, uv->v); - } - else { - lua_assert(issweepphase(g)); - makewhite(g, o); - } - } -} - - -/* -** create a new collectable object (with given type and size) and link -** it to '*list'. 'offset' tells how many bytes to allocate before the -** object itself (used only by states). -*/ -GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, GCObject **list, - int offset) { - global_State *g = G(L); - char *raw = cast(char *, luaM_newobject(L, novariant(tt), sz)); - GCObject *o = obj2gco(raw + offset); - if (list == NULL) - list = &g->allgc; /* standard list for collectable objects */ - gch(o)->marked = luaC_white(g); - gch(o)->tt = tt; - gch(o)->next = *list; - *list = o; - return o; -} - -/* }====================================================== */ - - - -/* -** {====================================================== -** Mark functions -** ======================================================= -*/ - - -/* -** mark an object. Userdata, strings, and closed upvalues are visited -** and turned black here. Other objects are marked gray and added -** to appropriate list to be visited (and turned black) later. (Open -** upvalues are already linked in 'headuv' list.) -*/ -static void reallymarkobject (global_State *g, GCObject *o) { - lu_mem size; - white2gray(o); - switch (gch(o)->tt) { - case LUA_TSHRSTR: - case LUA_TLNGSTR: { - size = sizestring(gco2ts(o)); - break; /* nothing else to mark; make it black */ - } - case LUA_TUSERDATA: { - Table *mt = gco2u(o)->metatable; - markobject(g, mt); - markobject(g, gco2u(o)->env); - size = sizeudata(gco2u(o)); - break; - } - case LUA_TUPVAL: { - UpVal *uv = gco2uv(o); - markvalue(g, uv->v); - if (uv->v != &uv->u.value) /* open? */ - return; /* open upvalues remain gray */ - size = sizeof(UpVal); - break; - } - case LUA_TLCL: { - gco2lcl(o)->gclist = g->gray; - g->gray = o; - return; - } - case LUA_TCCL: { - gco2ccl(o)->gclist = g->gray; - g->gray = o; - return; - } - case LUA_TTABLE: { - linktable(gco2t(o), &g->gray); - return; - } - case LUA_TTHREAD: { - gco2th(o)->gclist = g->gray; - g->gray = o; - return; - } - case LUA_TPROTO: { - gco2p(o)->gclist = g->gray; - g->gray = o; - return; - } - default: lua_assert(0); return; - } - gray2black(o); - g->GCmemtrav += size; -} - - -/* -** mark metamethods for basic types -*/ -static void markmt (global_State *g) { - int i; - for (i=0; i < LUA_NUMTAGS; i++) - markobject(g, g->mt[i]); -} - - -/* -** mark all objects in list of being-finalized -*/ -static void markbeingfnz (global_State *g) { - GCObject *o; - for (o = g->tobefnz; o != NULL; o = gch(o)->next) { - makewhite(g, o); - reallymarkobject(g, o); - } -} - - -/* -** mark all values stored in marked open upvalues. (See comment in -** 'lstate.h'.) -*/ -static void remarkupvals (global_State *g) { - UpVal *uv; - for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { - if (isgray(obj2gco(uv))) - markvalue(g, uv->v); - } -} - - -/* -** mark root set and reset all gray lists, to start a new -** incremental (or full) collection -*/ -static void restartcollection (global_State *g) { - g->gray = g->grayagain = NULL; - g->weak = g->allweak = g->ephemeron = NULL; - markobject(g, g->mainthread); - markvalue(g, &g->l_registry); - markmt(g); - markbeingfnz(g); /* mark any finalizing object left from previous cycle */ -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Traverse functions -** ======================================================= -*/ - -static void traverseweakvalue (global_State *g, Table *h) { - Node *n, *limit = gnodelast(h); - /* if there is array part, assume it may have white values (do not - traverse it just to check) */ - int hasclears = (h->sizearray > 0); - for (n = gnode(h, 0); n < limit; n++) { - checkdeadkey(n); - if (ttisnil(gval(n))) /* entry is empty? */ - removeentry(n); /* remove it */ - else { - lua_assert(!ttisnil(gkey(n))); - markvalue(g, gkey(n)); /* mark key */ - if (!hasclears && iscleared(g, gval(n))) /* is there a white value? */ - hasclears = 1; /* table will have to be cleared */ - } - } - if (hasclears) - linktable(h, &g->weak); /* has to be cleared later */ - else /* no white values */ - linktable(h, &g->grayagain); /* no need to clean */ -} - - -static int traverseephemeron (global_State *g, Table *h) { - int marked = 0; /* true if an object is marked in this traversal */ - int hasclears = 0; /* true if table has white keys */ - int prop = 0; /* true if table has entry "white-key -> white-value" */ - Node *n, *limit = gnodelast(h); - int i; - /* traverse array part (numeric keys are 'strong') */ - for (i = 0; i < h->sizearray; i++) { - if (valiswhite(&h->array[i])) { - marked = 1; - reallymarkobject(g, gcvalue(&h->array[i])); - } - } - /* traverse hash part */ - for (n = gnode(h, 0); n < limit; n++) { - checkdeadkey(n); - if (ttisnil(gval(n))) /* entry is empty? */ - removeentry(n); /* remove it */ - else if (iscleared(g, gkey(n))) { /* key is not marked (yet)? */ - hasclears = 1; /* table must be cleared */ - if (valiswhite(gval(n))) /* value not marked yet? */ - prop = 1; /* must propagate again */ - } - else if (valiswhite(gval(n))) { /* value not marked yet? */ - marked = 1; - reallymarkobject(g, gcvalue(gval(n))); /* mark it now */ - } - } - if (prop) - linktable(h, &g->ephemeron); /* have to propagate again */ - else if (hasclears) /* does table have white keys? */ - linktable(h, &g->allweak); /* may have to clean white keys */ - else /* no white keys */ - linktable(h, &g->grayagain); /* no need to clean */ - return marked; -} - - -static void traversestrongtable (global_State *g, Table *h) { - Node *n, *limit = gnodelast(h); - int i; - for (i = 0; i < h->sizearray; i++) /* traverse array part */ - markvalue(g, &h->array[i]); - for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ - checkdeadkey(n); - if (ttisnil(gval(n))) /* entry is empty? */ - removeentry(n); /* remove it */ - else { - lua_assert(!ttisnil(gkey(n))); - markvalue(g, gkey(n)); /* mark key */ - markvalue(g, gval(n)); /* mark value */ - } - } -} - - -static lu_mem traversetable (global_State *g, Table *h) { - const char *weakkey, *weakvalue; - const TValue *mode = gfasttm(g, h->metatable, TM_MODE); - markobject(g, h->metatable); - if (mode && ttisstring(mode) && /* is there a weak mode? */ - ((weakkey = strchr(svalue(mode), 'k')), - (weakvalue = strchr(svalue(mode), 'v')), - (weakkey || weakvalue))) { /* is really weak? */ - black2gray(obj2gco(h)); /* keep table gray */ - if (!weakkey) /* strong keys? */ - traverseweakvalue(g, h); - else if (!weakvalue) /* strong values? */ - traverseephemeron(g, h); - else /* all weak */ - linktable(h, &g->allweak); /* nothing to traverse now */ - } - else /* not weak */ - traversestrongtable(g, h); - return sizeof(Table) + sizeof(TValue) * h->sizearray + - sizeof(Node) * cast(size_t, sizenode(h)); -} - - -static int traverseproto (global_State *g, Proto *f) { - int i; - if (f->cache && iswhite(obj2gco(f->cache))) - f->cache = NULL; /* allow cache to be collected */ - markobject(g, f->source); - for (i = 0; i < f->sizek; i++) /* mark literals */ - markvalue(g, &f->k[i]); - for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */ - markobject(g, f->upvalues[i].name); - for (i = 0; i < f->sizep; i++) /* mark nested protos */ - markobject(g, f->p[i]); - for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ - markobject(g, f->locvars[i].varname); - return sizeof(Proto) + sizeof(Instruction) * f->sizecode + - sizeof(Proto *) * f->sizep + - sizeof(TValue) * f->sizek + - sizeof(int) * f->sizelineinfo + - sizeof(LocVar) * f->sizelocvars + - sizeof(Upvaldesc) * f->sizeupvalues; -} - - -static lu_mem traverseCclosure (global_State *g, CClosure *cl) { - int i; - for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ - markvalue(g, &cl->upvalue[i]); - return sizeCclosure(cl->nupvalues); -} - -static lu_mem traverseLclosure (global_State *g, LClosure *cl) { - int i; - markobject(g, cl->p); /* mark its prototype */ - for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ - markobject(g, cl->upvals[i]); - return sizeLclosure(cl->nupvalues); -} - - -static lu_mem traversestack (global_State *g, lua_State *th) { - StkId o = th->stack; - if (o == NULL) - return 1; /* stack not completely built yet */ - for (; o < th->top; o++) - markvalue(g, o); - if (g->gcstate == GCSatomic) { /* final traversal? */ - StkId lim = th->stack + th->stacksize; /* real end of stack */ - for (; o < lim; o++) /* clear not-marked stack slice */ - setnilvalue(o); - } - return sizeof(lua_State) + sizeof(TValue) * th->stacksize; -} - - -/* -** traverse one gray object, turning it to black (except for threads, -** which are always gray). -*/ -static void propagatemark (global_State *g) { - lu_mem size; - GCObject *o = g->gray; - lua_assert(isgray(o)); - gray2black(o); - switch (gch(o)->tt) { - case LUA_TTABLE: { - Table *h = gco2t(o); - g->gray = h->gclist; /* remove from 'gray' list */ - size = traversetable(g, h); - break; - } - case LUA_TLCL: { - LClosure *cl = gco2lcl(o); - g->gray = cl->gclist; /* remove from 'gray' list */ - size = traverseLclosure(g, cl); - break; - } - case LUA_TCCL: { - CClosure *cl = gco2ccl(o); - g->gray = cl->gclist; /* remove from 'gray' list */ - size = traverseCclosure(g, cl); - break; - } - case LUA_TTHREAD: { - lua_State *th = gco2th(o); - g->gray = th->gclist; /* remove from 'gray' list */ - th->gclist = g->grayagain; - g->grayagain = o; /* insert into 'grayagain' list */ - black2gray(o); - size = traversestack(g, th); - break; - } - case LUA_TPROTO: { - Proto *p = gco2p(o); - g->gray = p->gclist; /* remove from 'gray' list */ - size = traverseproto(g, p); - break; - } - default: lua_assert(0); return; - } - g->GCmemtrav += size; -} - - -static void propagateall (global_State *g) { - while (g->gray) propagatemark(g); -} - - -static void propagatelist (global_State *g, GCObject *l) { - lua_assert(g->gray == NULL); /* no grays left */ - g->gray = l; - propagateall(g); /* traverse all elements from 'l' */ -} - -/* -** retraverse all gray lists. Because tables may be reinserted in other -** lists when traversed, traverse the original lists to avoid traversing -** twice the same table (which is not wrong, but inefficient) -*/ -static void retraversegrays (global_State *g) { - GCObject *weak = g->weak; /* save original lists */ - GCObject *grayagain = g->grayagain; - GCObject *ephemeron = g->ephemeron; - g->weak = g->grayagain = g->ephemeron = NULL; - propagateall(g); /* traverse main gray list */ - propagatelist(g, grayagain); - propagatelist(g, weak); - propagatelist(g, ephemeron); -} - - -static void convergeephemerons (global_State *g) { - int changed; - do { - GCObject *w; - GCObject *next = g->ephemeron; /* get ephemeron list */ - g->ephemeron = NULL; /* tables will return to this list when traversed */ - changed = 0; - while ((w = next) != NULL) { - next = gco2t(w)->gclist; - if (traverseephemeron(g, gco2t(w))) { /* traverse marked some value? */ - propagateall(g); /* propagate changes */ - changed = 1; /* will have to revisit all ephemeron tables */ - } - } - } while (changed); -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Sweep Functions -** ======================================================= -*/ - - -/* -** clear entries with unmarked keys from all weaktables in list 'l' up -** to element 'f' -*/ -static void clearkeys (global_State *g, GCObject *l, GCObject *f) { - for (; l != f; l = gco2t(l)->gclist) { - Table *h = gco2t(l); - Node *n, *limit = gnodelast(h); - for (n = gnode(h, 0); n < limit; n++) { - if (!ttisnil(gval(n)) && (iscleared(g, gkey(n)))) { - setnilvalue(gval(n)); /* remove value ... */ - removeentry(n); /* and remove entry from table */ - } - } - } -} - - -/* -** clear entries with unmarked values from all weaktables in list 'l' up -** to element 'f' -*/ -static void clearvalues (global_State *g, GCObject *l, GCObject *f) { - for (; l != f; l = gco2t(l)->gclist) { - Table *h = gco2t(l); - Node *n, *limit = gnodelast(h); - int i; - for (i = 0; i < h->sizearray; i++) { - TValue *o = &h->array[i]; - if (iscleared(g, o)) /* value was collected? */ - setnilvalue(o); /* remove value */ - } - for (n = gnode(h, 0); n < limit; n++) { - if (!ttisnil(gval(n)) && iscleared(g, gval(n))) { - setnilvalue(gval(n)); /* remove value ... */ - removeentry(n); /* and remove entry from table */ - } - } - } -} - - -static void freeobj (lua_State *L, GCObject *o) { - switch (gch(o)->tt) { - case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; - case LUA_TLCL: { - luaM_freemem(L, o, sizeLclosure(gco2lcl(o)->nupvalues)); - break; - } - case LUA_TCCL: { - luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); - break; - } - case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; - case LUA_TTABLE: luaH_free(L, gco2t(o)); break; - case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break; - case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; - case LUA_TSHRSTR: - G(L)->strt.nuse--; - /* go through */ - case LUA_TLNGSTR: { - luaM_freemem(L, o, sizestring(gco2ts(o))); - break; - } - default: lua_assert(0); - } -} - - -#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) -static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count); - - -/* -** sweep the (open) upvalues of a thread and resize its stack and -** list of call-info structures. -*/ -static void sweepthread (lua_State *L, lua_State *L1) { - if (L1->stack == NULL) return; /* stack not completely built yet */ - sweepwholelist(L, &L1->openupval); /* sweep open upvalues */ - luaE_freeCI(L1); /* free extra CallInfo slots */ - /* should not change the stack during an emergency gc cycle */ - if (G(L)->gckind != KGC_EMERGENCY) - luaD_shrinkstack(L1); -} - - -/* -** sweep at most 'count' elements from a list of GCObjects erasing dead -** objects, where a dead (not alive) object is one marked with the "old" -** (non current) white and not fixed. -** In non-generational mode, change all non-dead objects back to white, -** preparing for next collection cycle. -** In generational mode, keep black objects black, and also mark them as -** old; stop when hitting an old object, as all objects after that -** one will be old too. -** When object is a thread, sweep its list of open upvalues too. -*/ -static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { - global_State *g = G(L); - int ow = otherwhite(g); - int toclear, toset; /* bits to clear and to set in all live objects */ - int tostop; /* stop sweep when this is true */ - if (isgenerational(g)) { /* generational mode? */ - toclear = ~0; /* clear nothing */ - toset = bitmask(OLDBIT); /* set the old bit of all surviving objects */ - tostop = bitmask(OLDBIT); /* do not sweep old generation */ - } - else { /* normal mode */ - toclear = maskcolors; /* clear all color bits + old bit */ - toset = luaC_white(g); /* make object white */ - tostop = 0; /* do not stop */ - } - while (*p != NULL && count-- > 0) { - GCObject *curr = *p; - int marked = gch(curr)->marked; - if (isdeadm(ow, marked)) { /* is 'curr' dead? */ - *p = gch(curr)->next; /* remove 'curr' from list */ - freeobj(L, curr); /* erase 'curr' */ - } - else { - if (testbits(marked, tostop)) - return NULL; /* stop sweeping this list */ - if (gch(curr)->tt == LUA_TTHREAD) - sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */ - /* update marks */ - gch(curr)->marked = cast_byte((marked & toclear) | toset); - p = &gch(curr)->next; /* go to next element */ - } - } - return (*p == NULL) ? NULL : p; -} - - -/* -** sweep a list until a live object (or end of list) -*/ -static GCObject **sweeptolive (lua_State *L, GCObject **p, int *n) { - GCObject ** old = p; - int i = 0; - do { - i++; - p = sweeplist(L, p, 1); - } while (p == old); - if (n) *n += i; - return p; -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Finalization -** ======================================================= -*/ - -static void checkSizes (lua_State *L) { - global_State *g = G(L); - if (g->gckind != KGC_EMERGENCY) { /* do not change sizes in emergency */ - int hs = g->strt.size / 2; /* half the size of the string table */ - if (g->strt.nuse < cast(lu_int32, hs)) /* using less than that half? */ - luaS_resize(L, hs); /* halve its size */ - luaZ_freebuffer(L, &g->buff); /* free concatenation buffer */ - } -} - - -static GCObject *udata2finalize (global_State *g) { - GCObject *o = g->tobefnz; /* get first element */ - lua_assert(isfinalized(o)); - g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */ - gch(o)->next = g->allgc; /* return it to 'allgc' list */ - g->allgc = o; - resetbit(gch(o)->marked, SEPARATED); /* mark that it is not in 'tobefnz' */ - lua_assert(!isold(o)); /* see MOVE OLD rule */ - if (!keepinvariantout(g)) /* not keeping invariant? */ - makewhite(g, o); /* "sweep" object */ - return o; -} - - -static void dothecall (lua_State *L, void *ud) { - UNUSED(ud); - luaD_call(L, L->top - 2, 0, 0); -} - - -static void GCTM (lua_State *L, int propagateerrors) { - global_State *g = G(L); - const TValue *tm; - TValue v; - setgcovalue(L, &v, udata2finalize(g)); - tm = luaT_gettmbyobj(L, &v, TM_GC); - if (tm != NULL && ttisfunction(tm)) { /* is there a finalizer? */ - int status; - lu_byte oldah = L->allowhook; - int running = g->gcrunning; - L->allowhook = 0; /* stop debug hooks during GC metamethod */ - g->gcrunning = 0; /* avoid GC steps */ - setobj2s(L, L->top, tm); /* push finalizer... */ - setobj2s(L, L->top + 1, &v); /* ... and its argument */ - L->top += 2; /* and (next line) call the finalizer */ - status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); - L->allowhook = oldah; /* restore hooks */ - g->gcrunning = running; /* restore state */ - if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ - if (status == LUA_ERRRUN) { /* is there an error object? */ - const char *msg = (ttisstring(L->top - 1)) - ? svalue(L->top - 1) - : "no message"; - luaO_pushfstring(L, "error in __gc metamethod (%s)", msg); - status = LUA_ERRGCMM; /* error in __gc metamethod */ - } - luaD_throw(L, status); /* re-throw error */ - } - } -} - - -/* -** move all unreachable objects (or 'all' objects) that need -** finalization from list 'finobj' to list 'tobefnz' (to be finalized) -*/ -static void separatetobefnz (lua_State *L, int all) { - global_State *g = G(L); - GCObject **p = &g->finobj; - GCObject *curr; - GCObject **lastnext = &g->tobefnz; - /* find last 'next' field in 'tobefnz' list (to add elements in its end) */ - while (*lastnext != NULL) - lastnext = &gch(*lastnext)->next; - while ((curr = *p) != NULL) { /* traverse all finalizable objects */ - lua_assert(!isfinalized(curr)); - lua_assert(testbit(gch(curr)->marked, SEPARATED)); - if (!(iswhite(curr) || all)) /* not being collected? */ - p = &gch(curr)->next; /* don't bother with it */ - else { - l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */ - *p = gch(curr)->next; /* remove 'curr' from 'finobj' list */ - gch(curr)->next = *lastnext; /* link at the end of 'tobefnz' list */ - *lastnext = curr; - lastnext = &gch(curr)->next; - } - } -} - - -/* -** if object 'o' has a finalizer, remove it from 'allgc' list (must -** search the list to find it) and link it in 'finobj' list. -*/ -void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { - global_State *g = G(L); - if (testbit(gch(o)->marked, SEPARATED) || /* obj. is already separated... */ - isfinalized(o) || /* ... or is finalized... */ - gfasttm(g, mt, TM_GC) == NULL) /* or has no finalizer? */ - return; /* nothing to be done */ - else { /* move 'o' to 'finobj' list */ - GCObject **p; - GCheader *ho = gch(o); - if (g->sweepgc == &ho->next) { /* avoid removing current sweep object */ - lua_assert(issweepphase(g)); - g->sweepgc = sweeptolive(L, g->sweepgc, NULL); - } - /* search for pointer pointing to 'o' */ - for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ } - *p = ho->next; /* remove 'o' from root list */ - ho->next = g->finobj; /* link it in list 'finobj' */ - g->finobj = o; - l_setbit(ho->marked, SEPARATED); /* mark it as such */ - if (!keepinvariantout(g)) /* not keeping invariant? */ - makewhite(g, o); /* "sweep" object */ - else - resetoldbit(o); /* see MOVE OLD rule */ - } -} - -/* }====================================================== */ - - -/* -** {====================================================== -** GC control -** ======================================================= -*/ - - -/* -** set a reasonable "time" to wait before starting a new GC cycle; -** cycle will start when memory use hits threshold -*/ -static void setpause (global_State *g, l_mem estimate) { - l_mem debt, threshold; - estimate = estimate / PAUSEADJ; /* adjust 'estimate' */ - threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */ - ? estimate * g->gcpause /* no overflow */ - : MAX_LMEM; /* overflow; truncate to maximum */ - debt = -cast(l_mem, threshold - gettotalbytes(g)); - luaE_setdebt(g, debt); -} - - -#define sweepphases \ - (bitmask(GCSsweepstring) | bitmask(GCSsweepudata) | bitmask(GCSsweep)) - - -/* -** enter first sweep phase (strings) and prepare pointers for other -** sweep phases. The calls to 'sweeptolive' make pointers point to an -** object inside the list (instead of to the header), so that the real -** sweep do not need to skip objects created between "now" and the start -** of the real sweep. -** Returns how many objects it swept. -*/ -static int entersweep (lua_State *L) { - global_State *g = G(L); - int n = 0; - g->gcstate = GCSsweepstring; - lua_assert(g->sweepgc == NULL && g->sweepfin == NULL); - /* prepare to sweep strings, finalizable objects, and regular objects */ - g->sweepstrgc = 0; - g->sweepfin = sweeptolive(L, &g->finobj, &n); - g->sweepgc = sweeptolive(L, &g->allgc, &n); - return n; -} - - -/* -** change GC mode -*/ -void luaC_changemode (lua_State *L, int mode) { - global_State *g = G(L); - if (mode == g->gckind) return; /* nothing to change */ - if (mode == KGC_GEN) { /* change to generational mode */ - /* make sure gray lists are consistent */ - luaC_runtilstate(L, bitmask(GCSpropagate)); - g->GCestimate = gettotalbytes(g); - g->gckind = KGC_GEN; - } - else { /* change to incremental mode */ - /* sweep all objects to turn them back to white - (as white has not changed, nothing extra will be collected) */ - g->gckind = KGC_NORMAL; - entersweep(L); - luaC_runtilstate(L, ~sweepphases); - } -} - - -/* -** call all pending finalizers -*/ -static void callallpendingfinalizers (lua_State *L, int propagateerrors) { - global_State *g = G(L); - while (g->tobefnz) { - resetoldbit(g->tobefnz); - GCTM(L, propagateerrors); - } -} - - -void luaC_freeallobjects (lua_State *L) { - global_State *g = G(L); - int i; - separatetobefnz(L, 1); /* separate all objects with finalizers */ - lua_assert(g->finobj == NULL); - callallpendingfinalizers(L, 0); - g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ - g->gckind = KGC_NORMAL; - sweepwholelist(L, &g->finobj); /* finalizers can create objs. in 'finobj' */ - sweepwholelist(L, &g->allgc); - for (i = 0; i < g->strt.size; i++) /* free all string lists */ - sweepwholelist(L, &g->strt.hash[i]); - lua_assert(g->strt.nuse == 0); -} - - -static l_mem atomic (lua_State *L) { - global_State *g = G(L); - l_mem work = -cast(l_mem, g->GCmemtrav); /* start counting work */ - GCObject *origweak, *origall; - lua_assert(!iswhite(obj2gco(g->mainthread))); - markobject(g, L); /* mark running thread */ - /* registry and global metatables may be changed by API */ - markvalue(g, &g->l_registry); - markmt(g); /* mark basic metatables */ - /* remark occasional upvalues of (maybe) dead threads */ - remarkupvals(g); - propagateall(g); /* propagate changes */ - work += g->GCmemtrav; /* stop counting (do not (re)count grays) */ - /* traverse objects caught by write barrier and by 'remarkupvals' */ - retraversegrays(g); - work -= g->GCmemtrav; /* restart counting */ - convergeephemerons(g); - /* at this point, all strongly accessible objects are marked. */ - /* clear values from weak tables, before checking finalizers */ - clearvalues(g, g->weak, NULL); - clearvalues(g, g->allweak, NULL); - origweak = g->weak; origall = g->allweak; - work += g->GCmemtrav; /* stop counting (objects being finalized) */ - separatetobefnz(L, 0); /* separate objects to be finalized */ - markbeingfnz(g); /* mark objects that will be finalized */ - propagateall(g); /* remark, to propagate `preserveness' */ - work -= g->GCmemtrav; /* restart counting */ - convergeephemerons(g); - /* at this point, all resurrected objects are marked. */ - /* remove dead objects from weak tables */ - clearkeys(g, g->ephemeron, NULL); /* clear keys from all ephemeron tables */ - clearkeys(g, g->allweak, NULL); /* clear keys from all allweak tables */ - /* clear values from resurrected weak tables */ - clearvalues(g, g->weak, origweak); - clearvalues(g, g->allweak, origall); - g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ - work += g->GCmemtrav; /* complete counting */ - return work; /* estimate of memory marked by 'atomic' */ -} - - -static lu_mem singlestep (lua_State *L) { - global_State *g = G(L); - switch (g->gcstate) { - case GCSpause: { - /* start to count memory traversed */ - g->GCmemtrav = g->strt.size * sizeof(GCObject*); - lua_assert(!isgenerational(g)); - restartcollection(g); - g->gcstate = GCSpropagate; - return g->GCmemtrav; - } - case GCSpropagate: { - if (g->gray) { - lu_mem oldtrav = g->GCmemtrav; - propagatemark(g); - return g->GCmemtrav - oldtrav; /* memory traversed in this step */ - } - else { /* no more `gray' objects */ - lu_mem work; - int sw; - g->gcstate = GCSatomic; /* finish mark phase */ - g->GCestimate = g->GCmemtrav; /* save what was counted */; - work = atomic(L); /* add what was traversed by 'atomic' */ - g->GCestimate += work; /* estimate of total memory traversed */ - sw = entersweep(L); - return work + sw * GCSWEEPCOST; - } - } - case GCSsweepstring: { - int i; - for (i = 0; i < GCSWEEPMAX && g->sweepstrgc + i < g->strt.size; i++) - sweepwholelist(L, &g->strt.hash[g->sweepstrgc + i]); - g->sweepstrgc += i; - if (g->sweepstrgc >= g->strt.size) /* no more strings to sweep? */ - g->gcstate = GCSsweepudata; - return i * GCSWEEPCOST; - } - case GCSsweepudata: { - if (g->sweepfin) { - g->sweepfin = sweeplist(L, g->sweepfin, GCSWEEPMAX); - return GCSWEEPMAX*GCSWEEPCOST; - } - else { - g->gcstate = GCSsweep; - return 0; - } - } - case GCSsweep: { - if (g->sweepgc) { - g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); - return GCSWEEPMAX*GCSWEEPCOST; - } - else { - /* sweep main thread */ - GCObject *mt = obj2gco(g->mainthread); - sweeplist(L, &mt, 1); - checkSizes(L); - g->gcstate = GCSpause; /* finish collection */ - return GCSWEEPCOST; - } - } - default: lua_assert(0); return 0; - } -} - - -/* -** advances the garbage collector until it reaches a state allowed -** by 'statemask' -*/ -void luaC_runtilstate (lua_State *L, int statesmask) { - global_State *g = G(L); - while (!testbit(statesmask, g->gcstate)) - singlestep(L); -} - - -static void generationalcollection (lua_State *L) { - global_State *g = G(L); - lua_assert(g->gcstate == GCSpropagate); - if (g->GCestimate == 0) { /* signal for another major collection? */ - luaC_fullgc(L, 0); /* perform a full regular collection */ - g->GCestimate = gettotalbytes(g); /* update control */ - } - else { - lu_mem estimate = g->GCestimate; - luaC_runtilstate(L, bitmask(GCSpause)); /* run complete (minor) cycle */ - g->gcstate = GCSpropagate; /* skip restart */ - if (gettotalbytes(g) > (estimate / 100) * g->gcmajorinc) - g->GCestimate = 0; /* signal for a major collection */ - else - g->GCestimate = estimate; /* keep estimate from last major coll. */ - - } - setpause(g, gettotalbytes(g)); - lua_assert(g->gcstate == GCSpropagate); -} - - -static void incstep (lua_State *L) { - global_State *g = G(L); - l_mem debt = g->GCdebt; - int stepmul = g->gcstepmul; - if (stepmul < 40) stepmul = 40; /* avoid ridiculous low values (and 0) */ - /* convert debt from Kb to 'work units' (avoid zero debt and overflows) */ - debt = (debt / STEPMULADJ) + 1; - debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM; - do { /* always perform at least one single step */ - lu_mem work = singlestep(L); /* do some work */ - debt -= work; - } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause); - if (g->gcstate == GCSpause) - setpause(g, g->GCestimate); /* pause until next cycle */ - else { - debt = (debt / stepmul) * STEPMULADJ; /* convert 'work units' to Kb */ - luaE_setdebt(g, debt); - } -} - - -/* -** performs a basic GC step -*/ -void luaC_forcestep (lua_State *L) { - global_State *g = G(L); - int i; - if (isgenerational(g)) generationalcollection(L); - else incstep(L); - /* run a few finalizers (or all of them at the end of a collect cycle) */ - for (i = 0; g->tobefnz && (i < GCFINALIZENUM || g->gcstate == GCSpause); i++) - GCTM(L, 1); /* call one finalizer */ -} - - -/* -** performs a basic GC step only if collector is running -*/ -void luaC_step (lua_State *L) { - global_State *g = G(L); - if (g->gcrunning) luaC_forcestep(L); - else luaE_setdebt(g, -GCSTEPSIZE); /* avoid being called too often */ -} - - - -/* -** performs a full GC cycle; if "isemergency", does not call -** finalizers (which could change stack positions) -*/ -void luaC_fullgc (lua_State *L, int isemergency) { - global_State *g = G(L); - int origkind = g->gckind; - lua_assert(origkind != KGC_EMERGENCY); - if (isemergency) /* do not run finalizers during emergency GC */ - g->gckind = KGC_EMERGENCY; - else { - g->gckind = KGC_NORMAL; - callallpendingfinalizers(L, 1); - } - if (keepinvariant(g)) { /* may there be some black objects? */ - /* must sweep all objects to turn them back to white - (as white has not changed, nothing will be collected) */ - entersweep(L); - } - /* finish any pending sweep phase to start a new cycle */ - luaC_runtilstate(L, bitmask(GCSpause)); - luaC_runtilstate(L, ~bitmask(GCSpause)); /* start new collection */ - luaC_runtilstate(L, bitmask(GCSpause)); /* run entire collection */ - if (origkind == KGC_GEN) { /* generational mode? */ - /* generational mode must be kept in propagate phase */ - luaC_runtilstate(L, bitmask(GCSpropagate)); - } - g->gckind = origkind; - setpause(g, gettotalbytes(g)); - if (!isemergency) /* do not run finalizers during emergency GC */ - callallpendingfinalizers(L, 1); -} - -/* }====================================================== */ - - diff --git a/contrib/lua/lua/src/lgc.h b/contrib/lua/lua/src/lgc.h deleted file mode 100644 index dee270b4dcb..00000000000 --- a/contrib/lua/lua/src/lgc.h +++ /dev/null @@ -1,157 +0,0 @@ -/* -** $Id: lgc.h,v 2.58 2012/09/11 12:53:08 roberto Exp $ -** Garbage Collector -** See Copyright Notice in lua.h -*/ - -#ifndef lgc_h -#define lgc_h - - -#include "lobject.h" -#include "lstate.h" - -/* -** Collectable objects may have one of three colors: white, which -** means the object is not marked; gray, which means the -** object is marked, but its references may be not marked; and -** black, which means that the object and all its references are marked. -** The main invariant of the garbage collector, while marking objects, -** is that a black object can never point to a white one. Moreover, -** any gray object must be in a "gray list" (gray, grayagain, weak, -** allweak, ephemeron) so that it can be visited again before finishing -** the collection cycle. These lists have no meaning when the invariant -** is not being enforced (e.g., sweep phase). -*/ - - - -/* how much to allocate before next GC step */ -#if !defined(GCSTEPSIZE) -/* ~100 small strings */ -#define GCSTEPSIZE (cast_int(100 * sizeof(TString))) -#endif - - -/* -** Possible states of the Garbage Collector -*/ -#define GCSpropagate 0 -#define GCSatomic 1 -#define GCSsweepstring 2 -#define GCSsweepudata 3 -#define GCSsweep 4 -#define GCSpause 5 - - -#define issweepphase(g) \ - (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep) - -#define isgenerational(g) ((g)->gckind == KGC_GEN) - -/* -** macros to tell when main invariant (white objects cannot point to black -** ones) must be kept. During a non-generational collection, the sweep -** phase may break the invariant, as objects turned white may point to -** still-black objects. The invariant is restored when sweep ends and -** all objects are white again. During a generational collection, the -** invariant must be kept all times. -*/ - -#define keepinvariant(g) (isgenerational(g) || g->gcstate <= GCSatomic) - - -/* -** Outside the collector, the state in generational mode is kept in -** 'propagate', so 'keepinvariant' is always true. -*/ -#define keepinvariantout(g) \ - check_exp(g->gcstate == GCSpropagate || !isgenerational(g), \ - g->gcstate <= GCSatomic) - - -/* -** some useful bit tricks -*/ -#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) -#define setbits(x,m) ((x) |= (m)) -#define testbits(x,m) ((x) & (m)) -#define bitmask(b) (1<<(b)) -#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) -#define l_setbit(x,b) setbits(x, bitmask(b)) -#define resetbit(x,b) resetbits(x, bitmask(b)) -#define testbit(x,b) testbits(x, bitmask(b)) - - -/* Layout for bit use in `marked' field: */ -#define WHITE0BIT 0 /* object is white (type 0) */ -#define WHITE1BIT 1 /* object is white (type 1) */ -#define BLACKBIT 2 /* object is black */ -#define FINALIZEDBIT 3 /* object has been separated for finalization */ -#define SEPARATED 4 /* object is in 'finobj' list or in 'tobefnz' */ -#define FIXEDBIT 5 /* object is fixed (should not be collected) */ -#define OLDBIT 6 /* object is old (only in generational mode) */ -/* bit 7 is currently used by tests (luaL_checkmemory) */ - -#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) - - -#define iswhite(x) testbits((x)->gch.marked, WHITEBITS) -#define isblack(x) testbit((x)->gch.marked, BLACKBIT) -#define isgray(x) /* neither white nor black */ \ - (!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT))) - -#define isold(x) testbit((x)->gch.marked, OLDBIT) - -/* MOVE OLD rule: whenever an object is moved to the beginning of - a GC list, its old bit must be cleared */ -#define resetoldbit(o) resetbit((o)->gch.marked, OLDBIT) - -#define otherwhite(g) (g->currentwhite ^ WHITEBITS) -#define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow))) -#define isdead(g,v) isdeadm(otherwhite(g), (v)->gch.marked) - -#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) -#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) - -#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) - -#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) - - -#define luaC_condGC(L,c) \ - {if (G(L)->GCdebt > 0) {c;}; condchangemem(L);} -#define luaC_checkGC(L) luaC_condGC(L, luaC_step(L);) - - -#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ - luaC_barrier_(L,obj2gco(p),gcvalue(v)); } - -#define luaC_barrierback(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ - luaC_barrierback_(L,p); } - -#define luaC_objbarrier(L,p,o) \ - { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ - luaC_barrier_(L,obj2gco(p),obj2gco(o)); } - -#define luaC_objbarrierback(L,p,o) \ - { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) luaC_barrierback_(L,p); } - -#define luaC_barrierproto(L,p,c) \ - { if (isblack(obj2gco(p))) luaC_barrierproto_(L,p,c); } - -LUAI_FUNC void luaC_freeallobjects (lua_State *L); -LUAI_FUNC void luaC_step (lua_State *L); -LUAI_FUNC void luaC_forcestep (lua_State *L); -LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); -LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); -LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, - GCObject **list, int offset); -LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); -LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); -LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c); -LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); -LUAI_FUNC void luaC_checkupvalcolor (global_State *g, UpVal *uv); -LUAI_FUNC void luaC_changemode (lua_State *L, int mode); - -#endif diff --git a/contrib/lua/lua/src/linit.c b/contrib/lua/lua/src/linit.c deleted file mode 100644 index 8d3aa6576fc..00000000000 --- a/contrib/lua/lua/src/linit.c +++ /dev/null @@ -1,67 +0,0 @@ -/* -** $Id: linit.c,v 1.32 2011/04/08 19:17:36 roberto Exp $ -** Initialization of libraries for lua.c and other clients -** See Copyright Notice in lua.h -*/ - - -/* -** If you embed Lua in your program and need to open the standard -** libraries, call luaL_openlibs in your program. If you need a -** different set of libraries, copy this file to your project and edit -** it to suit your needs. -*/ - - -#define linit_c -#define LUA_LIB - -#include "lua.h" - -#include "lualib.h" -#include "lauxlib.h" - - -/* -** these libs are loaded by lua.c and are readily available to any Lua -** program -*/ -static const luaL_Reg loadedlibs[] = { - {"_G", luaopen_base}, - {LUA_LOADLIBNAME, luaopen_package}, - {LUA_COLIBNAME, luaopen_coroutine}, - {LUA_TABLIBNAME, luaopen_table}, - {LUA_IOLIBNAME, luaopen_io}, - {LUA_OSLIBNAME, luaopen_os}, - {LUA_STRLIBNAME, luaopen_string}, - {LUA_BITLIBNAME, luaopen_bit32}, - {LUA_MATHLIBNAME, luaopen_math}, - {LUA_DBLIBNAME, luaopen_debug}, - {NULL, NULL} -}; - - -/* -** these libs are preloaded and must be required before used -*/ -static const luaL_Reg preloadedlibs[] = { - {NULL, NULL} -}; - - -LUALIB_API void luaL_openlibs (lua_State *L) { - const luaL_Reg *lib; - /* call open functions from 'loadedlibs' and set results to global table */ - for (lib = loadedlibs; lib->func; lib++) { - luaL_requiref(L, lib->name, lib->func, 1); - lua_pop(L, 1); /* remove lib */ - } - /* add open functions from 'preloadedlibs' into 'package.preload' table */ - luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD"); - for (lib = preloadedlibs; lib->func; lib++) { - lua_pushcfunction(L, lib->func); - lua_setfield(L, -2, lib->name); - } - lua_pop(L, 1); /* remove _PRELOAD table */ -} - diff --git a/contrib/lua/lua/src/liolib.c b/contrib/lua/lua/src/liolib.c deleted file mode 100644 index 3f80db1927f..00000000000 --- a/contrib/lua/lua/src/liolib.c +++ /dev/null @@ -1,665 +0,0 @@ -/* -** $Id: liolib.c,v 2.111 2013/03/21 13:57:27 roberto Exp $ -** Standard I/O (and system) library -** See Copyright Notice in lua.h -*/ - - -/* -** POSIX idiosyncrasy! -** This definition must come before the inclusion of 'stdio.h'; it -** should not affect non-POSIX systems -*/ -#if !defined(_FILE_OFFSET_BITS) -#define _FILE_OFFSET_BITS 64 -#endif - - -#include -#include -#include -#include - -#define liolib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -#if !defined(lua_checkmode) - -/* -** Check whether 'mode' matches '[rwa]%+?b?'. -** Change this macro to accept other modes for 'fopen' besides -** the standard ones. -*/ -#define lua_checkmode(mode) \ - (*mode != '\0' && strchr("rwa", *(mode++)) != NULL && \ - (*mode != '+' || ++mode) && /* skip if char is '+' */ \ - (*mode != 'b' || ++mode) && /* skip if char is 'b' */ \ - (*mode == '\0')) - -#endif - -/* -** {====================================================== -** lua_popen spawns a new process connected to the current -** one through the file streams. -** ======================================================= -*/ - -#if !defined(lua_popen) /* { */ - -#if defined(LUA_USE_POPEN) /* { */ - -#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) -#define lua_pclose(L,file) ((void)L, pclose(file)) - -#elif defined(LUA_WIN) /* }{ */ - -#define lua_popen(L,c,m) ((void)L, _popen(c,m)) -#define lua_pclose(L,file) ((void)L, _pclose(file)) - - -#else /* }{ */ - -#define lua_popen(L,c,m) ((void)((void)c, m), \ - luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) -#define lua_pclose(L,file) ((void)((void)L, file), -1) - - -#endif /* } */ - -#endif /* } */ - -/* }====================================================== */ - - -/* -** {====================================================== -** lua_fseek/lua_ftell: configuration for longer offsets -** ======================================================= -*/ - -#if !defined(lua_fseek) /* { */ - -#if defined(LUA_USE_POSIX) - -#define l_fseek(f,o,w) fseeko(f,o,w) -#define l_ftell(f) ftello(f) -#define l_seeknum off_t - -#elif defined(LUA_WIN) && !defined(_CRTIMP_TYPEINFO) \ - && defined(_MSC_VER) && (_MSC_VER >= 1400) -/* Windows (but not DDK) and Visual C++ 2005 or higher */ - -#define l_fseek(f,o,w) _fseeki64(f,o,w) -#define l_ftell(f) _ftelli64(f) -#define l_seeknum __int64 - -#else - -#define l_fseek(f,o,w) fseek(f,o,w) -#define l_ftell(f) ftell(f) -#define l_seeknum long - -#endif - -#endif /* } */ - -/* }====================================================== */ - - -#define IO_PREFIX "_IO_" -#define IO_INPUT (IO_PREFIX "input") -#define IO_OUTPUT (IO_PREFIX "output") - - -typedef luaL_Stream LStream; - - -#define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE)) - -#define isclosed(p) ((p)->closef == NULL) - - -static int io_type (lua_State *L) { - LStream *p; - luaL_checkany(L, 1); - p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE); - if (p == NULL) - lua_pushnil(L); /* not a file */ - else if (isclosed(p)) - lua_pushliteral(L, "closed file"); - else - lua_pushliteral(L, "file"); - return 1; -} - - -static int f_tostring (lua_State *L) { - LStream *p = tolstream(L); - if (isclosed(p)) - lua_pushliteral(L, "file (closed)"); - else - lua_pushfstring(L, "file (%p)", p->f); - return 1; -} - - -static FILE *tofile (lua_State *L) { - LStream *p = tolstream(L); - if (isclosed(p)) - luaL_error(L, "attempt to use a closed file"); - lua_assert(p->f); - return p->f; -} - - -/* -** When creating file handles, always creates a `closed' file handle -** before opening the actual file; so, if there is a memory error, the -** file is not left opened. -*/ -static LStream *newprefile (lua_State *L) { - LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream)); - p->closef = NULL; /* mark file handle as 'closed' */ - luaL_setmetatable(L, LUA_FILEHANDLE); - return p; -} - - -static int aux_close (lua_State *L) { - LStream *p = tolstream(L); - lua_CFunction cf = p->closef; - p->closef = NULL; /* mark stream as closed */ - return (*cf)(L); /* close it */ -} - - -static int io_close (lua_State *L) { - if (lua_isnone(L, 1)) /* no argument? */ - lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */ - tofile(L); /* make sure argument is an open stream */ - return aux_close(L); -} - - -static int f_gc (lua_State *L) { - LStream *p = tolstream(L); - if (!isclosed(p) && p->f != NULL) - aux_close(L); /* ignore closed and incompletely open files */ - return 0; -} - - -/* -** function to close regular files -*/ -static int io_fclose (lua_State *L) { - LStream *p = tolstream(L); - int res = fclose(p->f); - return luaL_fileresult(L, (res == 0), NULL); -} - - -static LStream *newfile (lua_State *L) { - LStream *p = newprefile(L); - p->f = NULL; - p->closef = &io_fclose; - return p; -} - - -static void opencheck (lua_State *L, const char *fname, const char *mode) { - LStream *p = newfile(L); - p->f = fopen(fname, mode); - if (p->f == NULL) - luaL_error(L, "cannot open file " LUA_QS " (%s)", fname, strerror(errno)); -} - - -static int io_open (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - const char *mode = luaL_optstring(L, 2, "r"); - LStream *p = newfile(L); - const char *md = mode; /* to traverse/check mode */ - luaL_argcheck(L, lua_checkmode(md), 2, "invalid mode"); - p->f = fopen(filename, mode); - return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; -} - - -/* -** function to close 'popen' files -*/ -static int io_pclose (lua_State *L) { - LStream *p = tolstream(L); - return luaL_execresult(L, lua_pclose(L, p->f)); -} - - -static int io_popen (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - const char *mode = luaL_optstring(L, 2, "r"); - LStream *p = newprefile(L); - p->f = lua_popen(L, filename, mode); - p->closef = &io_pclose; - return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; -} - - -static int io_tmpfile (lua_State *L) { - LStream *p = newfile(L); - p->f = tmpfile(); - return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1; -} - - -static FILE *getiofile (lua_State *L, const char *findex) { - LStream *p; - lua_getfield(L, LUA_REGISTRYINDEX, findex); - p = (LStream *)lua_touserdata(L, -1); - if (isclosed(p)) - luaL_error(L, "standard %s file is closed", findex + strlen(IO_PREFIX)); - return p->f; -} - - -static int g_iofile (lua_State *L, const char *f, const char *mode) { - if (!lua_isnoneornil(L, 1)) { - const char *filename = lua_tostring(L, 1); - if (filename) - opencheck(L, filename, mode); - else { - tofile(L); /* check that it's a valid file handle */ - lua_pushvalue(L, 1); - } - lua_setfield(L, LUA_REGISTRYINDEX, f); - } - /* return current value */ - lua_getfield(L, LUA_REGISTRYINDEX, f); - return 1; -} - - -static int io_input (lua_State *L) { - return g_iofile(L, IO_INPUT, "r"); -} - - -static int io_output (lua_State *L) { - return g_iofile(L, IO_OUTPUT, "w"); -} - - -static int io_readline (lua_State *L); - - -static void aux_lines (lua_State *L, int toclose) { - int i; - int n = lua_gettop(L) - 1; /* number of arguments to read */ - /* ensure that arguments will fit here and into 'io_readline' stack */ - luaL_argcheck(L, n <= LUA_MINSTACK - 3, LUA_MINSTACK - 3, "too many options"); - lua_pushvalue(L, 1); /* file handle */ - lua_pushinteger(L, n); /* number of arguments to read */ - lua_pushboolean(L, toclose); /* close/not close file when finished */ - for (i = 1; i <= n; i++) lua_pushvalue(L, i + 1); /* copy arguments */ - lua_pushcclosure(L, io_readline, 3 + n); -} - - -static int f_lines (lua_State *L) { - tofile(L); /* check that it's a valid file handle */ - aux_lines(L, 0); - return 1; -} - - -static int io_lines (lua_State *L) { - int toclose; - if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ - if (lua_isnil(L, 1)) { /* no file name? */ - lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */ - lua_replace(L, 1); /* put it at index 1 */ - tofile(L); /* check that it's a valid file handle */ - toclose = 0; /* do not close it after iteration */ - } - else { /* open a new file */ - const char *filename = luaL_checkstring(L, 1); - opencheck(L, filename, "r"); - lua_replace(L, 1); /* put file at index 1 */ - toclose = 1; /* close it after iteration */ - } - aux_lines(L, toclose); - return 1; -} - - -/* -** {====================================================== -** READ -** ======================================================= -*/ - - -static int read_number (lua_State *L, FILE *f) { - lua_Number d; - if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { - lua_pushnumber(L, d); - return 1; - } - else { - lua_pushnil(L); /* "result" to be removed */ - return 0; /* read fails */ - } -} - - -static int test_eof (lua_State *L, FILE *f) { - int c = getc(f); - ungetc(c, f); - lua_pushlstring(L, NULL, 0); - return (c != EOF); -} - - -static int read_line (lua_State *L, FILE *f, int chop) { - luaL_Buffer b; - luaL_buffinit(L, &b); - for (;;) { - size_t l; - char *p = luaL_prepbuffer(&b); - if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ - luaL_pushresult(&b); /* close buffer */ - return (lua_rawlen(L, -1) > 0); /* check whether read something */ - } - l = strlen(p); - if (l == 0 || p[l-1] != '\n') - luaL_addsize(&b, l); - else { - luaL_addsize(&b, l - chop); /* chop 'eol' if needed */ - luaL_pushresult(&b); /* close buffer */ - return 1; /* read at least an `eol' */ - } - } -} - - -#define MAX_SIZE_T (~(size_t)0) - -static void read_all (lua_State *L, FILE *f) { - size_t rlen = LUAL_BUFFERSIZE; /* how much to read in each cycle */ - luaL_Buffer b; - luaL_buffinit(L, &b); - for (;;) { - char *p = luaL_prepbuffsize(&b, rlen); - size_t nr = fread(p, sizeof(char), rlen, f); - luaL_addsize(&b, nr); - if (nr < rlen) break; /* eof? */ - else if (rlen <= (MAX_SIZE_T / 4)) /* avoid buffers too large */ - rlen *= 2; /* double buffer size at each iteration */ - } - luaL_pushresult(&b); /* close buffer */ -} - - -static int read_chars (lua_State *L, FILE *f, size_t n) { - size_t nr; /* number of chars actually read */ - char *p; - luaL_Buffer b; - luaL_buffinit(L, &b); - p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */ - nr = fread(p, sizeof(char), n, f); /* try to read 'n' chars */ - luaL_addsize(&b, nr); - luaL_pushresult(&b); /* close buffer */ - return (nr > 0); /* true iff read something */ -} - - -static int g_read (lua_State *L, FILE *f, int first) { - int nargs = lua_gettop(L) - 1; - int success; - int n; - clearerr(f); - if (nargs == 0) { /* no arguments? */ - success = read_line(L, f, 1); - n = first+1; /* to return 1 result */ - } - else { /* ensure stack space for all results and for auxlib's buffer */ - luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); - success = 1; - for (n = first; nargs-- && success; n++) { - if (lua_type(L, n) == LUA_TNUMBER) { - size_t l = (size_t)lua_tointeger(L, n); - success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); - } - else { - const char *p = lua_tostring(L, n); - luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); - switch (p[1]) { - case 'n': /* number */ - success = read_number(L, f); - break; - case 'l': /* line */ - success = read_line(L, f, 1); - break; - case 'L': /* line with end-of-line */ - success = read_line(L, f, 0); - break; - case 'a': /* file */ - read_all(L, f); /* read entire file */ - success = 1; /* always success */ - break; - default: - return luaL_argerror(L, n, "invalid format"); - } - } - } - } - if (ferror(f)) - return luaL_fileresult(L, 0, NULL); - if (!success) { - lua_pop(L, 1); /* remove last result */ - lua_pushnil(L); /* push nil instead */ - } - return n - first; -} - - -static int io_read (lua_State *L) { - return g_read(L, getiofile(L, IO_INPUT), 1); -} - - -static int f_read (lua_State *L) { - return g_read(L, tofile(L), 2); -} - - -static int io_readline (lua_State *L) { - LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1)); - int i; - int n = (int)lua_tointeger(L, lua_upvalueindex(2)); - if (isclosed(p)) /* file is already closed? */ - return luaL_error(L, "file is already closed"); - lua_settop(L , 1); - for (i = 1; i <= n; i++) /* push arguments to 'g_read' */ - lua_pushvalue(L, lua_upvalueindex(3 + i)); - n = g_read(L, p->f, 2); /* 'n' is number of results */ - lua_assert(n > 0); /* should return at least a nil */ - if (!lua_isnil(L, -n)) /* read at least one value? */ - return n; /* return them */ - else { /* first result is nil: EOF or error */ - if (n > 1) { /* is there error information? */ - /* 2nd result is error message */ - return luaL_error(L, "%s", lua_tostring(L, -n + 1)); - } - if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ - lua_settop(L, 0); - lua_pushvalue(L, lua_upvalueindex(1)); - aux_close(L); /* close it */ - } - return 0; - } -} - -/* }====================================================== */ - - -static int g_write (lua_State *L, FILE *f, int arg) { - int nargs = lua_gettop(L) - arg; - int status = 1; - for (; nargs--; arg++) { - if (lua_type(L, arg) == LUA_TNUMBER) { - /* optimization: could be done exactly as for strings */ - status = status && - fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; - } - else { - size_t l; - const char *s = luaL_checklstring(L, arg, &l); - status = status && (fwrite(s, sizeof(char), l, f) == l); - } - } - if (status) return 1; /* file handle already on stack top */ - else return luaL_fileresult(L, status, NULL); -} - - -static int io_write (lua_State *L) { - return g_write(L, getiofile(L, IO_OUTPUT), 1); -} - - -static int f_write (lua_State *L) { - FILE *f = tofile(L); - lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */ - return g_write(L, f, 2); -} - - -static int f_seek (lua_State *L) { - static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; - static const char *const modenames[] = {"set", "cur", "end", NULL}; - FILE *f = tofile(L); - int op = luaL_checkoption(L, 2, "cur", modenames); - lua_Number p3 = luaL_optnumber(L, 3, 0); - l_seeknum offset = (l_seeknum)p3; - luaL_argcheck(L, (lua_Number)offset == p3, 3, - "not an integer in proper range"); - op = l_fseek(f, offset, mode[op]); - if (op) - return luaL_fileresult(L, 0, NULL); /* error */ - else { - lua_pushnumber(L, (lua_Number)l_ftell(f)); - return 1; - } -} - - -static int f_setvbuf (lua_State *L) { - static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; - static const char *const modenames[] = {"no", "full", "line", NULL}; - FILE *f = tofile(L); - int op = luaL_checkoption(L, 2, NULL, modenames); - lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); - int res = setvbuf(f, NULL, mode[op], sz); - return luaL_fileresult(L, res == 0, NULL); -} - - - -static int io_flush (lua_State *L) { - return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); -} - - -static int f_flush (lua_State *L) { - return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL); -} - - -/* -** functions for 'io' library -*/ -static const luaL_Reg iolib[] = { - {"close", io_close}, - {"flush", io_flush}, - {"input", io_input}, - {"lines", io_lines}, - {"open", io_open}, - {"output", io_output}, - {"popen", io_popen}, - {"read", io_read}, - {"tmpfile", io_tmpfile}, - {"type", io_type}, - {"write", io_write}, - {NULL, NULL} -}; - - -/* -** methods for file handles -*/ -static const luaL_Reg flib[] = { - {"close", io_close}, - {"flush", f_flush}, - {"lines", f_lines}, - {"read", f_read}, - {"seek", f_seek}, - {"setvbuf", f_setvbuf}, - {"write", f_write}, - {"__gc", f_gc}, - {"__tostring", f_tostring}, - {NULL, NULL} -}; - - -static void createmeta (lua_State *L) { - luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ - lua_pushvalue(L, -1); /* push metatable */ - lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ - luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */ - lua_pop(L, 1); /* pop new metatable */ -} - - -/* -** function to (not) close the standard files stdin, stdout, and stderr -*/ -static int io_noclose (lua_State *L) { - LStream *p = tolstream(L); - p->closef = &io_noclose; /* keep file opened */ - lua_pushnil(L); - lua_pushliteral(L, "cannot close standard file"); - return 2; -} - - -static void createstdfile (lua_State *L, FILE *f, const char *k, - const char *fname) { - LStream *p = newprefile(L); - p->f = f; - p->closef = &io_noclose; - if (k != NULL) { - lua_pushvalue(L, -1); - lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */ - } - lua_setfield(L, -2, fname); /* add file to module */ -} - - -LUAMOD_API int luaopen_io (lua_State *L) { - luaL_newlib(L, iolib); /* new module */ - createmeta(L); - /* create (and set) default files */ - createstdfile(L, stdin, IO_INPUT, "stdin"); - createstdfile(L, stdout, IO_OUTPUT, "stdout"); - createstdfile(L, stderr, NULL, "stderr"); - return 1; -} - diff --git a/contrib/lua/lua/src/llex.c b/contrib/lua/lua/src/llex.c deleted file mode 100644 index 1a32e348b0b..00000000000 --- a/contrib/lua/lua/src/llex.c +++ /dev/null @@ -1,527 +0,0 @@ -/* -** $Id: llex.c,v 2.63 2013/03/16 21:10:18 roberto Exp $ -** Lexical Analyzer -** See Copyright Notice in lua.h -*/ - - -#include -#include - -#define llex_c -#define LUA_CORE - -#include "lua.h" - -#include "lctype.h" -#include "ldo.h" -#include "llex.h" -#include "lobject.h" -#include "lparser.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "lzio.h" - - - -#define next(ls) (ls->current = zgetc(ls->z)) - - - -#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') - - -/* ORDER RESERVED */ -static const char *const luaX_tokens [] = { - "and", "break", "do", "else", "elseif", - "end", "false", "for", "function", "goto", "if", - "in", "local", "nil", "not", "or", "repeat", - "return", "then", "true", "until", "while", - "..", "...", "==", ">=", "<=", "~=", "::", "", - "", "", "" -}; - - -#define save_and_next(ls) (save(ls, ls->current), next(ls)) - - -static l_noret lexerror (LexState *ls, const char *msg, int token); - - -static void save (LexState *ls, int c) { - Mbuffer *b = ls->buff; - if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) { - size_t newsize; - if (luaZ_sizebuffer(b) >= MAX_SIZET/2) - lexerror(ls, "lexical element too long", 0); - newsize = luaZ_sizebuffer(b) * 2; - luaZ_resizebuffer(ls->L, b, newsize); - } - b->buffer[luaZ_bufflen(b)++] = cast(char, c); -} - - -void luaX_init (lua_State *L) { - int i; - for (i=0; itsv.extra = cast_byte(i+1); /* reserved word */ - } -} - - -const char *luaX_token2str (LexState *ls, int token) { - if (token < FIRST_RESERVED) { /* single-byte symbols? */ - lua_assert(token == cast(unsigned char, token)); - return (lisprint(token)) ? luaO_pushfstring(ls->L, LUA_QL("%c"), token) : - luaO_pushfstring(ls->L, "char(%d)", token); - } - else { - const char *s = luaX_tokens[token - FIRST_RESERVED]; - if (token < TK_EOS) /* fixed format (symbols and reserved words)? */ - return luaO_pushfstring(ls->L, LUA_QS, s); - else /* names, strings, and numerals */ - return s; - } -} - - -static const char *txtToken (LexState *ls, int token) { - switch (token) { - case TK_NAME: - case TK_STRING: - case TK_NUMBER: - save(ls, '\0'); - return luaO_pushfstring(ls->L, LUA_QS, luaZ_buffer(ls->buff)); - default: - return luaX_token2str(ls, token); - } -} - - -static l_noret lexerror (LexState *ls, const char *msg, int token) { - char buff[LUA_IDSIZE]; - luaO_chunkid(buff, getstr(ls->source), LUA_IDSIZE); - msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); - if (token) - luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token)); - luaD_throw(ls->L, LUA_ERRSYNTAX); -} - - -l_noret luaX_syntaxerror (LexState *ls, const char *msg) { - lexerror(ls, msg, ls->t.token); -} - - -/* -** creates a new string and anchors it in function's table so that -** it will not be collected until the end of the function's compilation -** (by that time it should be anchored in function's prototype) -*/ -TString *luaX_newstring (LexState *ls, const char *str, size_t l) { - lua_State *L = ls->L; - TValue *o; /* entry for `str' */ - TString *ts = luaS_newlstr(L, str, l); /* create new string */ - setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */ - o = luaH_set(L, ls->fs->h, L->top - 1); - if (ttisnil(o)) { /* not in use yet? (see 'addK') */ - /* boolean value does not need GC barrier; - table has no metatable, so it does not need to invalidate cache */ - setbvalue(o, 1); /* t[string] = true */ - luaC_checkGC(L); - } - L->top--; /* remove string from stack */ - return ts; -} - - -/* -** increment line number and skips newline sequence (any of -** \n, \r, \n\r, or \r\n) -*/ -static void inclinenumber (LexState *ls) { - int old = ls->current; - lua_assert(currIsNewline(ls)); - next(ls); /* skip `\n' or `\r' */ - if (currIsNewline(ls) && ls->current != old) - next(ls); /* skip `\n\r' or `\r\n' */ - if (++ls->linenumber >= MAX_INT) - luaX_syntaxerror(ls, "chunk has too many lines"); -} - - -void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source, - int firstchar) { - ls->decpoint = '.'; - ls->L = L; - ls->current = firstchar; - ls->lookahead.token = TK_EOS; /* no look-ahead token */ - ls->z = z; - ls->fs = NULL; - ls->linenumber = 1; - ls->lastline = 1; - ls->source = source; - ls->envn = luaS_new(L, LUA_ENV); /* create env name */ - luaS_fix(ls->envn); /* never collect this name */ - luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ -} - - - -/* -** ======================================================= -** LEXICAL ANALYZER -** ======================================================= -*/ - - - -static int check_next (LexState *ls, const char *set) { - if (ls->current == '\0' || !strchr(set, ls->current)) - return 0; - save_and_next(ls); - return 1; -} - - -/* -** change all characters 'from' in buffer to 'to' -*/ -static void buffreplace (LexState *ls, char from, char to) { - size_t n = luaZ_bufflen(ls->buff); - char *p = luaZ_buffer(ls->buff); - while (n--) - if (p[n] == from) p[n] = to; -} - - -#if !defined(getlocaledecpoint) -#define getlocaledecpoint() (localeconv()->decimal_point[0]) -#endif - - -#define buff2d(b,e) luaO_str2d(luaZ_buffer(b), luaZ_bufflen(b) - 1, e) - -/* -** in case of format error, try to change decimal point separator to -** the one defined in the current locale and check again -*/ -static void trydecpoint (LexState *ls, SemInfo *seminfo) { - char old = ls->decpoint; - ls->decpoint = getlocaledecpoint(); - buffreplace(ls, old, ls->decpoint); /* try new decimal separator */ - if (!buff2d(ls->buff, &seminfo->r)) { - /* format error with correct decimal point: no more options */ - buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ - lexerror(ls, "malformed number", TK_NUMBER); - } -} - - -/* LUA_NUMBER */ -/* -** this function is quite liberal in what it accepts, as 'luaO_str2d' -** will reject ill-formed numerals. -*/ -static void read_numeral (LexState *ls, SemInfo *seminfo) { - const char *expo = "Ee"; - int first = ls->current; - lua_assert(lisdigit(ls->current)); - save_and_next(ls); - if (first == '0' && check_next(ls, "Xx")) /* hexadecimal? */ - expo = "Pp"; - for (;;) { - if (check_next(ls, expo)) /* exponent part? */ - check_next(ls, "+-"); /* optional exponent sign */ - if (lisxdigit(ls->current) || ls->current == '.') - save_and_next(ls); - else break; - } - save(ls, '\0'); - buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ - if (!buff2d(ls->buff, &seminfo->r)) /* format error? */ - trydecpoint(ls, seminfo); /* try to update decimal point separator */ -} - - -/* -** skip a sequence '[=*[' or ']=*]' and return its number of '='s or -** -1 if sequence is malformed -*/ -static int skip_sep (LexState *ls) { - int count = 0; - int s = ls->current; - lua_assert(s == '[' || s == ']'); - save_and_next(ls); - while (ls->current == '=') { - save_and_next(ls); - count++; - } - return (ls->current == s) ? count : (-count) - 1; -} - - -static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { - save_and_next(ls); /* skip 2nd `[' */ - if (currIsNewline(ls)) /* string starts with a newline? */ - inclinenumber(ls); /* skip it */ - for (;;) { - switch (ls->current) { - case EOZ: - lexerror(ls, (seminfo) ? "unfinished long string" : - "unfinished long comment", TK_EOS); - break; /* to avoid warnings */ - case ']': { - if (skip_sep(ls) == sep) { - save_and_next(ls); /* skip 2nd `]' */ - goto endloop; - } - break; - } - case '\n': case '\r': { - save(ls, '\n'); - inclinenumber(ls); - if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ - break; - } - default: { - if (seminfo) save_and_next(ls); - else next(ls); - } - } - } endloop: - if (seminfo) - seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep), - luaZ_bufflen(ls->buff) - 2*(2 + sep)); -} - - -static void escerror (LexState *ls, int *c, int n, const char *msg) { - int i; - luaZ_resetbuffer(ls->buff); /* prepare error message */ - save(ls, '\\'); - for (i = 0; i < n && c[i] != EOZ; i++) - save(ls, c[i]); - lexerror(ls, msg, TK_STRING); -} - - -static int readhexaesc (LexState *ls) { - int c[3], i; /* keep input for error message */ - int r = 0; /* result accumulator */ - c[0] = 'x'; /* for error message */ - for (i = 1; i < 3; i++) { /* read two hexadecimal digits */ - c[i] = next(ls); - if (!lisxdigit(c[i])) - escerror(ls, c, i + 1, "hexadecimal digit expected"); - r = (r << 4) + luaO_hexavalue(c[i]); - } - return r; -} - - -static int readdecesc (LexState *ls) { - int c[3], i; - int r = 0; /* result accumulator */ - for (i = 0; i < 3 && lisdigit(ls->current); i++) { /* read up to 3 digits */ - c[i] = ls->current; - r = 10*r + c[i] - '0'; - next(ls); - } - if (r > UCHAR_MAX) - escerror(ls, c, i, "decimal escape too large"); - return r; -} - - -static void read_string (LexState *ls, int del, SemInfo *seminfo) { - save_and_next(ls); /* keep delimiter (for error messages) */ - while (ls->current != del) { - switch (ls->current) { - case EOZ: - lexerror(ls, "unfinished string", TK_EOS); - break; /* to avoid warnings */ - case '\n': - case '\r': - lexerror(ls, "unfinished string", TK_STRING); - break; /* to avoid warnings */ - case '\\': { /* escape sequences */ - int c; /* final character to be saved */ - next(ls); /* do not save the `\' */ - switch (ls->current) { - case 'a': c = '\a'; goto read_save; - case 'b': c = '\b'; goto read_save; - case 'f': c = '\f'; goto read_save; - case 'n': c = '\n'; goto read_save; - case 'r': c = '\r'; goto read_save; - case 't': c = '\t'; goto read_save; - case 'v': c = '\v'; goto read_save; - case 'x': c = readhexaesc(ls); goto read_save; - case '\n': case '\r': - inclinenumber(ls); c = '\n'; goto only_save; - case '\\': case '\"': case '\'': - c = ls->current; goto read_save; - case EOZ: goto no_save; /* will raise an error next loop */ - case 'z': { /* zap following span of spaces */ - next(ls); /* skip the 'z' */ - while (lisspace(ls->current)) { - if (currIsNewline(ls)) inclinenumber(ls); - else next(ls); - } - goto no_save; - } - default: { - if (!lisdigit(ls->current)) - escerror(ls, &ls->current, 1, "invalid escape sequence"); - /* digital escape \ddd */ - c = readdecesc(ls); - goto only_save; - } - } - read_save: next(ls); /* read next character */ - only_save: save(ls, c); /* save 'c' */ - no_save: break; - } - default: - save_and_next(ls); - } - } - save_and_next(ls); /* skip delimiter */ - seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, - luaZ_bufflen(ls->buff) - 2); -} - - -static int llex (LexState *ls, SemInfo *seminfo) { - luaZ_resetbuffer(ls->buff); - for (;;) { - switch (ls->current) { - case '\n': case '\r': { /* line breaks */ - inclinenumber(ls); - break; - } - case ' ': case '\f': case '\t': case '\v': { /* spaces */ - next(ls); - break; - } - case '-': { /* '-' or '--' (comment) */ - next(ls); - if (ls->current != '-') return '-'; - /* else is a comment */ - next(ls); - if (ls->current == '[') { /* long comment? */ - int sep = skip_sep(ls); - luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ - if (sep >= 0) { - read_long_string(ls, NULL, sep); /* skip long comment */ - luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */ - break; - } - } - /* else short comment */ - while (!currIsNewline(ls) && ls->current != EOZ) - next(ls); /* skip until end of line (or end of file) */ - break; - } - case '[': { /* long string or simply '[' */ - int sep = skip_sep(ls); - if (sep >= 0) { - read_long_string(ls, seminfo, sep); - return TK_STRING; - } - else if (sep == -1) return '['; - else lexerror(ls, "invalid long string delimiter", TK_STRING); - } - case '=': { - next(ls); - if (ls->current != '=') return '='; - else { next(ls); return TK_EQ; } - } - case '<': { - next(ls); - if (ls->current != '=') return '<'; - else { next(ls); return TK_LE; } - } - case '>': { - next(ls); - if (ls->current != '=') return '>'; - else { next(ls); return TK_GE; } - } - case '~': { - next(ls); - if (ls->current != '=') return '~'; - else { next(ls); return TK_NE; } - } - case ':': { - next(ls); - if (ls->current != ':') return ':'; - else { next(ls); return TK_DBCOLON; } - } - case '"': case '\'': { /* short literal strings */ - read_string(ls, ls->current, seminfo); - return TK_STRING; - } - case '.': { /* '.', '..', '...', or number */ - save_and_next(ls); - if (check_next(ls, ".")) { - if (check_next(ls, ".")) - return TK_DOTS; /* '...' */ - else return TK_CONCAT; /* '..' */ - } - else if (!lisdigit(ls->current)) return '.'; - /* else go through */ - } - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': { - read_numeral(ls, seminfo); - return TK_NUMBER; - } - case EOZ: { - return TK_EOS; - } - default: { - if (lislalpha(ls->current)) { /* identifier or reserved word? */ - TString *ts; - do { - save_and_next(ls); - } while (lislalnum(ls->current)); - ts = luaX_newstring(ls, luaZ_buffer(ls->buff), - luaZ_bufflen(ls->buff)); - seminfo->ts = ts; - if (isreserved(ts)) /* reserved word? */ - return ts->tsv.extra - 1 + FIRST_RESERVED; - else { - return TK_NAME; - } - } - else { /* single-char tokens (+ - / ...) */ - int c = ls->current; - next(ls); - return c; - } - } - } - } -} - - -void luaX_next (LexState *ls) { - ls->lastline = ls->linenumber; - if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ - ls->t = ls->lookahead; /* use this one */ - ls->lookahead.token = TK_EOS; /* and discharge it */ - } - else - ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ -} - - -int luaX_lookahead (LexState *ls) { - lua_assert(ls->lookahead.token == TK_EOS); - ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); - return ls->lookahead.token; -} - diff --git a/contrib/lua/lua/src/llex.h b/contrib/lua/lua/src/llex.h deleted file mode 100644 index 9ca8a29948c..00000000000 --- a/contrib/lua/lua/src/llex.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -** $Id: llex.h,v 1.72 2011/11/30 12:43:51 roberto Exp $ -** Lexical Analyzer -** See Copyright Notice in lua.h -*/ - -#ifndef llex_h -#define llex_h - -#include "lobject.h" -#include "lzio.h" - - -#define FIRST_RESERVED 257 - - - -/* -* WARNING: if you change the order of this enumeration, -* grep "ORDER RESERVED" -*/ -enum RESERVED { - /* terminal symbols denoted by reserved words */ - TK_AND = FIRST_RESERVED, TK_BREAK, - TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, - TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, - TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, - /* other terminal symbols */ - TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_DBCOLON, TK_EOS, - TK_NUMBER, TK_NAME, TK_STRING -}; - -/* number of reserved words */ -#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) - - -typedef union { - lua_Number r; - TString *ts; -} SemInfo; /* semantics information */ - - -typedef struct Token { - int token; - SemInfo seminfo; -} Token; - - -/* state of the lexer plus state of the parser when shared by all - functions */ -typedef struct LexState { - int current; /* current character (charint) */ - int linenumber; /* input line counter */ - int lastline; /* line of last token `consumed' */ - Token t; /* current token */ - Token lookahead; /* look ahead token */ - struct FuncState *fs; /* current function (parser) */ - struct lua_State *L; - ZIO *z; /* input stream */ - Mbuffer *buff; /* buffer for tokens */ - struct Dyndata *dyd; /* dynamic structures used by the parser */ - TString *source; /* current source name */ - TString *envn; /* environment variable name */ - char decpoint; /* locale decimal point */ -} LexState; - - -LUAI_FUNC void luaX_init (lua_State *L); -LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, - TString *source, int firstchar); -LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); -LUAI_FUNC void luaX_next (LexState *ls); -LUAI_FUNC int luaX_lookahead (LexState *ls); -LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s); -LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); - - -#endif diff --git a/contrib/lua/lua/src/llimits.h b/contrib/lua/lua/src/llimits.h deleted file mode 100644 index 1b8c79bda2b..00000000000 --- a/contrib/lua/lua/src/llimits.h +++ /dev/null @@ -1,309 +0,0 @@ -/* -** $Id: llimits.h,v 1.103 2013/02/20 14:08:56 roberto Exp $ -** Limits, basic types, and some other `installation-dependent' definitions -** See Copyright Notice in lua.h -*/ - -#ifndef llimits_h -#define llimits_h - - -#include -#include - - -#include "lua.h" - - -typedef unsigned LUA_INT32 lu_int32; - -typedef LUAI_UMEM lu_mem; - -typedef LUAI_MEM l_mem; - - - -/* chars used as small naturals (so that `char' is reserved for characters) */ -typedef unsigned char lu_byte; - - -#define MAX_SIZET ((size_t)(~(size_t)0)-2) - -#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) - -#define MAX_LMEM ((l_mem) ((MAX_LUMEM >> 1) - 2)) - - -#define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ - -/* -** conversion of pointer to integer -** this is for hashing only; there is no problem if the integer -** cannot hold the whole pointer value -*/ -#define IntPoint(p) ((unsigned int)(lu_mem)(p)) - - - -/* type to ensure maximum alignment */ -#if !defined(LUAI_USER_ALIGNMENT_T) -#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } -#endif - -typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; - - -/* result of a `usual argument conversion' over lua_Number */ -typedef LUAI_UACNUMBER l_uacNumber; - - -/* internal assertions for in-house debugging */ -#if defined(lua_assert) -#define check_exp(c,e) (lua_assert(c), (e)) -/* to avoid problems with conditions too long */ -#define lua_longassert(c) { if (!(c)) lua_assert(0); } -#else -#define lua_assert(c) ((void)0) -#define check_exp(c,e) (e) -#define lua_longassert(c) ((void)0) -#endif - -/* -** assertion for checking API calls -*/ -#if !defined(luai_apicheck) - -#if defined(LUA_USE_APICHECK) -#include -#define luai_apicheck(L,e) assert(e) -#else -#define luai_apicheck(L,e) lua_assert(e) -#endif - -#endif - -#define api_check(l,e,msg) luai_apicheck(l,(e) && msg) - - -#if !defined(UNUSED) -#define UNUSED(x) ((void)(x)) /* to avoid warnings */ -#endif - - -#define cast(t, exp) ((t)(exp)) - -#define cast_byte(i) cast(lu_byte, (i)) -#define cast_num(i) cast(lua_Number, (i)) -#define cast_int(i) cast(int, (i)) -#define cast_uchar(i) cast(unsigned char, (i)) - - -/* -** non-return type -*/ -#if defined(__GNUC__) -#define l_noret void __attribute__((noreturn)) -#elif defined(_MSC_VER) -#define l_noret void __declspec(noreturn) -#else -#define l_noret void -#endif - - - -/* -** maximum depth for nested C calls and syntactical nested non-terminals -** in a program. (Value must fit in an unsigned short int.) -*/ -#if !defined(LUAI_MAXCCALLS) -#define LUAI_MAXCCALLS 200 -#endif - -/* -** maximum number of upvalues in a closure (both C and Lua). (Value -** must fit in an unsigned char.) -*/ -#define MAXUPVAL UCHAR_MAX - - -/* -** type for virtual-machine instructions -** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) -*/ -typedef lu_int32 Instruction; - - - -/* maximum stack for a Lua function */ -#define MAXSTACK 250 - - - -/* minimum size for the string table (must be power of 2) */ -#if !defined(MINSTRTABSIZE) -#define MINSTRTABSIZE 32 -#endif - - -/* minimum size for string buffer */ -#if !defined(LUA_MINBUFFER) -#define LUA_MINBUFFER 32 -#endif - - -#if !defined(lua_lock) -#define lua_lock(L) ((void) 0) -#define lua_unlock(L) ((void) 0) -#endif - -#if !defined(luai_threadyield) -#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} -#endif - - -/* -** these macros allow user-specific actions on threads when you defined -** LUAI_EXTRASPACE and need to do something extra when a thread is -** created/deleted/resumed/yielded. -*/ -#if !defined(luai_userstateopen) -#define luai_userstateopen(L) ((void)L) -#endif - -#if !defined(luai_userstateclose) -#define luai_userstateclose(L) ((void)L) -#endif - -#if !defined(luai_userstatethread) -#define luai_userstatethread(L,L1) ((void)L) -#endif - -#if !defined(luai_userstatefree) -#define luai_userstatefree(L,L1) ((void)L) -#endif - -#if !defined(luai_userstateresume) -#define luai_userstateresume(L,n) ((void)L) -#endif - -#if !defined(luai_userstateyield) -#define luai_userstateyield(L,n) ((void)L) -#endif - -/* -** lua_number2int is a macro to convert lua_Number to int. -** lua_number2integer is a macro to convert lua_Number to lua_Integer. -** lua_number2unsigned is a macro to convert a lua_Number to a lua_Unsigned. -** lua_unsigned2number is a macro to convert a lua_Unsigned to a lua_Number. -** luai_hashnum is a macro to hash a lua_Number value into an integer. -** The hash must be deterministic and give reasonable values for -** both small and large values (outside the range of integers). -*/ - -#if defined(MS_ASMTRICK) || defined(LUA_MSASMTRICK) /* { */ -/* trick with Microsoft assembler for X86 */ - -#define lua_number2int(i,n) __asm {__asm fld n __asm fistp i} -#define lua_number2integer(i,n) lua_number2int(i, n) -#define lua_number2unsigned(i,n) \ - {__int64 l; __asm {__asm fld n __asm fistp l} i = (unsigned int)l;} - - -#elif defined(LUA_IEEE754TRICK) /* }{ */ -/* the next trick should work on any machine using IEEE754 with - a 32-bit int type */ - -union luai_Cast { double l_d; LUA_INT32 l_p[2]; }; - -#if !defined(LUA_IEEEENDIAN) /* { */ -#define LUAI_EXTRAIEEE \ - static const union luai_Cast ieeeendian = {-(33.0 + 6755399441055744.0)}; -#define LUA_IEEEENDIANLOC (ieeeendian.l_p[1] == 33) -#else -#define LUA_IEEEENDIANLOC LUA_IEEEENDIAN -#define LUAI_EXTRAIEEE /* empty */ -#endif /* } */ - -#define lua_number2int32(i,n,t) \ - { LUAI_EXTRAIEEE \ - volatile union luai_Cast u; u.l_d = (n) + 6755399441055744.0; \ - (i) = (t)u.l_p[LUA_IEEEENDIANLOC]; } - -#define luai_hashnum(i,n) \ - { volatile union luai_Cast u; u.l_d = (n) + 1.0; /* avoid -0 */ \ - (i) = u.l_p[0]; (i) += u.l_p[1]; } /* add double bits for his hash */ - -#define lua_number2int(i,n) lua_number2int32(i, n, int) -#define lua_number2unsigned(i,n) lua_number2int32(i, n, lua_Unsigned) - -/* the trick can be expanded to lua_Integer when it is a 32-bit value */ -#if defined(LUA_IEEELL) -#define lua_number2integer(i,n) lua_number2int32(i, n, lua_Integer) -#endif - -#endif /* } */ - - -/* the following definitions always work, but may be slow */ - -#if !defined(lua_number2int) -#define lua_number2int(i,n) ((i)=(int)(n)) -#endif - -#if !defined(lua_number2integer) -#define lua_number2integer(i,n) ((i)=(lua_Integer)(n)) -#endif - -#if !defined(lua_number2unsigned) /* { */ -/* the following definition assures proper modulo behavior */ -#if defined(LUA_NUMBER_DOUBLE) || defined(LUA_NUMBER_FLOAT) -#include -#define SUPUNSIGNED ((lua_Number)(~(lua_Unsigned)0) + 1) -#define lua_number2unsigned(i,n) \ - ((i)=(lua_Unsigned)((n) - floor((n)/SUPUNSIGNED)*SUPUNSIGNED)) -#else -#define lua_number2unsigned(i,n) ((i)=(lua_Unsigned)(n)) -#endif -#endif /* } */ - - -#if !defined(lua_unsigned2number) -/* on several machines, coercion from unsigned to double is slow, - so it may be worth to avoid */ -#define lua_unsigned2number(u) \ - (((u) <= (lua_Unsigned)INT_MAX) ? (lua_Number)(int)(u) : (lua_Number)(u)) -#endif - - - -#if defined(ltable_c) && !defined(luai_hashnum) - -#include -#include - -#define luai_hashnum(i,n) { int e; \ - n = l_mathop(frexp)(n, &e) * (lua_Number)(INT_MAX - DBL_MAX_EXP); \ - lua_number2int(i, n); i += e; } - -#endif - - - -/* -** macro to control inclusion of some hard tests on stack reallocation -*/ -#if !defined(HARDSTACKTESTS) -#define condmovestack(L) ((void)0) -#else -/* realloc stack keeping its size */ -#define condmovestack(L) luaD_reallocstack((L), (L)->stacksize) -#endif - -#if !defined(HARDMEMTESTS) -#define condchangemem(L) condmovestack(L) -#else -#define condchangemem(L) \ - ((void)(!(G(L)->gcrunning) || (luaC_fullgc(L, 0), 1))) -#endif - -#endif diff --git a/contrib/lua/lua/src/lmathlib.c b/contrib/lua/lua/src/lmathlib.c deleted file mode 100644 index a49f1fd25a2..00000000000 --- a/contrib/lua/lua/src/lmathlib.c +++ /dev/null @@ -1,279 +0,0 @@ -/* -** $Id: lmathlib.c,v 1.83 2013/03/07 18:21:32 roberto Exp $ -** Standard mathematical library -** See Copyright Notice in lua.h -*/ - - -#include -#include - -#define lmathlib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -#undef PI -#define PI ((lua_Number)(3.1415926535897932384626433832795)) -#define RADIANS_PER_DEGREE ((lua_Number)(PI/180.0)) - - - -static int math_abs (lua_State *L) { - lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_sin (lua_State *L) { - lua_pushnumber(L, l_mathop(sin)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_sinh (lua_State *L) { - lua_pushnumber(L, l_mathop(sinh)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_cos (lua_State *L) { - lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_cosh (lua_State *L) { - lua_pushnumber(L, l_mathop(cosh)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_tan (lua_State *L) { - lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_tanh (lua_State *L) { - lua_pushnumber(L, l_mathop(tanh)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_asin (lua_State *L) { - lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_acos (lua_State *L) { - lua_pushnumber(L, l_mathop(acos)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_atan (lua_State *L) { - lua_pushnumber(L, l_mathop(atan)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_atan2 (lua_State *L) { - lua_pushnumber(L, l_mathop(atan2)(luaL_checknumber(L, 1), - luaL_checknumber(L, 2))); - return 1; -} - -static int math_ceil (lua_State *L) { - lua_pushnumber(L, l_mathop(ceil)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_floor (lua_State *L) { - lua_pushnumber(L, l_mathop(floor)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_fmod (lua_State *L) { - lua_pushnumber(L, l_mathop(fmod)(luaL_checknumber(L, 1), - luaL_checknumber(L, 2))); - return 1; -} - -static int math_modf (lua_State *L) { - lua_Number ip; - lua_Number fp = l_mathop(modf)(luaL_checknumber(L, 1), &ip); - lua_pushnumber(L, ip); - lua_pushnumber(L, fp); - return 2; -} - -static int math_sqrt (lua_State *L) { - lua_pushnumber(L, l_mathop(sqrt)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_pow (lua_State *L) { - lua_Number x = luaL_checknumber(L, 1); - lua_Number y = luaL_checknumber(L, 2); - lua_pushnumber(L, l_mathop(pow)(x, y)); - return 1; -} - -static int math_log (lua_State *L) { - lua_Number x = luaL_checknumber(L, 1); - lua_Number res; - if (lua_isnoneornil(L, 2)) - res = l_mathop(log)(x); - else { - lua_Number base = luaL_checknumber(L, 2); - if (base == (lua_Number)10.0) res = l_mathop(log10)(x); - else res = l_mathop(log)(x)/l_mathop(log)(base); - } - lua_pushnumber(L, res); - return 1; -} - -#if defined(LUA_COMPAT_LOG10) -static int math_log10 (lua_State *L) { - lua_pushnumber(L, l_mathop(log10)(luaL_checknumber(L, 1))); - return 1; -} -#endif - -static int math_exp (lua_State *L) { - lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1))); - return 1; -} - -static int math_deg (lua_State *L) { - lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE); - return 1; -} - -static int math_rad (lua_State *L) { - lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE); - return 1; -} - -static int math_frexp (lua_State *L) { - int e; - lua_pushnumber(L, l_mathop(frexp)(luaL_checknumber(L, 1), &e)); - lua_pushinteger(L, e); - return 2; -} - -static int math_ldexp (lua_State *L) { - lua_Number x = luaL_checknumber(L, 1); - int ep = luaL_checkint(L, 2); - lua_pushnumber(L, l_mathop(ldexp)(x, ep)); - return 1; -} - - - -static int math_min (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - lua_Number dmin = luaL_checknumber(L, 1); - int i; - for (i=2; i<=n; i++) { - lua_Number d = luaL_checknumber(L, i); - if (d < dmin) - dmin = d; - } - lua_pushnumber(L, dmin); - return 1; -} - - -static int math_max (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - lua_Number dmax = luaL_checknumber(L, 1); - int i; - for (i=2; i<=n; i++) { - lua_Number d = luaL_checknumber(L, i); - if (d > dmax) - dmax = d; - } - lua_pushnumber(L, dmax); - return 1; -} - - -static int math_random (lua_State *L) { - /* the `%' avoids the (rare) case of r==1, and is needed also because on - some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */ - lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX; - switch (lua_gettop(L)) { /* check number of arguments */ - case 0: { /* no arguments */ - lua_pushnumber(L, r); /* Number between 0 and 1 */ - break; - } - case 1: { /* only upper limit */ - lua_Number u = luaL_checknumber(L, 1); - luaL_argcheck(L, (lua_Number)1.0 <= u, 1, "interval is empty"); - lua_pushnumber(L, l_mathop(floor)(r*u) + (lua_Number)(1.0)); /* [1, u] */ - break; - } - case 2: { /* lower and upper limits */ - lua_Number l = luaL_checknumber(L, 1); - lua_Number u = luaL_checknumber(L, 2); - luaL_argcheck(L, l <= u, 2, "interval is empty"); - lua_pushnumber(L, l_mathop(floor)(r*(u-l+1)) + l); /* [l, u] */ - break; - } - default: return luaL_error(L, "wrong number of arguments"); - } - return 1; -} - - -static int math_randomseed (lua_State *L) { - srand(luaL_checkunsigned(L, 1)); - (void)rand(); /* discard first value to avoid undesirable correlations */ - return 0; -} - - -static const luaL_Reg mathlib[] = { - {"abs", math_abs}, - {"acos", math_acos}, - {"asin", math_asin}, - {"atan2", math_atan2}, - {"atan", math_atan}, - {"ceil", math_ceil}, - {"cosh", math_cosh}, - {"cos", math_cos}, - {"deg", math_deg}, - {"exp", math_exp}, - {"floor", math_floor}, - {"fmod", math_fmod}, - {"frexp", math_frexp}, - {"ldexp", math_ldexp}, -#if defined(LUA_COMPAT_LOG10) - {"log10", math_log10}, -#endif - {"log", math_log}, - {"max", math_max}, - {"min", math_min}, - {"modf", math_modf}, - {"pow", math_pow}, - {"rad", math_rad}, - {"random", math_random}, - {"randomseed", math_randomseed}, - {"sinh", math_sinh}, - {"sin", math_sin}, - {"sqrt", math_sqrt}, - {"tanh", math_tanh}, - {"tan", math_tan}, - {NULL, NULL} -}; - - -/* -** Open math library -*/ -LUAMOD_API int luaopen_math (lua_State *L) { - luaL_newlib(L, mathlib); - lua_pushnumber(L, PI); - lua_setfield(L, -2, "pi"); - lua_pushnumber(L, HUGE_VAL); - lua_setfield(L, -2, "huge"); - return 1; -} - diff --git a/contrib/lua/lua/src/lmem.c b/contrib/lua/lua/src/lmem.c deleted file mode 100644 index 3f88496e09d..00000000000 --- a/contrib/lua/lua/src/lmem.c +++ /dev/null @@ -1,99 +0,0 @@ -/* -** $Id: lmem.c,v 1.84 2012/05/23 15:41:53 roberto Exp $ -** Interface to Memory Manager -** See Copyright Notice in lua.h -*/ - - -#include - -#define lmem_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" - - - -/* -** About the realloc function: -** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); -** (`osize' is the old size, `nsize' is the new size) -** -** * frealloc(ud, NULL, x, s) creates a new block of size `s' (no -** matter 'x'). -** -** * frealloc(ud, p, x, 0) frees the block `p' -** (in this specific case, frealloc must return NULL); -** particularly, frealloc(ud, NULL, 0, 0) does nothing -** (which is equivalent to free(NULL) in ANSI C) -** -** frealloc returns NULL if it cannot create or reallocate the area -** (any reallocation to an equal or smaller size cannot fail!) -*/ - - - -#define MINSIZEARRAY 4 - - -void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, - int limit, const char *what) { - void *newblock; - int newsize; - if (*size >= limit/2) { /* cannot double it? */ - if (*size >= limit) /* cannot grow even a little? */ - luaG_runerror(L, "too many %s (limit is %d)", what, limit); - newsize = limit; /* still have at least one free place */ - } - else { - newsize = (*size)*2; - if (newsize < MINSIZEARRAY) - newsize = MINSIZEARRAY; /* minimum size */ - } - newblock = luaM_reallocv(L, block, *size, newsize, size_elems); - *size = newsize; /* update only when everything else is OK */ - return newblock; -} - - -l_noret luaM_toobig (lua_State *L) { - luaG_runerror(L, "memory allocation error: block too big"); -} - - - -/* -** generic allocation routine. -*/ -void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { - void *newblock; - global_State *g = G(L); - size_t realosize = (block) ? osize : 0; - lua_assert((realosize == 0) == (block == NULL)); -#if defined(HARDMEMTESTS) - if (nsize > realosize && g->gcrunning) - luaC_fullgc(L, 1); /* force a GC whenever possible */ -#endif - newblock = (*g->frealloc)(g->ud, block, osize, nsize); - if (newblock == NULL && nsize > 0) { - api_check(L, nsize > realosize, - "realloc cannot fail when shrinking a block"); - if (g->gcrunning) { - luaC_fullgc(L, 1); /* try to free some memory... */ - newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ - } - if (newblock == NULL) - luaD_throw(L, LUA_ERRMEM); - } - lua_assert((nsize == 0) == (newblock == NULL)); - g->GCdebt = (g->GCdebt + nsize) - realosize; - return newblock; -} - diff --git a/contrib/lua/lua/src/lmem.h b/contrib/lua/lua/src/lmem.h deleted file mode 100644 index 5f850999a9d..00000000000 --- a/contrib/lua/lua/src/lmem.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -** $Id: lmem.h,v 1.40 2013/02/20 14:08:21 roberto Exp $ -** Interface to Memory Manager -** See Copyright Notice in lua.h -*/ - -#ifndef lmem_h -#define lmem_h - - -#include - -#include "llimits.h" -#include "lua.h" - - -/* -** This macro avoids the runtime division MAX_SIZET/(e), as 'e' is -** always constant. -** The macro is somewhat complex to avoid warnings: -** +1 avoids warnings of "comparison has constant result"; -** cast to 'void' avoids warnings of "value unused". -*/ -#define luaM_reallocv(L,b,on,n,e) \ - (cast(void, \ - (cast(size_t, (n)+1) > MAX_SIZET/(e)) ? (luaM_toobig(L), 0) : 0), \ - luaM_realloc_(L, (b), (on)*(e), (n)*(e))) - -#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) -#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) -#define luaM_freearray(L, b, n) luaM_reallocv(L, (b), n, 0, sizeof((b)[0])) - -#define luaM_malloc(L,s) luaM_realloc_(L, NULL, 0, (s)) -#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) -#define luaM_newvector(L,n,t) \ - cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) - -#define luaM_newobject(L,tag,s) luaM_realloc_(L, NULL, tag, (s)) - -#define luaM_growvector(L,v,nelems,size,t,limit,e) \ - if ((nelems)+1 > (size)) \ - ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) - -#define luaM_reallocvector(L, v,oldn,n,t) \ - ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) - -LUAI_FUNC l_noret luaM_toobig (lua_State *L); - -/* not to be called directly */ -LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, - size_t size); -LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, - size_t size_elem, int limit, - const char *what); - -#endif - diff --git a/contrib/lua/lua/src/loadlib.c b/contrib/lua/lua/src/loadlib.c deleted file mode 100644 index a9959277bd8..00000000000 --- a/contrib/lua/lua/src/loadlib.c +++ /dev/null @@ -1,725 +0,0 @@ -/* -** $Id: loadlib.c,v 1.111 2012/05/30 12:33:44 roberto Exp $ -** Dynamic library loader for Lua -** See Copyright Notice in lua.h -** -** This module contains an implementation of loadlib for Unix systems -** that have dlfcn, an implementation for Windows, and a stub for other -** systems. -*/ - - -/* -** if needed, includes windows header before everything else -*/ -#if defined(_WIN32) -#include -#endif - - -#include -#include - - -#define loadlib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -/* -** LUA_PATH and LUA_CPATH are the names of the environment -** variables that Lua check to set its paths. -*/ -#if !defined(LUA_PATH) -#define LUA_PATH "LUA_PATH" -#endif - -#if !defined(LUA_CPATH) -#define LUA_CPATH "LUA_CPATH" -#endif - -#define LUA_PATHSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR - -#define LUA_PATHVERSION LUA_PATH LUA_PATHSUFFIX -#define LUA_CPATHVERSION LUA_CPATH LUA_PATHSUFFIX - -/* -** LUA_PATH_SEP is the character that separates templates in a path. -** LUA_PATH_MARK is the string that marks the substitution points in a -** template. -** LUA_EXEC_DIR in a Windows path is replaced by the executable's -** directory. -** LUA_IGMARK is a mark to ignore all before it when building the -** luaopen_ function name. -*/ -#if !defined (LUA_PATH_SEP) -#define LUA_PATH_SEP ";" -#endif -#if !defined (LUA_PATH_MARK) -#define LUA_PATH_MARK "?" -#endif -#if !defined (LUA_EXEC_DIR) -#define LUA_EXEC_DIR "!" -#endif -#if !defined (LUA_IGMARK) -#define LUA_IGMARK "-" -#endif - - -/* -** LUA_CSUBSEP is the character that replaces dots in submodule names -** when searching for a C loader. -** LUA_LSUBSEP is the character that replaces dots in submodule names -** when searching for a Lua loader. -*/ -#if !defined(LUA_CSUBSEP) -#define LUA_CSUBSEP LUA_DIRSEP -#endif - -#if !defined(LUA_LSUBSEP) -#define LUA_LSUBSEP LUA_DIRSEP -#endif - - -/* prefix for open functions in C libraries */ -#define LUA_POF "luaopen_" - -/* separator for open functions in C libraries */ -#define LUA_OFSEP "_" - - -/* table (in the registry) that keeps handles for all loaded C libraries */ -#define CLIBS "_CLIBS" - -#define LIB_FAIL "open" - - -/* error codes for ll_loadfunc */ -#define ERRLIB 1 -#define ERRFUNC 2 - -#define setprogdir(L) ((void)0) - - -/* -** system-dependent functions -*/ -static void ll_unloadlib (void *lib); -static void *ll_load (lua_State *L, const char *path, int seeglb); -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); - - - -#if defined(LUA_USE_DLOPEN) -/* -** {======================================================================== -** This is an implementation of loadlib based on the dlfcn interface. -** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, -** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least -** as an emulation layer on top of native functions. -** ========================================================================= -*/ - -#include - -static void ll_unloadlib (void *lib) { - dlclose(lib); -} - - -static void *ll_load (lua_State *L, const char *path, int seeglb) { - void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL)); - if (lib == NULL) lua_pushstring(L, dlerror()); - return lib; -} - - -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { - lua_CFunction f = (lua_CFunction)dlsym(lib, sym); - if (f == NULL) lua_pushstring(L, dlerror()); - return f; -} - -/* }====================================================== */ - - - -#elif defined(LUA_DL_DLL) -/* -** {====================================================================== -** This is an implementation of loadlib for Windows using native functions. -** ======================================================================= -*/ - -#undef setprogdir - -/* -** optional flags for LoadLibraryEx -*/ -#if !defined(LUA_LLE_FLAGS) -#define LUA_LLE_FLAGS 0 -#endif - - -static void setprogdir (lua_State *L) { - char buff[MAX_PATH + 1]; - char *lb; - DWORD nsize = sizeof(buff)/sizeof(char); - DWORD n = GetModuleFileNameA(NULL, buff, nsize); - if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL) - luaL_error(L, "unable to get ModuleFileName"); - else { - *lb = '\0'; - luaL_gsub(L, lua_tostring(L, -1), LUA_EXEC_DIR, buff); - lua_remove(L, -2); /* remove original string */ - } -} - - -static void pusherror (lua_State *L) { - int error = GetLastError(); - char buffer[128]; - if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, error, 0, buffer, sizeof(buffer)/sizeof(char), NULL)) - lua_pushstring(L, buffer); - else - lua_pushfstring(L, "system error %d\n", error); -} - -static void ll_unloadlib (void *lib) { - FreeLibrary((HMODULE)lib); -} - - -static void *ll_load (lua_State *L, const char *path, int seeglb) { - HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS); - (void)(seeglb); /* not used: symbols are 'global' by default */ - if (lib == NULL) pusherror(L); - return lib; -} - - -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { - lua_CFunction f = (lua_CFunction)GetProcAddress((HMODULE)lib, sym); - if (f == NULL) pusherror(L); - return f; -} - -/* }====================================================== */ - - -#else -/* -** {====================================================== -** Fallback for other systems -** ======================================================= -*/ - -#undef LIB_FAIL -#define LIB_FAIL "absent" - - -#define DLMSG "dynamic libraries not enabled; check your Lua installation" - - -static void ll_unloadlib (void *lib) { - (void)(lib); /* not used */ -} - - -static void *ll_load (lua_State *L, const char *path, int seeglb) { - (void)(path); (void)(seeglb); /* not used */ - lua_pushliteral(L, DLMSG); - return NULL; -} - - -static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { - (void)(lib); (void)(sym); /* not used */ - lua_pushliteral(L, DLMSG); - return NULL; -} - -/* }====================================================== */ -#endif - - -static void *ll_checkclib (lua_State *L, const char *path) { - void *plib; - lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); - lua_getfield(L, -1, path); - plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */ - lua_pop(L, 2); /* pop CLIBS table and 'plib' */ - return plib; -} - - -static void ll_addtoclib (lua_State *L, const char *path, void *plib) { - lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); - lua_pushlightuserdata(L, plib); - lua_pushvalue(L, -1); - lua_setfield(L, -3, path); /* CLIBS[path] = plib */ - lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */ - lua_pop(L, 1); /* pop CLIBS table */ -} - - -/* -** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib -** handles in list CLIBS -*/ -static int gctm (lua_State *L) { - int n = luaL_len(L, 1); - for (; n >= 1; n--) { /* for each handle, in reverse order */ - lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */ - ll_unloadlib(lua_touserdata(L, -1)); - lua_pop(L, 1); /* pop handle */ - } - return 0; -} - - -static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { - void *reg = ll_checkclib(L, path); /* check loaded C libraries */ - if (reg == NULL) { /* must load library? */ - reg = ll_load(L, path, *sym == '*'); - if (reg == NULL) return ERRLIB; /* unable to load library */ - ll_addtoclib(L, path, reg); - } - if (*sym == '*') { /* loading only library (no function)? */ - lua_pushboolean(L, 1); /* return 'true' */ - return 0; /* no errors */ - } - else { - lua_CFunction f = ll_sym(L, reg, sym); - if (f == NULL) - return ERRFUNC; /* unable to find function */ - lua_pushcfunction(L, f); /* else create new function */ - return 0; /* no errors */ - } -} - - -static int ll_loadlib (lua_State *L) { - const char *path = luaL_checkstring(L, 1); - const char *init = luaL_checkstring(L, 2); - int stat = ll_loadfunc(L, path, init); - if (stat == 0) /* no errors? */ - return 1; /* return the loaded function */ - else { /* error; error message is on stack top */ - lua_pushnil(L); - lua_insert(L, -2); - lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); - return 3; /* return nil, error message, and where */ - } -} - - - -/* -** {====================================================== -** 'require' function -** ======================================================= -*/ - - -static int readable (const char *filename) { - FILE *f = fopen(filename, "r"); /* try to open file */ - if (f == NULL) return 0; /* open failed */ - fclose(f); - return 1; -} - - -static const char *pushnexttemplate (lua_State *L, const char *path) { - const char *l; - while (*path == *LUA_PATH_SEP) path++; /* skip separators */ - if (*path == '\0') return NULL; /* no more templates */ - l = strchr(path, *LUA_PATH_SEP); /* find next separator */ - if (l == NULL) l = path + strlen(path); - lua_pushlstring(L, path, l - path); /* template */ - return l; -} - - -static const char *searchpath (lua_State *L, const char *name, - const char *path, - const char *sep, - const char *dirsep) { - luaL_Buffer msg; /* to build error message */ - luaL_buffinit(L, &msg); - if (*sep != '\0') /* non-empty separator? */ - name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */ - while ((path = pushnexttemplate(L, path)) != NULL) { - const char *filename = luaL_gsub(L, lua_tostring(L, -1), - LUA_PATH_MARK, name); - lua_remove(L, -2); /* remove path template */ - if (readable(filename)) /* does file exist and is readable? */ - return filename; /* return that file name */ - lua_pushfstring(L, "\n\tno file " LUA_QS, filename); - lua_remove(L, -2); /* remove file name */ - luaL_addvalue(&msg); /* concatenate error msg. entry */ - } - luaL_pushresult(&msg); /* create error message */ - return NULL; /* not found */ -} - - -static int ll_searchpath (lua_State *L) { - const char *f = searchpath(L, luaL_checkstring(L, 1), - luaL_checkstring(L, 2), - luaL_optstring(L, 3, "."), - luaL_optstring(L, 4, LUA_DIRSEP)); - if (f != NULL) return 1; - else { /* error message is on top of the stack */ - lua_pushnil(L); - lua_insert(L, -2); - return 2; /* return nil + error message */ - } -} - - -static const char *findfile (lua_State *L, const char *name, - const char *pname, - const char *dirsep) { - const char *path; - lua_getfield(L, lua_upvalueindex(1), pname); - path = lua_tostring(L, -1); - if (path == NULL) - luaL_error(L, LUA_QL("package.%s") " must be a string", pname); - return searchpath(L, name, path, ".", dirsep); -} - - -static int checkload (lua_State *L, int stat, const char *filename) { - if (stat) { /* module loaded successfully? */ - lua_pushstring(L, filename); /* will be 2nd argument to module */ - return 2; /* return open function and file name */ - } - else - return luaL_error(L, "error loading module " LUA_QS - " from file " LUA_QS ":\n\t%s", - lua_tostring(L, 1), filename, lua_tostring(L, -1)); -} - - -static int searcher_Lua (lua_State *L) { - const char *filename; - const char *name = luaL_checkstring(L, 1); - filename = findfile(L, name, "path", LUA_LSUBSEP); - if (filename == NULL) return 1; /* module not found in this path */ - return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename); -} - - -static int loadfunc (lua_State *L, const char *filename, const char *modname) { - const char *funcname; - const char *mark; - modname = luaL_gsub(L, modname, ".", LUA_OFSEP); - mark = strchr(modname, *LUA_IGMARK); - if (mark) { - int stat; - funcname = lua_pushlstring(L, modname, mark - modname); - funcname = lua_pushfstring(L, LUA_POF"%s", funcname); - stat = ll_loadfunc(L, filename, funcname); - if (stat != ERRFUNC) return stat; - modname = mark + 1; /* else go ahead and try old-style name */ - } - funcname = lua_pushfstring(L, LUA_POF"%s", modname); - return ll_loadfunc(L, filename, funcname); -} - - -static int searcher_C (lua_State *L) { - const char *name = luaL_checkstring(L, 1); - const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP); - if (filename == NULL) return 1; /* module not found in this path */ - return checkload(L, (loadfunc(L, filename, name) == 0), filename); -} - - -static int searcher_Croot (lua_State *L) { - const char *filename; - const char *name = luaL_checkstring(L, 1); - const char *p = strchr(name, '.'); - int stat; - if (p == NULL) return 0; /* is root */ - lua_pushlstring(L, name, p - name); - filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP); - if (filename == NULL) return 1; /* root not found */ - if ((stat = loadfunc(L, filename, name)) != 0) { - if (stat != ERRFUNC) - return checkload(L, 0, filename); /* real error */ - else { /* open function not found */ - lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS, - name, filename); - return 1; - } - } - lua_pushstring(L, filename); /* will be 2nd argument to module */ - return 2; -} - - -static int searcher_preload (lua_State *L) { - const char *name = luaL_checkstring(L, 1); - lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD"); - lua_getfield(L, -1, name); - if (lua_isnil(L, -1)) /* not found? */ - lua_pushfstring(L, "\n\tno field package.preload['%s']", name); - return 1; -} - - -static void findloader (lua_State *L, const char *name) { - int i; - luaL_Buffer msg; /* to build error message */ - luaL_buffinit(L, &msg); - lua_getfield(L, lua_upvalueindex(1), "searchers"); /* will be at index 3 */ - if (!lua_istable(L, 3)) - luaL_error(L, LUA_QL("package.searchers") " must be a table"); - /* iterate over available searchers to find a loader */ - for (i = 1; ; i++) { - lua_rawgeti(L, 3, i); /* get a searcher */ - if (lua_isnil(L, -1)) { /* no more searchers? */ - lua_pop(L, 1); /* remove nil */ - luaL_pushresult(&msg); /* create error message */ - luaL_error(L, "module " LUA_QS " not found:%s", - name, lua_tostring(L, -1)); - } - lua_pushstring(L, name); - lua_call(L, 1, 2); /* call it */ - if (lua_isfunction(L, -2)) /* did it find a loader? */ - return; /* module loader found */ - else if (lua_isstring(L, -2)) { /* searcher returned error message? */ - lua_pop(L, 1); /* remove extra return */ - luaL_addvalue(&msg); /* concatenate error message */ - } - else - lua_pop(L, 2); /* remove both returns */ - } -} - - -static int ll_require (lua_State *L) { - const char *name = luaL_checkstring(L, 1); - lua_settop(L, 1); /* _LOADED table will be at index 2 */ - lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); - lua_getfield(L, 2, name); /* _LOADED[name] */ - if (lua_toboolean(L, -1)) /* is it there? */ - return 1; /* package is already loaded */ - /* else must load package */ - lua_pop(L, 1); /* remove 'getfield' result */ - findloader(L, name); - lua_pushstring(L, name); /* pass name as argument to module loader */ - lua_insert(L, -2); /* name is 1st argument (before search data) */ - lua_call(L, 2, 1); /* run loader to load module */ - if (!lua_isnil(L, -1)) /* non-nil return? */ - lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ - lua_getfield(L, 2, name); - if (lua_isnil(L, -1)) { /* module did not set a value? */ - lua_pushboolean(L, 1); /* use true as result */ - lua_pushvalue(L, -1); /* extra copy to be returned */ - lua_setfield(L, 2, name); /* _LOADED[name] = true */ - } - return 1; -} - -/* }====================================================== */ - - - -/* -** {====================================================== -** 'module' function -** ======================================================= -*/ -#if defined(LUA_COMPAT_MODULE) - -/* -** changes the environment variable of calling function -*/ -static void set_env (lua_State *L) { - lua_Debug ar; - if (lua_getstack(L, 1, &ar) == 0 || - lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ - lua_iscfunction(L, -1)) - luaL_error(L, LUA_QL("module") " not called from a Lua function"); - lua_pushvalue(L, -2); /* copy new environment table to top */ - lua_setupvalue(L, -2, 1); - lua_pop(L, 1); /* remove function */ -} - - -static void dooptions (lua_State *L, int n) { - int i; - for (i = 2; i <= n; i++) { - if (lua_isfunction(L, i)) { /* avoid 'calling' extra info. */ - lua_pushvalue(L, i); /* get option (a function) */ - lua_pushvalue(L, -2); /* module */ - lua_call(L, 1, 0); - } - } -} - - -static void modinit (lua_State *L, const char *modname) { - const char *dot; - lua_pushvalue(L, -1); - lua_setfield(L, -2, "_M"); /* module._M = module */ - lua_pushstring(L, modname); - lua_setfield(L, -2, "_NAME"); - dot = strrchr(modname, '.'); /* look for last dot in module name */ - if (dot == NULL) dot = modname; - else dot++; - /* set _PACKAGE as package name (full module name minus last part) */ - lua_pushlstring(L, modname, dot - modname); - lua_setfield(L, -2, "_PACKAGE"); -} - - -static int ll_module (lua_State *L) { - const char *modname = luaL_checkstring(L, 1); - int lastarg = lua_gettop(L); /* last parameter */ - luaL_pushmodule(L, modname, 1); /* get/create module table */ - /* check whether table already has a _NAME field */ - lua_getfield(L, -1, "_NAME"); - if (!lua_isnil(L, -1)) /* is table an initialized module? */ - lua_pop(L, 1); - else { /* no; initialize it */ - lua_pop(L, 1); - modinit(L, modname); - } - lua_pushvalue(L, -1); - set_env(L); - dooptions(L, lastarg); - return 1; -} - - -static int ll_seeall (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - if (!lua_getmetatable(L, 1)) { - lua_createtable(L, 0, 1); /* create new metatable */ - lua_pushvalue(L, -1); - lua_setmetatable(L, 1); - } - lua_pushglobaltable(L); - lua_setfield(L, -2, "__index"); /* mt.__index = _G */ - return 0; -} - -#endif -/* }====================================================== */ - - - -/* auxiliary mark (for internal use) */ -#define AUXMARK "\1" - - -/* -** return registry.LUA_NOENV as a boolean -*/ -static int noenv (lua_State *L) { - int b; - lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); - b = lua_toboolean(L, -1); - lua_pop(L, 1); /* remove value */ - return b; -} - - -static void setpath (lua_State *L, const char *fieldname, const char *envname1, - const char *envname2, const char *def) { - const char *path = getenv(envname1); - if (path == NULL) /* no environment variable? */ - path = getenv(envname2); /* try alternative name */ - if (path == NULL || noenv(L)) /* no environment variable? */ - lua_pushstring(L, def); /* use default */ - else { - /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ - path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP, - LUA_PATH_SEP AUXMARK LUA_PATH_SEP); - luaL_gsub(L, path, AUXMARK, def); - lua_remove(L, -2); - } - setprogdir(L); - lua_setfield(L, -2, fieldname); -} - - -static const luaL_Reg pk_funcs[] = { - {"loadlib", ll_loadlib}, - {"searchpath", ll_searchpath}, -#if defined(LUA_COMPAT_MODULE) - {"seeall", ll_seeall}, -#endif - {NULL, NULL} -}; - - -static const luaL_Reg ll_funcs[] = { -#if defined(LUA_COMPAT_MODULE) - {"module", ll_module}, -#endif - {"require", ll_require}, - {NULL, NULL} -}; - - -static void createsearcherstable (lua_State *L) { - static const lua_CFunction searchers[] = - {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL}; - int i; - /* create 'searchers' table */ - lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0); - /* fill it with pre-defined searchers */ - for (i=0; searchers[i] != NULL; i++) { - lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */ - lua_pushcclosure(L, searchers[i], 1); - lua_rawseti(L, -2, i+1); - } -} - - -LUAMOD_API int luaopen_package (lua_State *L) { - /* create table CLIBS to keep track of loaded C libraries */ - luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); - lua_createtable(L, 0, 1); /* metatable for CLIBS */ - lua_pushcfunction(L, gctm); - lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */ - lua_setmetatable(L, -2); - /* create `package' table */ - luaL_newlib(L, pk_funcs); - createsearcherstable(L); -#if defined(LUA_COMPAT_LOADERS) - lua_pushvalue(L, -1); /* make a copy of 'searchers' table */ - lua_setfield(L, -3, "loaders"); /* put it in field `loaders' */ -#endif - lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ - /* set field 'path' */ - setpath(L, "path", LUA_PATHVERSION, LUA_PATH, LUA_PATH_DEFAULT); - /* set field 'cpath' */ - setpath(L, "cpath", LUA_CPATHVERSION, LUA_CPATH, LUA_CPATH_DEFAULT); - /* store config information */ - lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n" - LUA_EXEC_DIR "\n" LUA_IGMARK "\n"); - lua_setfield(L, -2, "config"); - /* set field `loaded' */ - luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); - lua_setfield(L, -2, "loaded"); - /* set field `preload' */ - luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD"); - lua_setfield(L, -2, "preload"); - lua_pushglobaltable(L); - lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */ - luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */ - lua_pop(L, 1); /* pop global table */ - return 1; /* return 'package' table */ -} - diff --git a/contrib/lua/lua/src/lobject.c b/contrib/lua/lua/src/lobject.c deleted file mode 100644 index c152785a5a7..00000000000 --- a/contrib/lua/lua/src/lobject.c +++ /dev/null @@ -1,287 +0,0 @@ -/* -** $Id: lobject.c,v 2.58 2013/02/20 14:08:56 roberto Exp $ -** Some generic functions over Lua objects -** See Copyright Notice in lua.h -*/ - -#include -#include -#include -#include - -#define lobject_c -#define LUA_CORE - -#include "lua.h" - -#include "lctype.h" -#include "ldebug.h" -#include "ldo.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "lvm.h" - - - -LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT}; - - -/* -** converts an integer to a "floating point byte", represented as -** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if -** eeeee != 0 and (xxx) otherwise. -*/ -int luaO_int2fb (unsigned int x) { - int e = 0; /* exponent */ - if (x < 8) return x; - while (x >= 0x10) { - x = (x+1) >> 1; - e++; - } - return ((e+1) << 3) | (cast_int(x) - 8); -} - - -/* converts back */ -int luaO_fb2int (int x) { - int e = (x >> 3) & 0x1f; - if (e == 0) return x; - else return ((x & 7) + 8) << (e - 1); -} - - -int luaO_ceillog2 (unsigned int x) { - static const lu_byte log_2[256] = { - 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, - 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 - }; - int l = 0; - x--; - while (x >= 256) { l += 8; x >>= 8; } - return l + log_2[x]; -} - - -lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2) { - switch (op) { - case LUA_OPADD: return luai_numadd(NULL, v1, v2); - case LUA_OPSUB: return luai_numsub(NULL, v1, v2); - case LUA_OPMUL: return luai_nummul(NULL, v1, v2); - case LUA_OPDIV: return luai_numdiv(NULL, v1, v2); - case LUA_OPMOD: return luai_nummod(NULL, v1, v2); - case LUA_OPPOW: return luai_numpow(NULL, v1, v2); - case LUA_OPUNM: return luai_numunm(NULL, v1); - default: lua_assert(0); return 0; - } -} - - -int luaO_hexavalue (int c) { - if (lisdigit(c)) return c - '0'; - else return ltolower(c) - 'a' + 10; -} - - -#if !defined(lua_strx2number) - -#include - - -static int isneg (const char **s) { - if (**s == '-') { (*s)++; return 1; } - else if (**s == '+') (*s)++; - return 0; -} - - -static lua_Number readhexa (const char **s, lua_Number r, int *count) { - for (; lisxdigit(cast_uchar(**s)); (*s)++) { /* read integer part */ - r = (r * cast_num(16.0)) + cast_num(luaO_hexavalue(cast_uchar(**s))); - (*count)++; - } - return r; -} - - -/* -** convert an hexadecimal numeric string to a number, following -** C99 specification for 'strtod' -*/ -static lua_Number lua_strx2number (const char *s, char **endptr) { - lua_Number r = 0.0; - int e = 0, i = 0; - int neg = 0; /* 1 if number is negative */ - *endptr = cast(char *, s); /* nothing is valid yet */ - while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ - neg = isneg(&s); /* check signal */ - if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ - return 0.0; /* invalid format (no '0x') */ - s += 2; /* skip '0x' */ - r = readhexa(&s, r, &i); /* read integer part */ - if (*s == '.') { - s++; /* skip dot */ - r = readhexa(&s, r, &e); /* read fractional part */ - } - if (i == 0 && e == 0) - return 0.0; /* invalid format (no digit) */ - e *= -4; /* each fractional digit divides value by 2^-4 */ - *endptr = cast(char *, s); /* valid up to here */ - if (*s == 'p' || *s == 'P') { /* exponent part? */ - int exp1 = 0; - int neg1; - s++; /* skip 'p' */ - neg1 = isneg(&s); /* signal */ - if (!lisdigit(cast_uchar(*s))) - goto ret; /* must have at least one digit */ - while (lisdigit(cast_uchar(*s))) /* read exponent */ - exp1 = exp1 * 10 + *(s++) - '0'; - if (neg1) exp1 = -exp1; - e += exp1; - } - *endptr = cast(char *, s); /* valid up to here */ - ret: - if (neg) r = -r; - return l_mathop(ldexp)(r, e); -} - -#endif - - -int luaO_str2d (const char *s, size_t len, lua_Number *result) { - char *endptr; - if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */ - return 0; - else if (strpbrk(s, "xX")) /* hexa? */ - *result = lua_strx2number(s, &endptr); - else - *result = lua_str2number(s, &endptr); - if (endptr == s) return 0; /* nothing recognized */ - while (lisspace(cast_uchar(*endptr))) endptr++; - return (endptr == s + len); /* OK if no trailing characters */ -} - - - -static void pushstr (lua_State *L, const char *str, size_t l) { - setsvalue2s(L, L->top++, luaS_newlstr(L, str, l)); -} - - -/* this function handles only `%d', `%c', %f, %p, and `%s' formats */ -const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { - int n = 0; - for (;;) { - const char *e = strchr(fmt, '%'); - if (e == NULL) break; - luaD_checkstack(L, 2); /* fmt + item */ - pushstr(L, fmt, e - fmt); - switch (*(e+1)) { - case 's': { - const char *s = va_arg(argp, char *); - if (s == NULL) s = "(null)"; - pushstr(L, s, strlen(s)); - break; - } - case 'c': { - char buff; - buff = cast(char, va_arg(argp, int)); - pushstr(L, &buff, 1); - break; - } - case 'd': { - setnvalue(L->top++, cast_num(va_arg(argp, int))); - break; - } - case 'f': { - setnvalue(L->top++, cast_num(va_arg(argp, l_uacNumber))); - break; - } - case 'p': { - char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ - int l = sprintf(buff, "%p", va_arg(argp, void *)); - pushstr(L, buff, l); - break; - } - case '%': { - pushstr(L, "%", 1); - break; - } - default: { - luaG_runerror(L, - "invalid option " LUA_QL("%%%c") " to " LUA_QL("lua_pushfstring"), - *(e + 1)); - } - } - n += 2; - fmt = e+2; - } - luaD_checkstack(L, 1); - pushstr(L, fmt, strlen(fmt)); - if (n > 0) luaV_concat(L, n + 1); - return svalue(L->top - 1); -} - - -const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { - const char *msg; - va_list argp; - va_start(argp, fmt); - msg = luaO_pushvfstring(L, fmt, argp); - va_end(argp); - return msg; -} - - -/* number of chars of a literal string without the ending \0 */ -#define LL(x) (sizeof(x)/sizeof(char) - 1) - -#define RETS "..." -#define PRE "[string \"" -#define POS "\"]" - -#define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) ) - -void luaO_chunkid (char *out, const char *source, size_t bufflen) { - size_t l = strlen(source); - if (*source == '=') { /* 'literal' source */ - if (l <= bufflen) /* small enough? */ - memcpy(out, source + 1, l * sizeof(char)); - else { /* truncate it */ - addstr(out, source + 1, bufflen - 1); - *out = '\0'; - } - } - else if (*source == '@') { /* file name */ - if (l <= bufflen) /* small enough? */ - memcpy(out, source + 1, l * sizeof(char)); - else { /* add '...' before rest of name */ - addstr(out, RETS, LL(RETS)); - bufflen -= LL(RETS); - memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char)); - } - } - else { /* string; format as [string "source"] */ - const char *nl = strchr(source, '\n'); /* find first new line (if any) */ - addstr(out, PRE, LL(PRE)); /* add prefix */ - bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */ - if (l < bufflen && nl == NULL) { /* small one-line source? */ - addstr(out, source, l); /* keep it */ - } - else { - if (nl != NULL) l = nl - source; /* stop at first newline */ - if (l > bufflen) l = bufflen; - addstr(out, source, l); - addstr(out, RETS, LL(RETS)); - } - memcpy(out, POS, (LL(POS) + 1) * sizeof(char)); - } -} - diff --git a/contrib/lua/lua/src/lobject.h b/contrib/lua/lua/src/lobject.h deleted file mode 100644 index dd23b9143cd..00000000000 --- a/contrib/lua/lua/src/lobject.h +++ /dev/null @@ -1,607 +0,0 @@ -/* -** $Id: lobject.h,v 2.71 2012/09/11 18:21:44 roberto Exp $ -** Type definitions for Lua objects -** See Copyright Notice in lua.h -*/ - - -#ifndef lobject_h -#define lobject_h - - -#include - - -#include "llimits.h" -#include "lua.h" - - -/* -** Extra tags for non-values -*/ -#define LUA_TPROTO LUA_NUMTAGS -#define LUA_TUPVAL (LUA_NUMTAGS+1) -#define LUA_TDEADKEY (LUA_NUMTAGS+2) - -/* -** number of all possible tags (including LUA_TNONE but excluding DEADKEY) -*/ -#define LUA_TOTALTAGS (LUA_TUPVAL+2) - - -/* -** tags for Tagged Values have the following use of bits: -** bits 0-3: actual tag (a LUA_T* value) -** bits 4-5: variant bits -** bit 6: whether value is collectable -*/ - -#define VARBITS (3 << 4) - - -/* -** LUA_TFUNCTION variants: -** 0 - Lua function -** 1 - light C function -** 2 - regular C function (closure) -*/ - -/* Variant tags for functions */ -#define LUA_TLCL (LUA_TFUNCTION | (0 << 4)) /* Lua closure */ -#define LUA_TLCF (LUA_TFUNCTION | (1 << 4)) /* light C function */ -#define LUA_TCCL (LUA_TFUNCTION | (2 << 4)) /* C closure */ - - -/* Variant tags for strings */ -#define LUA_TSHRSTR (LUA_TSTRING | (0 << 4)) /* short strings */ -#define LUA_TLNGSTR (LUA_TSTRING | (1 << 4)) /* long strings */ - - -/* Bit mark for collectable types */ -#define BIT_ISCOLLECTABLE (1 << 6) - -/* mark a tag as collectable */ -#define ctb(t) ((t) | BIT_ISCOLLECTABLE) - - -/* -** Union of all collectable objects -*/ -typedef union GCObject GCObject; - - -/* -** Common Header for all collectable objects (in macro form, to be -** included in other objects) -*/ -#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked - - -/* -** Common header in struct form -*/ -typedef struct GCheader { - CommonHeader; -} GCheader; - - - -/* -** Union of all Lua values -*/ -typedef union Value Value; - - -#define numfield lua_Number n; /* numbers */ - - - -/* -** Tagged Values. This is the basic representation of values in Lua, -** an actual value plus a tag with its type. -*/ - -#define TValuefields Value value_; int tt_ - -typedef struct lua_TValue TValue; - - -/* macro defining a nil value */ -#define NILCONSTANT {NULL}, LUA_TNIL - - -#define val_(o) ((o)->value_) -#define num_(o) (val_(o).n) - - -/* raw type tag of a TValue */ -#define rttype(o) ((o)->tt_) - -/* tag with no variants (bits 0-3) */ -#define novariant(x) ((x) & 0x0F) - -/* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */ -#define ttype(o) (rttype(o) & 0x3F) - -/* type tag of a TValue with no variants (bits 0-3) */ -#define ttypenv(o) (novariant(rttype(o))) - - -/* Macros to test type */ -#define checktag(o,t) (rttype(o) == (t)) -#define checktype(o,t) (ttypenv(o) == (t)) -#define ttisnumber(o) checktag((o), LUA_TNUMBER) -#define ttisnil(o) checktag((o), LUA_TNIL) -#define ttisboolean(o) checktag((o), LUA_TBOOLEAN) -#define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA) -#define ttisstring(o) checktype((o), LUA_TSTRING) -#define ttisshrstring(o) checktag((o), ctb(LUA_TSHRSTR)) -#define ttislngstring(o) checktag((o), ctb(LUA_TLNGSTR)) -#define ttistable(o) checktag((o), ctb(LUA_TTABLE)) -#define ttisfunction(o) checktype(o, LUA_TFUNCTION) -#define ttisclosure(o) ((rttype(o) & 0x1F) == LUA_TFUNCTION) -#define ttisCclosure(o) checktag((o), ctb(LUA_TCCL)) -#define ttisLclosure(o) checktag((o), ctb(LUA_TLCL)) -#define ttislcf(o) checktag((o), LUA_TLCF) -#define ttisuserdata(o) checktag((o), ctb(LUA_TUSERDATA)) -#define ttisthread(o) checktag((o), ctb(LUA_TTHREAD)) -#define ttisdeadkey(o) checktag((o), LUA_TDEADKEY) - -#define ttisequal(o1,o2) (rttype(o1) == rttype(o2)) - -/* Macros to access values */ -#define nvalue(o) check_exp(ttisnumber(o), num_(o)) -#define gcvalue(o) check_exp(iscollectable(o), val_(o).gc) -#define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p) -#define rawtsvalue(o) check_exp(ttisstring(o), &val_(o).gc->ts) -#define tsvalue(o) (&rawtsvalue(o)->tsv) -#define rawuvalue(o) check_exp(ttisuserdata(o), &val_(o).gc->u) -#define uvalue(o) (&rawuvalue(o)->uv) -#define clvalue(o) check_exp(ttisclosure(o), &val_(o).gc->cl) -#define clLvalue(o) check_exp(ttisLclosure(o), &val_(o).gc->cl.l) -#define clCvalue(o) check_exp(ttisCclosure(o), &val_(o).gc->cl.c) -#define fvalue(o) check_exp(ttislcf(o), val_(o).f) -#define hvalue(o) check_exp(ttistable(o), &val_(o).gc->h) -#define bvalue(o) check_exp(ttisboolean(o), val_(o).b) -#define thvalue(o) check_exp(ttisthread(o), &val_(o).gc->th) -/* a dead value may get the 'gc' field, but cannot access its contents */ -#define deadvalue(o) check_exp(ttisdeadkey(o), cast(void *, val_(o).gc)) - -#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) - - -#define iscollectable(o) (rttype(o) & BIT_ISCOLLECTABLE) - - -/* Macros for internal tests */ -#define righttt(obj) (ttype(obj) == gcvalue(obj)->gch.tt) - -#define checkliveness(g,obj) \ - lua_longassert(!iscollectable(obj) || \ - (righttt(obj) && !isdead(g,gcvalue(obj)))) - - -/* Macros to set values */ -#define settt_(o,t) ((o)->tt_=(t)) - -#define setnvalue(obj,x) \ - { TValue *io=(obj); num_(io)=(x); settt_(io, LUA_TNUMBER); } - -#define setnilvalue(obj) settt_(obj, LUA_TNIL) - -#define setfvalue(obj,x) \ - { TValue *io=(obj); val_(io).f=(x); settt_(io, LUA_TLCF); } - -#define setpvalue(obj,x) \ - { TValue *io=(obj); val_(io).p=(x); settt_(io, LUA_TLIGHTUSERDATA); } - -#define setbvalue(obj,x) \ - { TValue *io=(obj); val_(io).b=(x); settt_(io, LUA_TBOOLEAN); } - -#define setgcovalue(L,obj,x) \ - { TValue *io=(obj); GCObject *i_g=(x); \ - val_(io).gc=i_g; settt_(io, ctb(gch(i_g)->tt)); } - -#define setsvalue(L,obj,x) \ - { TValue *io=(obj); \ - TString *x_ = (x); \ - val_(io).gc=cast(GCObject *, x_); settt_(io, ctb(x_->tsv.tt)); \ - checkliveness(G(L),io); } - -#define setuvalue(L,obj,x) \ - { TValue *io=(obj); \ - val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TUSERDATA)); \ - checkliveness(G(L),io); } - -#define setthvalue(L,obj,x) \ - { TValue *io=(obj); \ - val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTHREAD)); \ - checkliveness(G(L),io); } - -#define setclLvalue(L,obj,x) \ - { TValue *io=(obj); \ - val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TLCL)); \ - checkliveness(G(L),io); } - -#define setclCvalue(L,obj,x) \ - { TValue *io=(obj); \ - val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TCCL)); \ - checkliveness(G(L),io); } - -#define sethvalue(L,obj,x) \ - { TValue *io=(obj); \ - val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTABLE)); \ - checkliveness(G(L),io); } - -#define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY) - - - -#define setobj(L,obj1,obj2) \ - { const TValue *io2=(obj2); TValue *io1=(obj1); \ - io1->value_ = io2->value_; io1->tt_ = io2->tt_; \ - checkliveness(G(L),io1); } - - -/* -** different types of assignments, according to destination -*/ - -/* from stack to (same) stack */ -#define setobjs2s setobj -/* to stack (not from same stack) */ -#define setobj2s setobj -#define setsvalue2s setsvalue -#define sethvalue2s sethvalue -#define setptvalue2s setptvalue -/* from table to same table */ -#define setobjt2t setobj -/* to table */ -#define setobj2t setobj -/* to new object */ -#define setobj2n setobj -#define setsvalue2n setsvalue - - -/* check whether a number is valid (useful only for NaN trick) */ -#define luai_checknum(L,o,c) { /* empty */ } - - -/* -** {====================================================== -** NaN Trick -** ======================================================= -*/ -#if defined(LUA_NANTRICK) - -/* -** numbers are represented in the 'd_' field. All other values have the -** value (NNMARK | tag) in 'tt__'. A number with such pattern would be -** a "signaled NaN", which is never generated by regular operations by -** the CPU (nor by 'strtod') -*/ - -/* allows for external implementation for part of the trick */ -#if !defined(NNMARK) /* { */ - - -#if !defined(LUA_IEEEENDIAN) -#error option 'LUA_NANTRICK' needs 'LUA_IEEEENDIAN' -#endif - - -#define NNMARK 0x7FF7A500 -#define NNMASK 0x7FFFFF00 - -#undef TValuefields -#undef NILCONSTANT - -#if (LUA_IEEEENDIAN == 0) /* { */ - -/* little endian */ -#define TValuefields \ - union { struct { Value v__; int tt__; } i; double d__; } u -#define NILCONSTANT {{{NULL}, tag2tt(LUA_TNIL)}} -/* field-access macros */ -#define v_(o) ((o)->u.i.v__) -#define d_(o) ((o)->u.d__) -#define tt_(o) ((o)->u.i.tt__) - -#else /* }{ */ - -/* big endian */ -#define TValuefields \ - union { struct { int tt__; Value v__; } i; double d__; } u -#define NILCONSTANT {{tag2tt(LUA_TNIL), {NULL}}} -/* field-access macros */ -#define v_(o) ((o)->u.i.v__) -#define d_(o) ((o)->u.d__) -#define tt_(o) ((o)->u.i.tt__) - -#endif /* } */ - -#endif /* } */ - - -/* correspondence with standard representation */ -#undef val_ -#define val_(o) v_(o) -#undef num_ -#define num_(o) d_(o) - - -#undef numfield -#define numfield /* no such field; numbers are the entire struct */ - -/* basic check to distinguish numbers from non-numbers */ -#undef ttisnumber -#define ttisnumber(o) ((tt_(o) & NNMASK) != NNMARK) - -#define tag2tt(t) (NNMARK | (t)) - -#undef rttype -#define rttype(o) (ttisnumber(o) ? LUA_TNUMBER : tt_(o) & 0xff) - -#undef settt_ -#define settt_(o,t) (tt_(o) = tag2tt(t)) - -#undef setnvalue -#define setnvalue(obj,x) \ - { TValue *io_=(obj); num_(io_)=(x); lua_assert(ttisnumber(io_)); } - -#undef setobj -#define setobj(L,obj1,obj2) \ - { const TValue *o2_=(obj2); TValue *o1_=(obj1); \ - o1_->u = o2_->u; \ - checkliveness(G(L),o1_); } - - -/* -** these redefinitions are not mandatory, but these forms are more efficient -*/ - -#undef checktag -#undef checktype -#define checktag(o,t) (tt_(o) == tag2tt(t)) -#define checktype(o,t) (ctb(tt_(o) | VARBITS) == ctb(tag2tt(t) | VARBITS)) - -#undef ttisequal -#define ttisequal(o1,o2) \ - (ttisnumber(o1) ? ttisnumber(o2) : (tt_(o1) == tt_(o2))) - - -#undef luai_checknum -#define luai_checknum(L,o,c) { if (!ttisnumber(o)) c; } - -#endif -/* }====================================================== */ - - - -/* -** {====================================================== -** types and prototypes -** ======================================================= -*/ - - -union Value { - GCObject *gc; /* collectable objects */ - void *p; /* light userdata */ - int b; /* booleans */ - lua_CFunction f; /* light C functions */ - numfield /* numbers */ -}; - - -struct lua_TValue { - TValuefields; -}; - - -typedef TValue *StkId; /* index to stack elements */ - - - - -/* -** Header for string value; string bytes follow the end of this structure -*/ -typedef union TString { - L_Umaxalign dummy; /* ensures maximum alignment for strings */ - struct { - CommonHeader; - lu_byte extra; /* reserved words for short strings; "has hash" for longs */ - unsigned int hash; - size_t len; /* number of characters in string */ - } tsv; -} TString; - - -/* get the actual string (array of bytes) from a TString */ -#define getstr(ts) cast(const char *, (ts) + 1) - -/* get the actual string (array of bytes) from a Lua value */ -#define svalue(o) getstr(rawtsvalue(o)) - - -/* -** Header for userdata; memory area follows the end of this structure -*/ -typedef union Udata { - L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ - struct { - CommonHeader; - struct Table *metatable; - struct Table *env; - size_t len; /* number of bytes */ - } uv; -} Udata; - - - -/* -** Description of an upvalue for function prototypes -*/ -typedef struct Upvaldesc { - TString *name; /* upvalue name (for debug information) */ - lu_byte instack; /* whether it is in stack */ - lu_byte idx; /* index of upvalue (in stack or in outer function's list) */ -} Upvaldesc; - - -/* -** Description of a local variable for function prototypes -** (used for debug information) -*/ -typedef struct LocVar { - TString *varname; - int startpc; /* first point where variable is active */ - int endpc; /* first point where variable is dead */ -} LocVar; - - -/* -** Function Prototypes -*/ -typedef struct Proto { - CommonHeader; - TValue *k; /* constants used by the function */ - Instruction *code; - struct Proto **p; /* functions defined inside the function */ - int *lineinfo; /* map from opcodes to source lines (debug information) */ - LocVar *locvars; /* information about local variables (debug information) */ - Upvaldesc *upvalues; /* upvalue information */ - union Closure *cache; /* last created closure with this prototype */ - TString *source; /* used for debug information */ - int sizeupvalues; /* size of 'upvalues' */ - int sizek; /* size of `k' */ - int sizecode; - int sizelineinfo; - int sizep; /* size of `p' */ - int sizelocvars; - int linedefined; - int lastlinedefined; - GCObject *gclist; - lu_byte numparams; /* number of fixed parameters */ - lu_byte is_vararg; - lu_byte maxstacksize; /* maximum stack used by this function */ -} Proto; - - - -/* -** Lua Upvalues -*/ -typedef struct UpVal { - CommonHeader; - TValue *v; /* points to stack or to its own value */ - union { - TValue value; /* the value (when closed) */ - struct { /* double linked list (when open) */ - struct UpVal *prev; - struct UpVal *next; - } l; - } u; -} UpVal; - - -/* -** Closures -*/ - -#define ClosureHeader \ - CommonHeader; lu_byte nupvalues; GCObject *gclist - -typedef struct CClosure { - ClosureHeader; - lua_CFunction f; - TValue upvalue[1]; /* list of upvalues */ -} CClosure; - - -typedef struct LClosure { - ClosureHeader; - struct Proto *p; - UpVal *upvals[1]; /* list of upvalues */ -} LClosure; - - -typedef union Closure { - CClosure c; - LClosure l; -} Closure; - - -#define isLfunction(o) ttisLclosure(o) - -#define getproto(o) (clLvalue(o)->p) - - -/* -** Tables -*/ - -typedef union TKey { - struct { - TValuefields; - struct Node *next; /* for chaining */ - } nk; - TValue tvk; -} TKey; - - -typedef struct Node { - TValue i_val; - TKey i_key; -} Node; - - -typedef struct Table { - CommonHeader; - lu_byte flags; /* 1<

lsizenode)) - - -/* -** (address of) a fixed nil value -*/ -#define luaO_nilobject (&luaO_nilobject_) - - -LUAI_DDEC const TValue luaO_nilobject_; - - -LUAI_FUNC int luaO_int2fb (unsigned int x); -LUAI_FUNC int luaO_fb2int (int x); -LUAI_FUNC int luaO_ceillog2 (unsigned int x); -LUAI_FUNC lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2); -LUAI_FUNC int luaO_str2d (const char *s, size_t len, lua_Number *result); -LUAI_FUNC int luaO_hexavalue (int c); -LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, - va_list argp); -LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); -LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len); - - -#endif - diff --git a/contrib/lua/lua/src/lopcodes.c b/contrib/lua/lua/src/lopcodes.c deleted file mode 100644 index ef73692754e..00000000000 --- a/contrib/lua/lua/src/lopcodes.c +++ /dev/null @@ -1,107 +0,0 @@ -/* -** $Id: lopcodes.c,v 1.49 2012/05/14 13:34:18 roberto Exp $ -** Opcodes for Lua virtual machine -** See Copyright Notice in lua.h -*/ - - -#define lopcodes_c -#define LUA_CORE - - -#include "lopcodes.h" - - -/* ORDER OP */ - -LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { - "MOVE", - "LOADK", - "LOADKX", - "LOADBOOL", - "LOADNIL", - "GETUPVAL", - "GETTABUP", - "GETTABLE", - "SETTABUP", - "SETUPVAL", - "SETTABLE", - "NEWTABLE", - "SELF", - "ADD", - "SUB", - "MUL", - "DIV", - "MOD", - "POW", - "UNM", - "NOT", - "LEN", - "CONCAT", - "JMP", - "EQ", - "LT", - "LE", - "TEST", - "TESTSET", - "CALL", - "TAILCALL", - "RETURN", - "FORLOOP", - "FORPREP", - "TFORCALL", - "TFORLOOP", - "SETLIST", - "CLOSURE", - "VARARG", - "EXTRAARG", - NULL -}; - - -#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) - -LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { -/* T A B C mode opcode */ - opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ - ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ - ,opmode(0, 1, OpArgN, OpArgN, iABx) /* OP_LOADKX */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ - ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_LOADNIL */ - ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ - ,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */ - ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ - ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABUP */ - ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ - ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ - ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ - ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ - ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ - ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ - ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ - ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ - ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TEST */ - ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ - ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ - ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ - ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ - ,opmode(0, 0, OpArgN, OpArgU, iABC) /* OP_TFORCALL */ - ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_TFORLOOP */ - ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ - ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ - ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ - ,opmode(0, 0, OpArgU, OpArgU, iAx) /* OP_EXTRAARG */ -}; - diff --git a/contrib/lua/lua/src/lopcodes.h b/contrib/lua/lua/src/lopcodes.h deleted file mode 100644 index 07d2b3f39aa..00000000000 --- a/contrib/lua/lua/src/lopcodes.h +++ /dev/null @@ -1,288 +0,0 @@ -/* -** $Id: lopcodes.h,v 1.142 2011/07/15 12:50:29 roberto Exp $ -** Opcodes for Lua virtual machine -** See Copyright Notice in lua.h -*/ - -#ifndef lopcodes_h -#define lopcodes_h - -#include "llimits.h" - - -/*=========================================================================== - We assume that instructions are unsigned numbers. - All instructions have an opcode in the first 6 bits. - Instructions can have the following fields: - `A' : 8 bits - `B' : 9 bits - `C' : 9 bits - 'Ax' : 26 bits ('A', 'B', and 'C' together) - `Bx' : 18 bits (`B' and `C' together) - `sBx' : signed Bx - - A signed argument is represented in excess K; that is, the number - value is the unsigned value minus K. K is exactly the maximum value - for that argument (so that -max is represented by 0, and +max is - represented by 2*max), which is half the maximum for the corresponding - unsigned argument. -===========================================================================*/ - - -enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */ - - -/* -** size and position of opcode arguments. -*/ -#define SIZE_C 9 -#define SIZE_B 9 -#define SIZE_Bx (SIZE_C + SIZE_B) -#define SIZE_A 8 -#define SIZE_Ax (SIZE_C + SIZE_B + SIZE_A) - -#define SIZE_OP 6 - -#define POS_OP 0 -#define POS_A (POS_OP + SIZE_OP) -#define POS_C (POS_A + SIZE_A) -#define POS_B (POS_C + SIZE_C) -#define POS_Bx POS_C -#define POS_Ax POS_A - - -/* -** limits for opcode arguments. -** we use (signed) int to manipulate most arguments, -** so they must fit in LUAI_BITSINT-1 bits (-1 for sign) -*/ -#if SIZE_Bx < LUAI_BITSINT-1 -#define MAXARG_Bx ((1<>1) /* `sBx' is signed */ -#else -#define MAXARG_Bx MAX_INT -#define MAXARG_sBx MAX_INT -#endif - -#if SIZE_Ax < LUAI_BITSINT-1 -#define MAXARG_Ax ((1<>POS_OP) & MASK1(SIZE_OP,0))) -#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ - ((cast(Instruction, o)<>pos) & MASK1(size,0))) -#define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \ - ((cast(Instruction, v)<= R(A) + 1 */ -OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ -OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ -OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ - -OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ -OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ - -OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ -OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ -OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ - -OP_FORLOOP,/* A sBx R(A)+=R(A+2); - if R(A) > 4) & 3)) -#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3)) -#define testAMode(m) (luaP_opmodes[m] & (1 << 6)) -#define testTMode(m) (luaP_opmodes[m] & (1 << 7)) - - -LUAI_DDEC const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ - - -/* number of list items to accumulate before a SETLIST instruction */ -#define LFIELDS_PER_FLUSH 50 - - -#endif diff --git a/contrib/lua/lua/src/loslib.c b/contrib/lua/lua/src/loslib.c deleted file mode 100644 index 5170fd0d0fc..00000000000 --- a/contrib/lua/lua/src/loslib.c +++ /dev/null @@ -1,323 +0,0 @@ -/* -** $Id: loslib.c,v 1.40 2012/10/19 15:54:02 roberto Exp $ -** Standard Operating System library -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include -#include -#include - -#define loslib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -/* -** list of valid conversion specifiers for the 'strftime' function -*/ -#if !defined(LUA_STRFTIMEOPTIONS) - -#if !defined(LUA_USE_POSIX) -#define LUA_STRFTIMEOPTIONS { "aAbBcdHIjmMpSUwWxXyYz%", "" } -#else -#define LUA_STRFTIMEOPTIONS \ - { "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "" \ - "", "E", "cCxXyY", \ - "O", "deHImMSuUVwWy" } -#endif - -#endif - - - -/* -** By default, Lua uses tmpnam except when POSIX is available, where it -** uses mkstemp. -*/ -#if defined(LUA_USE_MKSTEMP) -#include -#define LUA_TMPNAMBUFSIZE 32 -#define lua_tmpnam(b,e) { \ - strcpy(b, "/tmp/lua_XXXXXX"); \ - e = mkstemp(b); \ - if (e != -1) close(e); \ - e = (e == -1); } - -#elif !defined(lua_tmpnam) - -#define LUA_TMPNAMBUFSIZE L_tmpnam -#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } - -#endif - - -/* -** By default, Lua uses gmtime/localtime, except when POSIX is available, -** where it uses gmtime_r/localtime_r -*/ -#if defined(LUA_USE_GMTIME_R) - -#define l_gmtime(t,r) gmtime_r(t,r) -#define l_localtime(t,r) localtime_r(t,r) - -#elif !defined(l_gmtime) - -#define l_gmtime(t,r) ((void)r, gmtime(t)) -#define l_localtime(t,r) ((void)r, localtime(t)) - -#endif - - - -static int os_execute (lua_State *L) { - const char *cmd = luaL_optstring(L, 1, NULL); - int stat = system(cmd); - if (cmd != NULL) - return luaL_execresult(L, stat); - else { - lua_pushboolean(L, stat); /* true if there is a shell */ - return 1; - } -} - - -static int os_remove (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - return luaL_fileresult(L, remove(filename) == 0, filename); -} - - -static int os_rename (lua_State *L) { - const char *fromname = luaL_checkstring(L, 1); - const char *toname = luaL_checkstring(L, 2); - return luaL_fileresult(L, rename(fromname, toname) == 0, NULL); -} - - -static int os_tmpname (lua_State *L) { - char buff[LUA_TMPNAMBUFSIZE]; - int err; - lua_tmpnam(buff, err); - if (err) - return luaL_error(L, "unable to generate a unique filename"); - lua_pushstring(L, buff); - return 1; -} - - -static int os_getenv (lua_State *L) { - lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ - return 1; -} - - -static int os_clock (lua_State *L) { - lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); - return 1; -} - - -/* -** {====================================================== -** Time/Date operations -** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, -** wday=%w+1, yday=%j, isdst=? } -** ======================================================= -*/ - -static void setfield (lua_State *L, const char *key, int value) { - lua_pushinteger(L, value); - lua_setfield(L, -2, key); -} - -static void setboolfield (lua_State *L, const char *key, int value) { - if (value < 0) /* undefined? */ - return; /* does not set field */ - lua_pushboolean(L, value); - lua_setfield(L, -2, key); -} - -static int getboolfield (lua_State *L, const char *key) { - int res; - lua_getfield(L, -1, key); - res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1); - lua_pop(L, 1); - return res; -} - - -static int getfield (lua_State *L, const char *key, int d) { - int res, isnum; - lua_getfield(L, -1, key); - res = (int)lua_tointegerx(L, -1, &isnum); - if (!isnum) { - if (d < 0) - return luaL_error(L, "field " LUA_QS " missing in date table", key); - res = d; - } - lua_pop(L, 1); - return res; -} - - -static const char *checkoption (lua_State *L, const char *conv, char *buff) { - static const char *const options[] = LUA_STRFTIMEOPTIONS; - unsigned int i; - for (i = 0; i < sizeof(options)/sizeof(options[0]); i += 2) { - if (*conv != '\0' && strchr(options[i], *conv) != NULL) { - buff[1] = *conv; - if (*options[i + 1] == '\0') { /* one-char conversion specifier? */ - buff[2] = '\0'; /* end buffer */ - return conv + 1; - } - else if (*(conv + 1) != '\0' && - strchr(options[i + 1], *(conv + 1)) != NULL) { - buff[2] = *(conv + 1); /* valid two-char conversion specifier */ - buff[3] = '\0'; /* end buffer */ - return conv + 2; - } - } - } - luaL_argerror(L, 1, - lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv)); - return conv; /* to avoid warnings */ -} - - -static int os_date (lua_State *L) { - const char *s = luaL_optstring(L, 1, "%c"); - time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL)); - struct tm tmr, *stm; - if (*s == '!') { /* UTC? */ - stm = l_gmtime(&t, &tmr); - s++; /* skip `!' */ - } - else - stm = l_localtime(&t, &tmr); - if (stm == NULL) /* invalid date? */ - lua_pushnil(L); - else if (strcmp(s, "*t") == 0) { - lua_createtable(L, 0, 9); /* 9 = number of fields */ - setfield(L, "sec", stm->tm_sec); - setfield(L, "min", stm->tm_min); - setfield(L, "hour", stm->tm_hour); - setfield(L, "day", stm->tm_mday); - setfield(L, "month", stm->tm_mon+1); - setfield(L, "year", stm->tm_year+1900); - setfield(L, "wday", stm->tm_wday+1); - setfield(L, "yday", stm->tm_yday+1); - setboolfield(L, "isdst", stm->tm_isdst); - } - else { - char cc[4]; - luaL_Buffer b; - cc[0] = '%'; - luaL_buffinit(L, &b); - while (*s) { - if (*s != '%') /* no conversion specifier? */ - luaL_addchar(&b, *s++); - else { - size_t reslen; - char buff[200]; /* should be big enough for any conversion result */ - s = checkoption(L, s + 1, cc); - reslen = strftime(buff, sizeof(buff), cc, stm); - luaL_addlstring(&b, buff, reslen); - } - } - luaL_pushresult(&b); - } - return 1; -} - - -static int os_time (lua_State *L) { - time_t t; - if (lua_isnoneornil(L, 1)) /* called without args? */ - t = time(NULL); /* get current time */ - else { - struct tm ts; - luaL_checktype(L, 1, LUA_TTABLE); - lua_settop(L, 1); /* make sure table is at the top */ - ts.tm_sec = getfield(L, "sec", 0); - ts.tm_min = getfield(L, "min", 0); - ts.tm_hour = getfield(L, "hour", 12); - ts.tm_mday = getfield(L, "day", -1); - ts.tm_mon = getfield(L, "month", -1) - 1; - ts.tm_year = getfield(L, "year", -1) - 1900; - ts.tm_isdst = getboolfield(L, "isdst"); - t = mktime(&ts); - } - if (t == (time_t)(-1)) - lua_pushnil(L); - else - lua_pushnumber(L, (lua_Number)t); - return 1; -} - - -static int os_difftime (lua_State *L) { - lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), - (time_t)(luaL_optnumber(L, 2, 0)))); - return 1; -} - -/* }====================================================== */ - - -static int os_setlocale (lua_State *L) { - static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, - LC_NUMERIC, LC_TIME}; - static const char *const catnames[] = {"all", "collate", "ctype", "monetary", - "numeric", "time", NULL}; - const char *l = luaL_optstring(L, 1, NULL); - int op = luaL_checkoption(L, 2, "all", catnames); - lua_pushstring(L, setlocale(cat[op], l)); - return 1; -} - - -static int os_exit (lua_State *L) { - int status; - if (lua_isboolean(L, 1)) - status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE); - else - status = luaL_optint(L, 1, EXIT_SUCCESS); - if (lua_toboolean(L, 2)) - lua_close(L); - if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */ - return 0; -} - - -static const luaL_Reg syslib[] = { - {"clock", os_clock}, - {"date", os_date}, - {"difftime", os_difftime}, - {"execute", os_execute}, - {"exit", os_exit}, - {"getenv", os_getenv}, - {"remove", os_remove}, - {"rename", os_rename}, - {"setlocale", os_setlocale}, - {"time", os_time}, - {"tmpname", os_tmpname}, - {NULL, NULL} -}; - -/* }====================================================== */ - - - -LUAMOD_API int luaopen_os (lua_State *L) { - luaL_newlib(L, syslib); - return 1; -} - diff --git a/contrib/lua/lua/src/lparser.c b/contrib/lua/lua/src/lparser.c deleted file mode 100644 index d8f5b4ffc5f..00000000000 --- a/contrib/lua/lua/src/lparser.c +++ /dev/null @@ -1,1638 +0,0 @@ -/* -** $Id: lparser.c,v 2.130 2013/02/06 13:37:39 roberto Exp $ -** Lua Parser -** See Copyright Notice in lua.h -*/ - - -#include - -#define lparser_c -#define LUA_CORE - -#include "lua.h" - -#include "lcode.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "llex.h" -#include "lmem.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" - - - -/* maximum number of local variables per function (must be smaller - than 250, due to the bytecode format) */ -#define MAXVARS 200 - - -#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) - - - -/* -** nodes for block list (list of active blocks) -*/ -typedef struct BlockCnt { - struct BlockCnt *previous; /* chain */ - short firstlabel; /* index of first label in this block */ - short firstgoto; /* index of first pending goto in this block */ - lu_byte nactvar; /* # active locals outside the block */ - lu_byte upval; /* true if some variable in the block is an upvalue */ - lu_byte isloop; /* true if `block' is a loop */ -} BlockCnt; - - - -/* -** prototypes for recursive non-terminal functions -*/ -static void statement (LexState *ls); -static void expr (LexState *ls, expdesc *v); - - -static void anchor_token (LexState *ls) { - /* last token from outer function must be EOS */ - lua_assert(ls->fs != NULL || ls->t.token == TK_EOS); - if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { - TString *ts = ls->t.seminfo.ts; - luaX_newstring(ls, getstr(ts), ts->tsv.len); - } -} - - -/* semantic error */ -static l_noret semerror (LexState *ls, const char *msg) { - ls->t.token = 0; /* remove 'near to' from final message */ - luaX_syntaxerror(ls, msg); -} - - -static l_noret error_expected (LexState *ls, int token) { - luaX_syntaxerror(ls, - luaO_pushfstring(ls->L, "%s expected", luaX_token2str(ls, token))); -} - - -static l_noret errorlimit (FuncState *fs, int limit, const char *what) { - lua_State *L = fs->ls->L; - const char *msg; - int line = fs->f->linedefined; - const char *where = (line == 0) - ? "main function" - : luaO_pushfstring(L, "function at line %d", line); - msg = luaO_pushfstring(L, "too many %s (limit is %d) in %s", - what, limit, where); - luaX_syntaxerror(fs->ls, msg); -} - - -static void checklimit (FuncState *fs, int v, int l, const char *what) { - if (v > l) errorlimit(fs, l, what); -} - - -static int testnext (LexState *ls, int c) { - if (ls->t.token == c) { - luaX_next(ls); - return 1; - } - else return 0; -} - - -static void check (LexState *ls, int c) { - if (ls->t.token != c) - error_expected(ls, c); -} - - -static void checknext (LexState *ls, int c) { - check(ls, c); - luaX_next(ls); -} - - -#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } - - - -static void check_match (LexState *ls, int what, int who, int where) { - if (!testnext(ls, what)) { - if (where == ls->linenumber) - error_expected(ls, what); - else { - luaX_syntaxerror(ls, luaO_pushfstring(ls->L, - "%s expected (to close %s at line %d)", - luaX_token2str(ls, what), luaX_token2str(ls, who), where)); - } - } -} - - -static TString *str_checkname (LexState *ls) { - TString *ts; - check(ls, TK_NAME); - ts = ls->t.seminfo.ts; - luaX_next(ls); - return ts; -} - - -static void init_exp (expdesc *e, expkind k, int i) { - e->f = e->t = NO_JUMP; - e->k = k; - e->u.info = i; -} - - -static void codestring (LexState *ls, expdesc *e, TString *s) { - init_exp(e, VK, luaK_stringK(ls->fs, s)); -} - - -static void checkname (LexState *ls, expdesc *e) { - codestring(ls, e, str_checkname(ls)); -} - - -static int registerlocalvar (LexState *ls, TString *varname) { - FuncState *fs = ls->fs; - Proto *f = fs->f; - int oldsize = f->sizelocvars; - luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, - LocVar, SHRT_MAX, "local variables"); - while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; - f->locvars[fs->nlocvars].varname = varname; - luaC_objbarrier(ls->L, f, varname); - return fs->nlocvars++; -} - - -static void new_localvar (LexState *ls, TString *name) { - FuncState *fs = ls->fs; - Dyndata *dyd = ls->dyd; - int reg = registerlocalvar(ls, name); - checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, - MAXVARS, "local variables"); - luaM_growvector(ls->L, dyd->actvar.arr, dyd->actvar.n + 1, - dyd->actvar.size, Vardesc, MAX_INT, "local variables"); - dyd->actvar.arr[dyd->actvar.n++].idx = cast(short, reg); -} - - -static void new_localvarliteral_ (LexState *ls, const char *name, size_t sz) { - new_localvar(ls, luaX_newstring(ls, name, sz)); -} - -#define new_localvarliteral(ls,v) \ - new_localvarliteral_(ls, "" v, (sizeof(v)/sizeof(char))-1) - - -static LocVar *getlocvar (FuncState *fs, int i) { - int idx = fs->ls->dyd->actvar.arr[fs->firstlocal + i].idx; - lua_assert(idx < fs->nlocvars); - return &fs->f->locvars[idx]; -} - - -static void adjustlocalvars (LexState *ls, int nvars) { - FuncState *fs = ls->fs; - fs->nactvar = cast_byte(fs->nactvar + nvars); - for (; nvars; nvars--) { - getlocvar(fs, fs->nactvar - nvars)->startpc = fs->pc; - } -} - - -static void removevars (FuncState *fs, int tolevel) { - fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel); - while (fs->nactvar > tolevel) - getlocvar(fs, --fs->nactvar)->endpc = fs->pc; -} - - -static int searchupvalue (FuncState *fs, TString *name) { - int i; - Upvaldesc *up = fs->f->upvalues; - for (i = 0; i < fs->nups; i++) { - if (luaS_eqstr(up[i].name, name)) return i; - } - return -1; /* not found */ -} - - -static int newupvalue (FuncState *fs, TString *name, expdesc *v) { - Proto *f = fs->f; - int oldsize = f->sizeupvalues; - checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues"); - luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues, - Upvaldesc, MAXUPVAL, "upvalues"); - while (oldsize < f->sizeupvalues) f->upvalues[oldsize++].name = NULL; - f->upvalues[fs->nups].instack = (v->k == VLOCAL); - f->upvalues[fs->nups].idx = cast_byte(v->u.info); - f->upvalues[fs->nups].name = name; - luaC_objbarrier(fs->ls->L, f, name); - return fs->nups++; -} - - -static int searchvar (FuncState *fs, TString *n) { - int i; - for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { - if (luaS_eqstr(n, getlocvar(fs, i)->varname)) - return i; - } - return -1; /* not found */ -} - - -/* - Mark block where variable at given level was defined - (to emit close instructions later). -*/ -static void markupval (FuncState *fs, int level) { - BlockCnt *bl = fs->bl; - while (bl->nactvar > level) bl = bl->previous; - bl->upval = 1; -} - - -/* - Find variable with given name 'n'. If it is an upvalue, add this - upvalue into all intermediate functions. -*/ -static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { - if (fs == NULL) /* no more levels? */ - return VVOID; /* default is global */ - else { - int v = searchvar(fs, n); /* look up locals at current level */ - if (v >= 0) { /* found? */ - init_exp(var, VLOCAL, v); /* variable is local */ - if (!base) - markupval(fs, v); /* local will be used as an upval */ - return VLOCAL; - } - else { /* not found as local at current level; try upvalues */ - int idx = searchupvalue(fs, n); /* try existing upvalues */ - if (idx < 0) { /* not found? */ - if (singlevaraux(fs->prev, n, var, 0) == VVOID) /* try upper levels */ - return VVOID; /* not found; is a global */ - /* else was LOCAL or UPVAL */ - idx = newupvalue(fs, n, var); /* will be a new upvalue */ - } - init_exp(var, VUPVAL, idx); - return VUPVAL; - } - } -} - - -static void singlevar (LexState *ls, expdesc *var) { - TString *varname = str_checkname(ls); - FuncState *fs = ls->fs; - if (singlevaraux(fs, varname, var, 1) == VVOID) { /* global name? */ - expdesc key; - singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ - lua_assert(var->k == VLOCAL || var->k == VUPVAL); - codestring(ls, &key, varname); /* key is variable name */ - luaK_indexed(fs, var, &key); /* env[varname] */ - } -} - - -static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { - FuncState *fs = ls->fs; - int extra = nvars - nexps; - if (hasmultret(e->k)) { - extra++; /* includes call itself */ - if (extra < 0) extra = 0; - luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ - if (extra > 1) luaK_reserveregs(fs, extra-1); - } - else { - if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ - if (extra > 0) { - int reg = fs->freereg; - luaK_reserveregs(fs, extra); - luaK_nil(fs, reg, extra); - } - } -} - - -static void enterlevel (LexState *ls) { - lua_State *L = ls->L; - ++L->nCcalls; - checklimit(ls->fs, L->nCcalls, LUAI_MAXCCALLS, "C levels"); -} - - -#define leavelevel(ls) ((ls)->L->nCcalls--) - - -static void closegoto (LexState *ls, int g, Labeldesc *label) { - int i; - FuncState *fs = ls->fs; - Labellist *gl = &ls->dyd->gt; - Labeldesc *gt = &gl->arr[g]; - lua_assert(luaS_eqstr(gt->name, label->name)); - if (gt->nactvar < label->nactvar) { - TString *vname = getlocvar(fs, gt->nactvar)->varname; - const char *msg = luaO_pushfstring(ls->L, - " at line %d jumps into the scope of local " LUA_QS, - getstr(gt->name), gt->line, getstr(vname)); - semerror(ls, msg); - } - luaK_patchlist(fs, gt->pc, label->pc); - /* remove goto from pending list */ - for (i = g; i < gl->n - 1; i++) - gl->arr[i] = gl->arr[i + 1]; - gl->n--; -} - - -/* -** try to close a goto with existing labels; this solves backward jumps -*/ -static int findlabel (LexState *ls, int g) { - int i; - BlockCnt *bl = ls->fs->bl; - Dyndata *dyd = ls->dyd; - Labeldesc *gt = &dyd->gt.arr[g]; - /* check labels in current block for a match */ - for (i = bl->firstlabel; i < dyd->label.n; i++) { - Labeldesc *lb = &dyd->label.arr[i]; - if (luaS_eqstr(lb->name, gt->name)) { /* correct label? */ - if (gt->nactvar > lb->nactvar && - (bl->upval || dyd->label.n > bl->firstlabel)) - luaK_patchclose(ls->fs, gt->pc, lb->nactvar); - closegoto(ls, g, lb); /* close it */ - return 1; - } - } - return 0; /* label not found; cannot close goto */ -} - - -static int newlabelentry (LexState *ls, Labellist *l, TString *name, - int line, int pc) { - int n = l->n; - luaM_growvector(ls->L, l->arr, n, l->size, - Labeldesc, SHRT_MAX, "labels/gotos"); - l->arr[n].name = name; - l->arr[n].line = line; - l->arr[n].nactvar = ls->fs->nactvar; - l->arr[n].pc = pc; - l->n++; - return n; -} - - -/* -** check whether new label 'lb' matches any pending gotos in current -** block; solves forward jumps -*/ -static void findgotos (LexState *ls, Labeldesc *lb) { - Labellist *gl = &ls->dyd->gt; - int i = ls->fs->bl->firstgoto; - while (i < gl->n) { - if (luaS_eqstr(gl->arr[i].name, lb->name)) - closegoto(ls, i, lb); - else - i++; - } -} - - -/* -** "export" pending gotos to outer level, to check them against -** outer labels; if the block being exited has upvalues, and -** the goto exits the scope of any variable (which can be the -** upvalue), close those variables being exited. -*/ -static void movegotosout (FuncState *fs, BlockCnt *bl) { - int i = bl->firstgoto; - Labellist *gl = &fs->ls->dyd->gt; - /* correct pending gotos to current block and try to close it - with visible labels */ - while (i < gl->n) { - Labeldesc *gt = &gl->arr[i]; - if (gt->nactvar > bl->nactvar) { - if (bl->upval) - luaK_patchclose(fs, gt->pc, bl->nactvar); - gt->nactvar = bl->nactvar; - } - if (!findlabel(fs->ls, i)) - i++; /* move to next one */ - } -} - - -static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { - bl->isloop = isloop; - bl->nactvar = fs->nactvar; - bl->firstlabel = fs->ls->dyd->label.n; - bl->firstgoto = fs->ls->dyd->gt.n; - bl->upval = 0; - bl->previous = fs->bl; - fs->bl = bl; - lua_assert(fs->freereg == fs->nactvar); -} - - -/* -** create a label named "break" to resolve break statements -*/ -static void breaklabel (LexState *ls) { - TString *n = luaS_new(ls->L, "break"); - int l = newlabelentry(ls, &ls->dyd->label, n, 0, ls->fs->pc); - findgotos(ls, &ls->dyd->label.arr[l]); -} - -/* -** generates an error for an undefined 'goto'; choose appropriate -** message when label name is a reserved word (which can only be 'break') -*/ -static l_noret undefgoto (LexState *ls, Labeldesc *gt) { - const char *msg = isreserved(gt->name) - ? "<%s> at line %d not inside a loop" - : "no visible label " LUA_QS " for at line %d"; - msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line); - semerror(ls, msg); -} - - -static void leaveblock (FuncState *fs) { - BlockCnt *bl = fs->bl; - LexState *ls = fs->ls; - if (bl->previous && bl->upval) { - /* create a 'jump to here' to close upvalues */ - int j = luaK_jump(fs); - luaK_patchclose(fs, j, bl->nactvar); - luaK_patchtohere(fs, j); - } - if (bl->isloop) - breaklabel(ls); /* close pending breaks */ - fs->bl = bl->previous; - removevars(fs, bl->nactvar); - lua_assert(bl->nactvar == fs->nactvar); - fs->freereg = fs->nactvar; /* free registers */ - ls->dyd->label.n = bl->firstlabel; /* remove local labels */ - if (bl->previous) /* inner block? */ - movegotosout(fs, bl); /* update pending gotos to outer block */ - else if (bl->firstgoto < ls->dyd->gt.n) /* pending gotos in outer block? */ - undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]); /* error */ -} - - -/* -** adds a new prototype into list of prototypes -*/ -static Proto *addprototype (LexState *ls) { - Proto *clp; - lua_State *L = ls->L; - FuncState *fs = ls->fs; - Proto *f = fs->f; /* prototype of current function */ - if (fs->np >= f->sizep) { - int oldsize = f->sizep; - luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions"); - while (oldsize < f->sizep) f->p[oldsize++] = NULL; - } - f->p[fs->np++] = clp = luaF_newproto(L); - luaC_objbarrier(L, f, clp); - return clp; -} - - -/* -** codes instruction to create new closure in parent function. -** The OP_CLOSURE instruction must use the last available register, -** so that, if it invokes the GC, the GC knows which registers -** are in use at that time. -*/ -static void codeclosure (LexState *ls, expdesc *v) { - FuncState *fs = ls->fs->prev; - init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1)); - luaK_exp2nextreg(fs, v); /* fix it at the last register */ -} - - -static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { - lua_State *L = ls->L; - Proto *f; - fs->prev = ls->fs; /* linked list of funcstates */ - fs->ls = ls; - ls->fs = fs; - fs->pc = 0; - fs->lasttarget = 0; - fs->jpc = NO_JUMP; - fs->freereg = 0; - fs->nk = 0; - fs->np = 0; - fs->nups = 0; - fs->nlocvars = 0; - fs->nactvar = 0; - fs->firstlocal = ls->dyd->actvar.n; - fs->bl = NULL; - f = fs->f; - f->source = ls->source; - f->maxstacksize = 2; /* registers 0/1 are always valid */ - fs->h = luaH_new(L); - /* anchor table of constants (to avoid being collected) */ - sethvalue2s(L, L->top, fs->h); - incr_top(L); - enterblock(fs, bl, 0); -} - - -static void close_func (LexState *ls) { - lua_State *L = ls->L; - FuncState *fs = ls->fs; - Proto *f = fs->f; - luaK_ret(fs, 0, 0); /* final return */ - leaveblock(fs); - luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); - f->sizecode = fs->pc; - luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); - f->sizelineinfo = fs->pc; - luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue); - f->sizek = fs->nk; - luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *); - f->sizep = fs->np; - luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); - f->sizelocvars = fs->nlocvars; - luaM_reallocvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); - f->sizeupvalues = fs->nups; - lua_assert(fs->bl == NULL); - ls->fs = fs->prev; - /* last token read was anchored in defunct function; must re-anchor it */ - anchor_token(ls); - L->top--; /* pop table of constants */ - luaC_checkGC(L); -} - - - -/*============================================================*/ -/* GRAMMAR RULES */ -/*============================================================*/ - - -/* -** check whether current token is in the follow set of a block. -** 'until' closes syntactical blocks, but do not close scope, -** so it handled in separate. -*/ -static int block_follow (LexState *ls, int withuntil) { - switch (ls->t.token) { - case TK_ELSE: case TK_ELSEIF: - case TK_END: case TK_EOS: - return 1; - case TK_UNTIL: return withuntil; - default: return 0; - } -} - - -static void statlist (LexState *ls) { - /* statlist -> { stat [`;'] } */ - while (!block_follow(ls, 1)) { - if (ls->t.token == TK_RETURN) { - statement(ls); - return; /* 'return' must be last statement */ - } - statement(ls); - } -} - - -static void fieldsel (LexState *ls, expdesc *v) { - /* fieldsel -> ['.' | ':'] NAME */ - FuncState *fs = ls->fs; - expdesc key; - luaK_exp2anyregup(fs, v); - luaX_next(ls); /* skip the dot or colon */ - checkname(ls, &key); - luaK_indexed(fs, v, &key); -} - - -static void yindex (LexState *ls, expdesc *v) { - /* index -> '[' expr ']' */ - luaX_next(ls); /* skip the '[' */ - expr(ls, v); - luaK_exp2val(ls->fs, v); - checknext(ls, ']'); -} - - -/* -** {====================================================================== -** Rules for Constructors -** ======================================================================= -*/ - - -struct ConsControl { - expdesc v; /* last list item read */ - expdesc *t; /* table descriptor */ - int nh; /* total number of `record' elements */ - int na; /* total number of array elements */ - int tostore; /* number of array elements pending to be stored */ -}; - - -static void recfield (LexState *ls, struct ConsControl *cc) { - /* recfield -> (NAME | `['exp1`]') = exp1 */ - FuncState *fs = ls->fs; - int reg = ls->fs->freereg; - expdesc key, val; - int rkkey; - if (ls->t.token == TK_NAME) { - checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); - checkname(ls, &key); - } - else /* ls->t.token == '[' */ - yindex(ls, &key); - cc->nh++; - checknext(ls, '='); - rkkey = luaK_exp2RK(fs, &key); - expr(ls, &val); - luaK_codeABC(fs, OP_SETTABLE, cc->t->u.info, rkkey, luaK_exp2RK(fs, &val)); - fs->freereg = reg; /* free registers */ -} - - -static void closelistfield (FuncState *fs, struct ConsControl *cc) { - if (cc->v.k == VVOID) return; /* there is no list item */ - luaK_exp2nextreg(fs, &cc->v); - cc->v.k = VVOID; - if (cc->tostore == LFIELDS_PER_FLUSH) { - luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); /* flush */ - cc->tostore = 0; /* no more items pending */ - } -} - - -static void lastlistfield (FuncState *fs, struct ConsControl *cc) { - if (cc->tostore == 0) return; - if (hasmultret(cc->v.k)) { - luaK_setmultret(fs, &cc->v); - luaK_setlist(fs, cc->t->u.info, cc->na, LUA_MULTRET); - cc->na--; /* do not count last expression (unknown number of elements) */ - } - else { - if (cc->v.k != VVOID) - luaK_exp2nextreg(fs, &cc->v); - luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); - } -} - - -static void listfield (LexState *ls, struct ConsControl *cc) { - /* listfield -> exp */ - expr(ls, &cc->v); - checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); - cc->na++; - cc->tostore++; -} - - -static void field (LexState *ls, struct ConsControl *cc) { - /* field -> listfield | recfield */ - switch(ls->t.token) { - case TK_NAME: { /* may be 'listfield' or 'recfield' */ - if (luaX_lookahead(ls) != '=') /* expression? */ - listfield(ls, cc); - else - recfield(ls, cc); - break; - } - case '[': { - recfield(ls, cc); - break; - } - default: { - listfield(ls, cc); - break; - } - } -} - - -static void constructor (LexState *ls, expdesc *t) { - /* constructor -> '{' [ field { sep field } [sep] ] '}' - sep -> ',' | ';' */ - FuncState *fs = ls->fs; - int line = ls->linenumber; - int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); - struct ConsControl cc; - cc.na = cc.nh = cc.tostore = 0; - cc.t = t; - init_exp(t, VRELOCABLE, pc); - init_exp(&cc.v, VVOID, 0); /* no value (yet) */ - luaK_exp2nextreg(ls->fs, t); /* fix it at stack top */ - checknext(ls, '{'); - do { - lua_assert(cc.v.k == VVOID || cc.tostore > 0); - if (ls->t.token == '}') break; - closelistfield(fs, &cc); - field(ls, &cc); - } while (testnext(ls, ',') || testnext(ls, ';')); - check_match(ls, '}', '{', line); - lastlistfield(fs, &cc); - SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ - SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ -} - -/* }====================================================================== */ - - - -static void parlist (LexState *ls) { - /* parlist -> [ param { `,' param } ] */ - FuncState *fs = ls->fs; - Proto *f = fs->f; - int nparams = 0; - f->is_vararg = 0; - if (ls->t.token != ')') { /* is `parlist' not empty? */ - do { - switch (ls->t.token) { - case TK_NAME: { /* param -> NAME */ - new_localvar(ls, str_checkname(ls)); - nparams++; - break; - } - case TK_DOTS: { /* param -> `...' */ - luaX_next(ls); - f->is_vararg = 1; - break; - } - default: luaX_syntaxerror(ls, " or " LUA_QL("...") " expected"); - } - } while (!f->is_vararg && testnext(ls, ',')); - } - adjustlocalvars(ls, nparams); - f->numparams = cast_byte(fs->nactvar); - luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ -} - - -static void body (LexState *ls, expdesc *e, int ismethod, int line) { - /* body -> `(' parlist `)' block END */ - FuncState new_fs; - BlockCnt bl; - new_fs.f = addprototype(ls); - new_fs.f->linedefined = line; - open_func(ls, &new_fs, &bl); - checknext(ls, '('); - if (ismethod) { - new_localvarliteral(ls, "self"); /* create 'self' parameter */ - adjustlocalvars(ls, 1); - } - parlist(ls); - checknext(ls, ')'); - statlist(ls); - new_fs.f->lastlinedefined = ls->linenumber; - check_match(ls, TK_END, TK_FUNCTION, line); - codeclosure(ls, e); - close_func(ls); -} - - -static int explist (LexState *ls, expdesc *v) { - /* explist -> expr { `,' expr } */ - int n = 1; /* at least one expression */ - expr(ls, v); - while (testnext(ls, ',')) { - luaK_exp2nextreg(ls->fs, v); - expr(ls, v); - n++; - } - return n; -} - - -static void funcargs (LexState *ls, expdesc *f, int line) { - FuncState *fs = ls->fs; - expdesc args; - int base, nparams; - switch (ls->t.token) { - case '(': { /* funcargs -> `(' [ explist ] `)' */ - luaX_next(ls); - if (ls->t.token == ')') /* arg list is empty? */ - args.k = VVOID; - else { - explist(ls, &args); - luaK_setmultret(fs, &args); - } - check_match(ls, ')', '(', line); - break; - } - case '{': { /* funcargs -> constructor */ - constructor(ls, &args); - break; - } - case TK_STRING: { /* funcargs -> STRING */ - codestring(ls, &args, ls->t.seminfo.ts); - luaX_next(ls); /* must use `seminfo' before `next' */ - break; - } - default: { - luaX_syntaxerror(ls, "function arguments expected"); - } - } - lua_assert(f->k == VNONRELOC); - base = f->u.info; /* base register for call */ - if (hasmultret(args.k)) - nparams = LUA_MULTRET; /* open call */ - else { - if (args.k != VVOID) - luaK_exp2nextreg(fs, &args); /* close last argument */ - nparams = fs->freereg - (base+1); - } - init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); - luaK_fixline(fs, line); - fs->freereg = base+1; /* call remove function and arguments and leaves - (unless changed) one result */ -} - - - - -/* -** {====================================================================== -** Expression parsing -** ======================================================================= -*/ - - -static void primaryexp (LexState *ls, expdesc *v) { - /* primaryexp -> NAME | '(' expr ')' */ - switch (ls->t.token) { - case '(': { - int line = ls->linenumber; - luaX_next(ls); - expr(ls, v); - check_match(ls, ')', '(', line); - luaK_dischargevars(ls->fs, v); - return; - } - case TK_NAME: { - singlevar(ls, v); - return; - } - default: { - luaX_syntaxerror(ls, "unexpected symbol"); - } - } -} - - -static void suffixedexp (LexState *ls, expdesc *v) { - /* suffixedexp -> - primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */ - FuncState *fs = ls->fs; - int line = ls->linenumber; - primaryexp(ls, v); - for (;;) { - switch (ls->t.token) { - case '.': { /* fieldsel */ - fieldsel(ls, v); - break; - } - case '[': { /* `[' exp1 `]' */ - expdesc key; - luaK_exp2anyregup(fs, v); - yindex(ls, &key); - luaK_indexed(fs, v, &key); - break; - } - case ':': { /* `:' NAME funcargs */ - expdesc key; - luaX_next(ls); - checkname(ls, &key); - luaK_self(fs, v, &key); - funcargs(ls, v, line); - break; - } - case '(': case TK_STRING: case '{': { /* funcargs */ - luaK_exp2nextreg(fs, v); - funcargs(ls, v, line); - break; - } - default: return; - } - } -} - - -static void simpleexp (LexState *ls, expdesc *v) { - /* simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... | - constructor | FUNCTION body | suffixedexp */ - switch (ls->t.token) { - case TK_NUMBER: { - init_exp(v, VKNUM, 0); - v->u.nval = ls->t.seminfo.r; - break; - } - case TK_STRING: { - codestring(ls, v, ls->t.seminfo.ts); - break; - } - case TK_NIL: { - init_exp(v, VNIL, 0); - break; - } - case TK_TRUE: { - init_exp(v, VTRUE, 0); - break; - } - case TK_FALSE: { - init_exp(v, VFALSE, 0); - break; - } - case TK_DOTS: { /* vararg */ - FuncState *fs = ls->fs; - check_condition(ls, fs->f->is_vararg, - "cannot use " LUA_QL("...") " outside a vararg function"); - init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); - break; - } - case '{': { /* constructor */ - constructor(ls, v); - return; - } - case TK_FUNCTION: { - luaX_next(ls); - body(ls, v, 0, ls->linenumber); - return; - } - default: { - suffixedexp(ls, v); - return; - } - } - luaX_next(ls); -} - - -static UnOpr getunopr (int op) { - switch (op) { - case TK_NOT: return OPR_NOT; - case '-': return OPR_MINUS; - case '#': return OPR_LEN; - default: return OPR_NOUNOPR; - } -} - - -static BinOpr getbinopr (int op) { - switch (op) { - case '+': return OPR_ADD; - case '-': return OPR_SUB; - case '*': return OPR_MUL; - case '/': return OPR_DIV; - case '%': return OPR_MOD; - case '^': return OPR_POW; - case TK_CONCAT: return OPR_CONCAT; - case TK_NE: return OPR_NE; - case TK_EQ: return OPR_EQ; - case '<': return OPR_LT; - case TK_LE: return OPR_LE; - case '>': return OPR_GT; - case TK_GE: return OPR_GE; - case TK_AND: return OPR_AND; - case TK_OR: return OPR_OR; - default: return OPR_NOBINOPR; - } -} - - -static const struct { - lu_byte left; /* left priority for each binary operator */ - lu_byte right; /* right priority */ -} priority[] = { /* ORDER OPR */ - {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `*' `/' `%' */ - {10, 9}, {5, 4}, /* ^, .. (right associative) */ - {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */ - {3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */ - {2, 2}, {1, 1} /* and, or */ -}; - -#define UNARY_PRIORITY 8 /* priority for unary operators */ - - -/* -** subexpr -> (simpleexp | unop subexpr) { binop subexpr } -** where `binop' is any binary operator with a priority higher than `limit' -*/ -static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { - BinOpr op; - UnOpr uop; - enterlevel(ls); - uop = getunopr(ls->t.token); - if (uop != OPR_NOUNOPR) { - int line = ls->linenumber; - luaX_next(ls); - subexpr(ls, v, UNARY_PRIORITY); - luaK_prefix(ls->fs, uop, v, line); - } - else simpleexp(ls, v); - /* expand while operators have priorities higher than `limit' */ - op = getbinopr(ls->t.token); - while (op != OPR_NOBINOPR && priority[op].left > limit) { - expdesc v2; - BinOpr nextop; - int line = ls->linenumber; - luaX_next(ls); - luaK_infix(ls->fs, op, v); - /* read sub-expression with higher priority */ - nextop = subexpr(ls, &v2, priority[op].right); - luaK_posfix(ls->fs, op, v, &v2, line); - op = nextop; - } - leavelevel(ls); - return op; /* return first untreated operator */ -} - - -static void expr (LexState *ls, expdesc *v) { - subexpr(ls, v, 0); -} - -/* }==================================================================== */ - - - -/* -** {====================================================================== -** Rules for Statements -** ======================================================================= -*/ - - -static void block (LexState *ls) { - /* block -> statlist */ - FuncState *fs = ls->fs; - BlockCnt bl; - enterblock(fs, &bl, 0); - statlist(ls); - leaveblock(fs); -} - - -/* -** structure to chain all variables in the left-hand side of an -** assignment -*/ -struct LHS_assign { - struct LHS_assign *prev; - expdesc v; /* variable (global, local, upvalue, or indexed) */ -}; - - -/* -** check whether, in an assignment to an upvalue/local variable, the -** upvalue/local variable is begin used in a previous assignment to a -** table. If so, save original upvalue/local value in a safe place and -** use this safe copy in the previous assignment. -*/ -static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { - FuncState *fs = ls->fs; - int extra = fs->freereg; /* eventual position to save local variable */ - int conflict = 0; - for (; lh; lh = lh->prev) { /* check all previous assignments */ - if (lh->v.k == VINDEXED) { /* assigning to a table? */ - /* table is the upvalue/local being assigned now? */ - if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) { - conflict = 1; - lh->v.u.ind.vt = VLOCAL; - lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ - } - /* index is the local being assigned? (index cannot be upvalue) */ - if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) { - conflict = 1; - lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ - } - } - } - if (conflict) { - /* copy upvalue/local value to a temporary (in position 'extra') */ - OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; - luaK_codeABC(fs, op, extra, v->u.info, 0); - luaK_reserveregs(fs, 1); - } -} - - -static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { - expdesc e; - check_condition(ls, vkisvar(lh->v.k), "syntax error"); - if (testnext(ls, ',')) { /* assignment -> ',' suffixedexp assignment */ - struct LHS_assign nv; - nv.prev = lh; - suffixedexp(ls, &nv.v); - if (nv.v.k != VINDEXED) - check_conflict(ls, lh, &nv.v); - checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS, - "C levels"); - assignment(ls, &nv, nvars+1); - } - else { /* assignment -> `=' explist */ - int nexps; - checknext(ls, '='); - nexps = explist(ls, &e); - if (nexps != nvars) { - adjust_assign(ls, nvars, nexps, &e); - if (nexps > nvars) - ls->fs->freereg -= nexps - nvars; /* remove extra values */ - } - else { - luaK_setoneret(ls->fs, &e); /* close last expression */ - luaK_storevar(ls->fs, &lh->v, &e); - return; /* avoid default */ - } - } - init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ - luaK_storevar(ls->fs, &lh->v, &e); -} - - -static int cond (LexState *ls) { - /* cond -> exp */ - expdesc v; - expr(ls, &v); /* read condition */ - if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */ - luaK_goiftrue(ls->fs, &v); - return v.f; -} - - -static void gotostat (LexState *ls, int pc) { - int line = ls->linenumber; - TString *label; - int g; - if (testnext(ls, TK_GOTO)) - label = str_checkname(ls); - else { - luaX_next(ls); /* skip break */ - label = luaS_new(ls->L, "break"); - } - g = newlabelentry(ls, &ls->dyd->gt, label, line, pc); - findlabel(ls, g); /* close it if label already defined */ -} - - -/* check for repeated labels on the same block */ -static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) { - int i; - for (i = fs->bl->firstlabel; i < ll->n; i++) { - if (luaS_eqstr(label, ll->arr[i].name)) { - const char *msg = luaO_pushfstring(fs->ls->L, - "label " LUA_QS " already defined on line %d", - getstr(label), ll->arr[i].line); - semerror(fs->ls, msg); - } - } -} - - -/* skip no-op statements */ -static void skipnoopstat (LexState *ls) { - while (ls->t.token == ';' || ls->t.token == TK_DBCOLON) - statement(ls); -} - - -static void labelstat (LexState *ls, TString *label, int line) { - /* label -> '::' NAME '::' */ - FuncState *fs = ls->fs; - Labellist *ll = &ls->dyd->label; - int l; /* index of new label being created */ - checkrepeated(fs, ll, label); /* check for repeated labels */ - checknext(ls, TK_DBCOLON); /* skip double colon */ - /* create new entry for this label */ - l = newlabelentry(ls, ll, label, line, fs->pc); - skipnoopstat(ls); /* skip other no-op statements */ - if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */ - /* assume that locals are already out of scope */ - ll->arr[l].nactvar = fs->bl->nactvar; - } - findgotos(ls, &ll->arr[l]); -} - - -static void whilestat (LexState *ls, int line) { - /* whilestat -> WHILE cond DO block END */ - FuncState *fs = ls->fs; - int whileinit; - int condexit; - BlockCnt bl; - luaX_next(ls); /* skip WHILE */ - whileinit = luaK_getlabel(fs); - condexit = cond(ls); - enterblock(fs, &bl, 1); - checknext(ls, TK_DO); - block(ls); - luaK_jumpto(fs, whileinit); - check_match(ls, TK_END, TK_WHILE, line); - leaveblock(fs); - luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ -} - - -static void repeatstat (LexState *ls, int line) { - /* repeatstat -> REPEAT block UNTIL cond */ - int condexit; - FuncState *fs = ls->fs; - int repeat_init = luaK_getlabel(fs); - BlockCnt bl1, bl2; - enterblock(fs, &bl1, 1); /* loop block */ - enterblock(fs, &bl2, 0); /* scope block */ - luaX_next(ls); /* skip REPEAT */ - statlist(ls); - check_match(ls, TK_UNTIL, TK_REPEAT, line); - condexit = cond(ls); /* read condition (inside scope block) */ - if (bl2.upval) /* upvalues? */ - luaK_patchclose(fs, condexit, bl2.nactvar); - leaveblock(fs); /* finish scope */ - luaK_patchlist(fs, condexit, repeat_init); /* close the loop */ - leaveblock(fs); /* finish loop */ -} - - -static int exp1 (LexState *ls) { - expdesc e; - int reg; - expr(ls, &e); - luaK_exp2nextreg(ls->fs, &e); - lua_assert(e.k == VNONRELOC); - reg = e.u.info; - return reg; -} - - -static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { - /* forbody -> DO block */ - BlockCnt bl; - FuncState *fs = ls->fs; - int prep, endfor; - adjustlocalvars(ls, 3); /* control variables */ - checknext(ls, TK_DO); - prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs); - enterblock(fs, &bl, 0); /* scope for declared variables */ - adjustlocalvars(ls, nvars); - luaK_reserveregs(fs, nvars); - block(ls); - leaveblock(fs); /* end of scope for declared variables */ - luaK_patchtohere(fs, prep); - if (isnum) /* numeric for? */ - endfor = luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP); - else { /* generic for */ - luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars); - luaK_fixline(fs, line); - endfor = luaK_codeAsBx(fs, OP_TFORLOOP, base + 2, NO_JUMP); - } - luaK_patchlist(fs, endfor, prep + 1); - luaK_fixline(fs, line); -} - - -static void fornum (LexState *ls, TString *varname, int line) { - /* fornum -> NAME = exp1,exp1[,exp1] forbody */ - FuncState *fs = ls->fs; - int base = fs->freereg; - new_localvarliteral(ls, "(for index)"); - new_localvarliteral(ls, "(for limit)"); - new_localvarliteral(ls, "(for step)"); - new_localvar(ls, varname); - checknext(ls, '='); - exp1(ls); /* initial value */ - checknext(ls, ','); - exp1(ls); /* limit */ - if (testnext(ls, ',')) - exp1(ls); /* optional step */ - else { /* default step = 1 */ - luaK_codek(fs, fs->freereg, luaK_numberK(fs, 1)); - luaK_reserveregs(fs, 1); - } - forbody(ls, base, line, 1, 1); -} - - -static void forlist (LexState *ls, TString *indexname) { - /* forlist -> NAME {,NAME} IN explist forbody */ - FuncState *fs = ls->fs; - expdesc e; - int nvars = 4; /* gen, state, control, plus at least one declared var */ - int line; - int base = fs->freereg; - /* create control variables */ - new_localvarliteral(ls, "(for generator)"); - new_localvarliteral(ls, "(for state)"); - new_localvarliteral(ls, "(for control)"); - /* create declared variables */ - new_localvar(ls, indexname); - while (testnext(ls, ',')) { - new_localvar(ls, str_checkname(ls)); - nvars++; - } - checknext(ls, TK_IN); - line = ls->linenumber; - adjust_assign(ls, 3, explist(ls, &e), &e); - luaK_checkstack(fs, 3); /* extra space to call generator */ - forbody(ls, base, line, nvars - 3, 0); -} - - -static void forstat (LexState *ls, int line) { - /* forstat -> FOR (fornum | forlist) END */ - FuncState *fs = ls->fs; - TString *varname; - BlockCnt bl; - enterblock(fs, &bl, 1); /* scope for loop and control variables */ - luaX_next(ls); /* skip `for' */ - varname = str_checkname(ls); /* first variable name */ - switch (ls->t.token) { - case '=': fornum(ls, varname, line); break; - case ',': case TK_IN: forlist(ls, varname); break; - default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected"); - } - check_match(ls, TK_END, TK_FOR, line); - leaveblock(fs); /* loop scope (`break' jumps to this point) */ -} - - -static void test_then_block (LexState *ls, int *escapelist) { - /* test_then_block -> [IF | ELSEIF] cond THEN block */ - BlockCnt bl; - FuncState *fs = ls->fs; - expdesc v; - int jf; /* instruction to skip 'then' code (if condition is false) */ - luaX_next(ls); /* skip IF or ELSEIF */ - expr(ls, &v); /* read condition */ - checknext(ls, TK_THEN); - if (ls->t.token == TK_GOTO || ls->t.token == TK_BREAK) { - luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */ - enterblock(fs, &bl, 0); /* must enter block before 'goto' */ - gotostat(ls, v.t); /* handle goto/break */ - skipnoopstat(ls); /* skip other no-op statements */ - if (block_follow(ls, 0)) { /* 'goto' is the entire block? */ - leaveblock(fs); - return; /* and that is it */ - } - else /* must skip over 'then' part if condition is false */ - jf = luaK_jump(fs); - } - else { /* regular case (not goto/break) */ - luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */ - enterblock(fs, &bl, 0); - jf = v.f; - } - statlist(ls); /* `then' part */ - leaveblock(fs); - if (ls->t.token == TK_ELSE || - ls->t.token == TK_ELSEIF) /* followed by 'else'/'elseif'? */ - luaK_concat(fs, escapelist, luaK_jump(fs)); /* must jump over it */ - luaK_patchtohere(fs, jf); -} - - -static void ifstat (LexState *ls, int line) { - /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ - FuncState *fs = ls->fs; - int escapelist = NO_JUMP; /* exit list for finished parts */ - test_then_block(ls, &escapelist); /* IF cond THEN block */ - while (ls->t.token == TK_ELSEIF) - test_then_block(ls, &escapelist); /* ELSEIF cond THEN block */ - if (testnext(ls, TK_ELSE)) - block(ls); /* `else' part */ - check_match(ls, TK_END, TK_IF, line); - luaK_patchtohere(fs, escapelist); /* patch escape list to 'if' end */ -} - - -static void localfunc (LexState *ls) { - expdesc b; - FuncState *fs = ls->fs; - new_localvar(ls, str_checkname(ls)); /* new local variable */ - adjustlocalvars(ls, 1); /* enter its scope */ - body(ls, &b, 0, ls->linenumber); /* function created in next register */ - /* debug information will only see the variable after this point! */ - getlocvar(fs, b.u.info)->startpc = fs->pc; -} - - -static void localstat (LexState *ls) { - /* stat -> LOCAL NAME {`,' NAME} [`=' explist] */ - int nvars = 0; - int nexps; - expdesc e; - do { - new_localvar(ls, str_checkname(ls)); - nvars++; - } while (testnext(ls, ',')); - if (testnext(ls, '=')) - nexps = explist(ls, &e); - else { - e.k = VVOID; - nexps = 0; - } - adjust_assign(ls, nvars, nexps, &e); - adjustlocalvars(ls, nvars); -} - - -static int funcname (LexState *ls, expdesc *v) { - /* funcname -> NAME {fieldsel} [`:' NAME] */ - int ismethod = 0; - singlevar(ls, v); - while (ls->t.token == '.') - fieldsel(ls, v); - if (ls->t.token == ':') { - ismethod = 1; - fieldsel(ls, v); - } - return ismethod; -} - - -static void funcstat (LexState *ls, int line) { - /* funcstat -> FUNCTION funcname body */ - int ismethod; - expdesc v, b; - luaX_next(ls); /* skip FUNCTION */ - ismethod = funcname(ls, &v); - body(ls, &b, ismethod, line); - luaK_storevar(ls->fs, &v, &b); - luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ -} - - -static void exprstat (LexState *ls) { - /* stat -> func | assignment */ - FuncState *fs = ls->fs; - struct LHS_assign v; - suffixedexp(ls, &v.v); - if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */ - v.prev = NULL; - assignment(ls, &v, 1); - } - else { /* stat -> func */ - check_condition(ls, v.v.k == VCALL, "syntax error"); - SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ - } -} - - -static void retstat (LexState *ls) { - /* stat -> RETURN [explist] [';'] */ - FuncState *fs = ls->fs; - expdesc e; - int first, nret; /* registers with returned values */ - if (block_follow(ls, 1) || ls->t.token == ';') - first = nret = 0; /* return no values */ - else { - nret = explist(ls, &e); /* optional return values */ - if (hasmultret(e.k)) { - luaK_setmultret(fs, &e); - if (e.k == VCALL && nret == 1) { /* tail call? */ - SET_OPCODE(getcode(fs,&e), OP_TAILCALL); - lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); - } - first = fs->nactvar; - nret = LUA_MULTRET; /* return all values */ - } - else { - if (nret == 1) /* only one single value? */ - first = luaK_exp2anyreg(fs, &e); - else { - luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ - first = fs->nactvar; /* return all `active' values */ - lua_assert(nret == fs->freereg - first); - } - } - } - luaK_ret(fs, first, nret); - testnext(ls, ';'); /* skip optional semicolon */ -} - - -static void statement (LexState *ls) { - int line = ls->linenumber; /* may be needed for error messages */ - enterlevel(ls); - switch (ls->t.token) { - case ';': { /* stat -> ';' (empty statement) */ - luaX_next(ls); /* skip ';' */ - break; - } - case TK_IF: { /* stat -> ifstat */ - ifstat(ls, line); - break; - } - case TK_WHILE: { /* stat -> whilestat */ - whilestat(ls, line); - break; - } - case TK_DO: { /* stat -> DO block END */ - luaX_next(ls); /* skip DO */ - block(ls); - check_match(ls, TK_END, TK_DO, line); - break; - } - case TK_FOR: { /* stat -> forstat */ - forstat(ls, line); - break; - } - case TK_REPEAT: { /* stat -> repeatstat */ - repeatstat(ls, line); - break; - } - case TK_FUNCTION: { /* stat -> funcstat */ - funcstat(ls, line); - break; - } - case TK_LOCAL: { /* stat -> localstat */ - luaX_next(ls); /* skip LOCAL */ - if (testnext(ls, TK_FUNCTION)) /* local function? */ - localfunc(ls); - else - localstat(ls); - break; - } - case TK_DBCOLON: { /* stat -> label */ - luaX_next(ls); /* skip double colon */ - labelstat(ls, str_checkname(ls), line); - break; - } - case TK_RETURN: { /* stat -> retstat */ - luaX_next(ls); /* skip RETURN */ - retstat(ls); - break; - } - case TK_BREAK: /* stat -> breakstat */ - case TK_GOTO: { /* stat -> 'goto' NAME */ - gotostat(ls, luaK_jump(ls->fs)); - break; - } - default: { /* stat -> func | assignment */ - exprstat(ls); - break; - } - } - lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && - ls->fs->freereg >= ls->fs->nactvar); - ls->fs->freereg = ls->fs->nactvar; /* free registers */ - leavelevel(ls); -} - -/* }====================================================================== */ - - -/* -** compiles the main function, which is a regular vararg function with an -** upvalue named LUA_ENV -*/ -static void mainfunc (LexState *ls, FuncState *fs) { - BlockCnt bl; - expdesc v; - open_func(ls, fs, &bl); - fs->f->is_vararg = 1; /* main function is always vararg */ - init_exp(&v, VLOCAL, 0); /* create and... */ - newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */ - luaX_next(ls); /* read first token */ - statlist(ls); /* parse main body */ - check(ls, TK_EOS); - close_func(ls); -} - - -Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, - Dyndata *dyd, const char *name, int firstchar) { - LexState lexstate; - FuncState funcstate; - Closure *cl = luaF_newLclosure(L, 1); /* create main closure */ - /* anchor closure (to avoid being collected) */ - setclLvalue(L, L->top, cl); - incr_top(L); - funcstate.f = cl->l.p = luaF_newproto(L); - funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ - lexstate.buff = buff; - lexstate.dyd = dyd; - dyd->actvar.n = dyd->gt.n = dyd->label.n = 0; - luaX_setinput(L, &lexstate, z, funcstate.f->source, firstchar); - mainfunc(&lexstate, &funcstate); - lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); - /* all scopes should be correctly finished */ - lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); - return cl; /* it's on the stack too */ -} - diff --git a/contrib/lua/lua/src/lparser.h b/contrib/lua/lua/src/lparser.h deleted file mode 100644 index 301167d4f5c..00000000000 --- a/contrib/lua/lua/src/lparser.h +++ /dev/null @@ -1,119 +0,0 @@ -/* -** $Id: lparser.h,v 1.70 2012/05/08 13:53:33 roberto Exp $ -** Lua Parser -** See Copyright Notice in lua.h -*/ - -#ifndef lparser_h -#define lparser_h - -#include "llimits.h" -#include "lobject.h" -#include "lzio.h" - - -/* -** Expression descriptor -*/ - -typedef enum { - VVOID, /* no value */ - VNIL, - VTRUE, - VFALSE, - VK, /* info = index of constant in `k' */ - VKNUM, /* nval = numerical value */ - VNONRELOC, /* info = result register */ - VLOCAL, /* info = local register */ - VUPVAL, /* info = index of upvalue in 'upvalues' */ - VINDEXED, /* t = table register/upvalue; idx = index R/K */ - VJMP, /* info = instruction pc */ - VRELOCABLE, /* info = instruction pc */ - VCALL, /* info = instruction pc */ - VVARARG /* info = instruction pc */ -} expkind; - - -#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED) -#define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL) - -typedef struct expdesc { - expkind k; - union { - struct { /* for indexed variables (VINDEXED) */ - short idx; /* index (R/K) */ - lu_byte t; /* table (register or upvalue) */ - lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */ - } ind; - int info; /* for generic use */ - lua_Number nval; /* for VKNUM */ - } u; - int t; /* patch list of `exit when true' */ - int f; /* patch list of `exit when false' */ -} expdesc; - - -/* description of active local variable */ -typedef struct Vardesc { - short idx; /* variable index in stack */ -} Vardesc; - - -/* description of pending goto statements and label statements */ -typedef struct Labeldesc { - TString *name; /* label identifier */ - int pc; /* position in code */ - int line; /* line where it appeared */ - lu_byte nactvar; /* local level where it appears in current block */ -} Labeldesc; - - -/* list of labels or gotos */ -typedef struct Labellist { - Labeldesc *arr; /* array */ - int n; /* number of entries in use */ - int size; /* array size */ -} Labellist; - - -/* dynamic structures used by the parser */ -typedef struct Dyndata { - struct { /* list of active local variables */ - Vardesc *arr; - int n; - int size; - } actvar; - Labellist gt; /* list of pending gotos */ - Labellist label; /* list of active labels */ -} Dyndata; - - -/* control of blocks */ -struct BlockCnt; /* defined in lparser.c */ - - -/* state needed to generate code for a given function */ -typedef struct FuncState { - Proto *f; /* current function header */ - Table *h; /* table to find (and reuse) elements in `k' */ - struct FuncState *prev; /* enclosing function */ - struct LexState *ls; /* lexical state */ - struct BlockCnt *bl; /* chain of current blocks */ - int pc; /* next position to code (equivalent to `ncode') */ - int lasttarget; /* 'label' of last 'jump label' */ - int jpc; /* list of pending jumps to `pc' */ - int nk; /* number of elements in `k' */ - int np; /* number of elements in `p' */ - int firstlocal; /* index of first local var (in Dyndata array) */ - short nlocvars; /* number of elements in 'f->locvars' */ - lu_byte nactvar; /* number of active local variables */ - lu_byte nups; /* number of upvalues */ - lu_byte freereg; /* first free register */ -} FuncState; - - -LUAI_FUNC Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, - Dyndata *dyd, const char *name, int firstchar); - - -#endif diff --git a/contrib/lua/lua/src/lstate.c b/contrib/lua/lua/src/lstate.c deleted file mode 100644 index 207a106d5ba..00000000000 --- a/contrib/lua/lua/src/lstate.c +++ /dev/null @@ -1,322 +0,0 @@ -/* -** $Id: lstate.c,v 2.99 2012/10/02 17:40:53 roberto Exp $ -** Global State -** See Copyright Notice in lua.h -*/ - - -#include -#include - -#define lstate_c -#define LUA_CORE - -#include "lua.h" - -#include "lapi.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "llex.h" -#include "lmem.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" - - -#if !defined(LUAI_GCPAUSE) -#define LUAI_GCPAUSE 200 /* 200% */ -#endif - -#if !defined(LUAI_GCMAJOR) -#define LUAI_GCMAJOR 200 /* 200% */ -#endif - -#if !defined(LUAI_GCMUL) -#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ -#endif - - -#define MEMERRMSG "not enough memory" - - -/* -** a macro to help the creation of a unique random seed when a state is -** created; the seed is used to randomize hashes. -*/ -#if !defined(luai_makeseed) -#include -#define luai_makeseed() cast(unsigned int, time(NULL)) -#endif - - - -/* -** thread state + extra space -*/ -typedef struct LX { -#if defined(LUAI_EXTRASPACE) - char buff[LUAI_EXTRASPACE]; -#endif - lua_State l; -} LX; - - -/* -** Main thread combines a thread state and the global state -*/ -typedef struct LG { - LX l; - global_State g; -} LG; - - - -#define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l))) - - -/* -** Compute an initial seed as random as possible. In ANSI, rely on -** Address Space Layout Randomization (if present) to increase -** randomness.. -*/ -#define addbuff(b,p,e) \ - { size_t t = cast(size_t, e); \ - memcpy(buff + p, &t, sizeof(t)); p += sizeof(t); } - -static unsigned int makeseed (lua_State *L) { - char buff[4 * sizeof(size_t)]; - unsigned int h = luai_makeseed(); - int p = 0; - addbuff(buff, p, L); /* heap variable */ - addbuff(buff, p, &h); /* local variable */ - addbuff(buff, p, luaO_nilobject); /* global variable */ - addbuff(buff, p, &lua_newstate); /* public function */ - lua_assert(p == sizeof(buff)); - return luaS_hash(buff, p, h); -} - - -/* -** set GCdebt to a new value keeping the value (totalbytes + GCdebt) -** invariant -*/ -void luaE_setdebt (global_State *g, l_mem debt) { - g->totalbytes -= (debt - g->GCdebt); - g->GCdebt = debt; -} - - -CallInfo *luaE_extendCI (lua_State *L) { - CallInfo *ci = luaM_new(L, CallInfo); - lua_assert(L->ci->next == NULL); - L->ci->next = ci; - ci->previous = L->ci; - ci->next = NULL; - return ci; -} - - -void luaE_freeCI (lua_State *L) { - CallInfo *ci = L->ci; - CallInfo *next = ci->next; - ci->next = NULL; - while ((ci = next) != NULL) { - next = ci->next; - luaM_free(L, ci); - } -} - - -static void stack_init (lua_State *L1, lua_State *L) { - int i; CallInfo *ci; - /* initialize stack array */ - L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, TValue); - L1->stacksize = BASIC_STACK_SIZE; - for (i = 0; i < BASIC_STACK_SIZE; i++) - setnilvalue(L1->stack + i); /* erase new stack */ - L1->top = L1->stack; - L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK; - /* initialize first ci */ - ci = &L1->base_ci; - ci->next = ci->previous = NULL; - ci->callstatus = 0; - ci->func = L1->top; - setnilvalue(L1->top++); /* 'function' entry for this 'ci' */ - ci->top = L1->top + LUA_MINSTACK; - L1->ci = ci; -} - - -static void freestack (lua_State *L) { - if (L->stack == NULL) - return; /* stack not completely built yet */ - L->ci = &L->base_ci; /* free the entire 'ci' list */ - luaE_freeCI(L); - luaM_freearray(L, L->stack, L->stacksize); /* free stack array */ -} - - -/* -** Create registry table and its predefined values -*/ -static void init_registry (lua_State *L, global_State *g) { - TValue mt; - /* create registry */ - Table *registry = luaH_new(L); - sethvalue(L, &g->l_registry, registry); - luaH_resize(L, registry, LUA_RIDX_LAST, 0); - /* registry[LUA_RIDX_MAINTHREAD] = L */ - setthvalue(L, &mt, L); - luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &mt); - /* registry[LUA_RIDX_GLOBALS] = table of globals */ - sethvalue(L, &mt, luaH_new(L)); - luaH_setint(L, registry, LUA_RIDX_GLOBALS, &mt); -} - - -/* -** open parts of the state that may cause memory-allocation errors -*/ -static void f_luaopen (lua_State *L, void *ud) { - global_State *g = G(L); - UNUSED(ud); - stack_init(L, L); /* init stack */ - init_registry(L, g); - luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ - luaT_init(L); - luaX_init(L); - /* pre-create memory-error message */ - g->memerrmsg = luaS_newliteral(L, MEMERRMSG); - luaS_fix(g->memerrmsg); /* it should never be collected */ - g->gcrunning = 1; /* allow gc */ -} - - -/* -** preinitialize a state with consistent values without allocating -** any memory (to avoid errors) -*/ -static void preinit_state (lua_State *L, global_State *g) { - G(L) = g; - L->stack = NULL; - L->ci = NULL; - L->stacksize = 0; - L->errorJmp = NULL; - L->nCcalls = 0; - L->hook = NULL; - L->hookmask = 0; - L->basehookcount = 0; - L->allowhook = 1; - resethookcount(L); - L->openupval = NULL; - L->nny = 1; - L->status = LUA_OK; - L->errfunc = 0; -} - - -static void close_state (lua_State *L) { - global_State *g = G(L); - luaF_close(L, L->stack); /* close all upvalues for this thread */ - luaC_freeallobjects(L); /* collect all objects */ - luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); - luaZ_freebuffer(L, &g->buff); - freestack(L); - lua_assert(gettotalbytes(g) == sizeof(LG)); - (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ -} - - -LUA_API lua_State *lua_newthread (lua_State *L) { - lua_State *L1; - lua_lock(L); - luaC_checkGC(L); - L1 = &luaC_newobj(L, LUA_TTHREAD, sizeof(LX), NULL, offsetof(LX, l))->th; - setthvalue(L, L->top, L1); - api_incr_top(L); - preinit_state(L1, G(L)); - L1->hookmask = L->hookmask; - L1->basehookcount = L->basehookcount; - L1->hook = L->hook; - resethookcount(L1); - luai_userstatethread(L, L1); - stack_init(L1, L); /* init stack */ - lua_unlock(L); - return L1; -} - - -void luaE_freethread (lua_State *L, lua_State *L1) { - LX *l = fromstate(L1); - luaF_close(L1, L1->stack); /* close all upvalues for this thread */ - lua_assert(L1->openupval == NULL); - luai_userstatefree(L, L1); - freestack(L1); - luaM_free(L, l); -} - - -LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { - int i; - lua_State *L; - global_State *g; - LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG))); - if (l == NULL) return NULL; - L = &l->l.l; - g = &l->g; - L->next = NULL; - L->tt = LUA_TTHREAD; - g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); - L->marked = luaC_white(g); - g->gckind = KGC_NORMAL; - preinit_state(L, g); - g->frealloc = f; - g->ud = ud; - g->mainthread = L; - g->seed = makeseed(L); - g->uvhead.u.l.prev = &g->uvhead; - g->uvhead.u.l.next = &g->uvhead; - g->gcrunning = 0; /* no GC while building state */ - g->GCestimate = 0; - g->strt.size = 0; - g->strt.nuse = 0; - g->strt.hash = NULL; - setnilvalue(&g->l_registry); - luaZ_initbuffer(L, &g->buff); - g->panic = NULL; - g->version = lua_version(NULL); - g->gcstate = GCSpause; - g->allgc = NULL; - g->finobj = NULL; - g->tobefnz = NULL; - g->sweepgc = g->sweepfin = NULL; - g->gray = g->grayagain = NULL; - g->weak = g->ephemeron = g->allweak = NULL; - g->totalbytes = sizeof(LG); - g->GCdebt = 0; - g->gcpause = LUAI_GCPAUSE; - g->gcmajorinc = LUAI_GCMAJOR; - g->gcstepmul = LUAI_GCMUL; - for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; - if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { - /* memory allocation error: free partial state */ - close_state(L); - L = NULL; - } - else - luai_userstateopen(L); - return L; -} - - -LUA_API void lua_close (lua_State *L) { - L = G(L)->mainthread; /* only the main thread can be closed */ - lua_lock(L); - luai_userstateclose(L); - close_state(L); -} - - diff --git a/contrib/lua/lua/src/lstate.h b/contrib/lua/lua/src/lstate.h deleted file mode 100644 index c8a31f5c0b8..00000000000 --- a/contrib/lua/lua/src/lstate.h +++ /dev/null @@ -1,228 +0,0 @@ -/* -** $Id: lstate.h,v 2.82 2012/07/02 13:37:04 roberto Exp $ -** Global State -** See Copyright Notice in lua.h -*/ - -#ifndef lstate_h -#define lstate_h - -#include "lua.h" - -#include "lobject.h" -#include "ltm.h" -#include "lzio.h" - - -/* - -** Some notes about garbage-collected objects: All objects in Lua must -** be kept somehow accessible until being freed. -** -** Lua keeps most objects linked in list g->allgc. The link uses field -** 'next' of the CommonHeader. -** -** Strings are kept in several lists headed by the array g->strt.hash. -** -** Open upvalues are not subject to independent garbage collection. They -** are collected together with their respective threads. Lua keeps a -** double-linked list with all open upvalues (g->uvhead) so that it can -** mark objects referred by them. (They are always gray, so they must -** be remarked in the atomic step. Usually their contents would be marked -** when traversing the respective threads, but the thread may already be -** dead, while the upvalue is still accessible through closures.) -** -** Objects with finalizers are kept in the list g->finobj. -** -** The list g->tobefnz links all objects being finalized. - -*/ - - -struct lua_longjmp; /* defined in ldo.c */ - - - -/* extra stack space to handle TM calls and some other extras */ -#define EXTRA_STACK 5 - - -#define BASIC_STACK_SIZE (2*LUA_MINSTACK) - - -/* kinds of Garbage Collection */ -#define KGC_NORMAL 0 -#define KGC_EMERGENCY 1 /* gc was forced by an allocation failure */ -#define KGC_GEN 2 /* generational collection */ - - -typedef struct stringtable { - GCObject **hash; - lu_int32 nuse; /* number of elements */ - int size; -} stringtable; - - -/* -** information about a call -*/ -typedef struct CallInfo { - StkId func; /* function index in the stack */ - StkId top; /* top for this function */ - struct CallInfo *previous, *next; /* dynamic call link */ - short nresults; /* expected number of results from this function */ - lu_byte callstatus; - ptrdiff_t extra; - union { - struct { /* only for Lua functions */ - StkId base; /* base for this function */ - const Instruction *savedpc; - } l; - struct { /* only for C functions */ - int ctx; /* context info. in case of yields */ - lua_CFunction k; /* continuation in case of yields */ - ptrdiff_t old_errfunc; - lu_byte old_allowhook; - lu_byte status; - } c; - } u; -} CallInfo; - - -/* -** Bits in CallInfo status -*/ -#define CIST_LUA (1<<0) /* call is running a Lua function */ -#define CIST_HOOKED (1<<1) /* call is running a debug hook */ -#define CIST_REENTRY (1<<2) /* call is running on same invocation of - luaV_execute of previous call */ -#define CIST_YIELDED (1<<3) /* call reentered after suspension */ -#define CIST_YPCALL (1<<4) /* call is a yieldable protected call */ -#define CIST_STAT (1<<5) /* call has an error status (pcall) */ -#define CIST_TAIL (1<<6) /* call was tail called */ -#define CIST_HOOKYIELD (1<<7) /* last hook called yielded */ - - -#define isLua(ci) ((ci)->callstatus & CIST_LUA) - - -/* -** `global state', shared by all threads of this state -*/ -typedef struct global_State { - lua_Alloc frealloc; /* function to reallocate memory */ - void *ud; /* auxiliary data to `frealloc' */ - lu_mem totalbytes; /* number of bytes currently allocated - GCdebt */ - l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ - lu_mem GCmemtrav; /* memory traversed by the GC */ - lu_mem GCestimate; /* an estimate of the non-garbage memory in use */ - stringtable strt; /* hash table for strings */ - TValue l_registry; - unsigned int seed; /* randomized seed for hashes */ - lu_byte currentwhite; - lu_byte gcstate; /* state of garbage collector */ - lu_byte gckind; /* kind of GC running */ - lu_byte gcrunning; /* true if GC is running */ - int sweepstrgc; /* position of sweep in `strt' */ - GCObject *allgc; /* list of all collectable objects */ - GCObject *finobj; /* list of collectable objects with finalizers */ - GCObject **sweepgc; /* current position of sweep in list 'allgc' */ - GCObject **sweepfin; /* current position of sweep in list 'finobj' */ - GCObject *gray; /* list of gray objects */ - GCObject *grayagain; /* list of objects to be traversed atomically */ - GCObject *weak; /* list of tables with weak values */ - GCObject *ephemeron; /* list of ephemeron tables (weak keys) */ - GCObject *allweak; /* list of all-weak tables */ - GCObject *tobefnz; /* list of userdata to be GC */ - UpVal uvhead; /* head of double-linked list of all open upvalues */ - Mbuffer buff; /* temporary buffer for string concatenation */ - int gcpause; /* size of pause between successive GCs */ - int gcmajorinc; /* pause between major collections (only in gen. mode) */ - int gcstepmul; /* GC `granularity' */ - lua_CFunction panic; /* to be called in unprotected errors */ - struct lua_State *mainthread; - const lua_Number *version; /* pointer to version number */ - TString *memerrmsg; /* memory-error message */ - TString *tmname[TM_N]; /* array with tag-method names */ - struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */ -} global_State; - - -/* -** `per thread' state -*/ -struct lua_State { - CommonHeader; - lu_byte status; - StkId top; /* first free slot in the stack */ - global_State *l_G; - CallInfo *ci; /* call info for current function */ - const Instruction *oldpc; /* last pc traced */ - StkId stack_last; /* last free slot in the stack */ - StkId stack; /* stack base */ - int stacksize; - unsigned short nny; /* number of non-yieldable calls in stack */ - unsigned short nCcalls; /* number of nested C calls */ - lu_byte hookmask; - lu_byte allowhook; - int basehookcount; - int hookcount; - lua_Hook hook; - GCObject *openupval; /* list of open upvalues in this stack */ - GCObject *gclist; - struct lua_longjmp *errorJmp; /* current error recover point */ - ptrdiff_t errfunc; /* current error handling function (stack index) */ - CallInfo base_ci; /* CallInfo for first level (C calling Lua) */ -}; - - -#define G(L) (L->l_G) - - -/* -** Union of all collectable objects -*/ -union GCObject { - GCheader gch; /* common header */ - union TString ts; - union Udata u; - union Closure cl; - struct Table h; - struct Proto p; - struct UpVal uv; - struct lua_State th; /* thread */ -}; - - -#define gch(o) (&(o)->gch) - -/* macros to convert a GCObject into a specific value */ -#define rawgco2ts(o) \ - check_exp(novariant((o)->gch.tt) == LUA_TSTRING, &((o)->ts)) -#define gco2ts(o) (&rawgco2ts(o)->tsv) -#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) -#define gco2u(o) (&rawgco2u(o)->uv) -#define gco2lcl(o) check_exp((o)->gch.tt == LUA_TLCL, &((o)->cl.l)) -#define gco2ccl(o) check_exp((o)->gch.tt == LUA_TCCL, &((o)->cl.c)) -#define gco2cl(o) \ - check_exp(novariant((o)->gch.tt) == LUA_TFUNCTION, &((o)->cl)) -#define gco2t(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) -#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) -#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) -#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) - -/* macro to convert any Lua object into a GCObject */ -#define obj2gco(v) (cast(GCObject *, (v))) - - -/* actual number of total bytes allocated */ -#define gettotalbytes(g) ((g)->totalbytes + (g)->GCdebt) - -LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt); -LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); -LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L); -LUAI_FUNC void luaE_freeCI (lua_State *L); - - -#endif - diff --git a/contrib/lua/lua/src/lstring.c b/contrib/lua/lua/src/lstring.c deleted file mode 100644 index 8b5af0b2e77..00000000000 --- a/contrib/lua/lua/src/lstring.c +++ /dev/null @@ -1,185 +0,0 @@ -/* -** $Id: lstring.c,v 2.26 2013/01/08 13:50:10 roberto Exp $ -** String table (keeps all strings handled by Lua) -** See Copyright Notice in lua.h -*/ - - -#include - -#define lstring_c -#define LUA_CORE - -#include "lua.h" - -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" - - -/* -** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to -** compute its hash -*/ -#if !defined(LUAI_HASHLIMIT) -#define LUAI_HASHLIMIT 5 -#endif - - -/* -** equality for long strings -*/ -int luaS_eqlngstr (TString *a, TString *b) { - size_t len = a->tsv.len; - lua_assert(a->tsv.tt == LUA_TLNGSTR && b->tsv.tt == LUA_TLNGSTR); - return (a == b) || /* same instance or... */ - ((len == b->tsv.len) && /* equal length and ... */ - (memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */ -} - - -/* -** equality for strings -*/ -int luaS_eqstr (TString *a, TString *b) { - return (a->tsv.tt == b->tsv.tt) && - (a->tsv.tt == LUA_TSHRSTR ? eqshrstr(a, b) : luaS_eqlngstr(a, b)); -} - - -unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) { - unsigned int h = seed ^ cast(unsigned int, l); - size_t l1; - size_t step = (l >> LUAI_HASHLIMIT) + 1; - for (l1 = l; l1 >= step; l1 -= step) - h = h ^ ((h<<5) + (h>>2) + cast_byte(str[l1 - 1])); - return h; -} - - -/* -** resizes the string table -*/ -void luaS_resize (lua_State *L, int newsize) { - int i; - stringtable *tb = &G(L)->strt; - /* cannot resize while GC is traversing strings */ - luaC_runtilstate(L, ~bitmask(GCSsweepstring)); - if (newsize > tb->size) { - luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *); - for (i = tb->size; i < newsize; i++) tb->hash[i] = NULL; - } - /* rehash */ - for (i=0; isize; i++) { - GCObject *p = tb->hash[i]; - tb->hash[i] = NULL; - while (p) { /* for each node in the list */ - GCObject *next = gch(p)->next; /* save next */ - unsigned int h = lmod(gco2ts(p)->hash, newsize); /* new position */ - gch(p)->next = tb->hash[h]; /* chain it */ - tb->hash[h] = p; - resetoldbit(p); /* see MOVE OLD rule */ - p = next; - } - } - if (newsize < tb->size) { - /* shrinking slice must be empty */ - lua_assert(tb->hash[newsize] == NULL && tb->hash[tb->size - 1] == NULL); - luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *); - } - tb->size = newsize; -} - - -/* -** creates a new string object -*/ -static TString *createstrobj (lua_State *L, const char *str, size_t l, - int tag, unsigned int h, GCObject **list) { - TString *ts; - size_t totalsize; /* total size of TString object */ - totalsize = sizeof(TString) + ((l + 1) * sizeof(char)); - ts = &luaC_newobj(L, tag, totalsize, list, 0)->ts; - ts->tsv.len = l; - ts->tsv.hash = h; - ts->tsv.extra = 0; - memcpy(ts+1, str, l*sizeof(char)); - ((char *)(ts+1))[l] = '\0'; /* ending 0 */ - return ts; -} - - -/* -** creates a new short string, inserting it into string table -*/ -static TString *newshrstr (lua_State *L, const char *str, size_t l, - unsigned int h) { - GCObject **list; /* (pointer to) list where it will be inserted */ - stringtable *tb = &G(L)->strt; - TString *s; - if (tb->nuse >= cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) - luaS_resize(L, tb->size*2); /* too crowded */ - list = &tb->hash[lmod(h, tb->size)]; - s = createstrobj(L, str, l, LUA_TSHRSTR, h, list); - tb->nuse++; - return s; -} - - -/* -** checks whether short string exists and reuses it or creates a new one -*/ -static TString *internshrstr (lua_State *L, const char *str, size_t l) { - GCObject *o; - global_State *g = G(L); - unsigned int h = luaS_hash(str, l, g->seed); - for (o = g->strt.hash[lmod(h, g->strt.size)]; - o != NULL; - o = gch(o)->next) { - TString *ts = rawgco2ts(o); - if (h == ts->tsv.hash && - l == ts->tsv.len && - (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { - if (isdead(G(L), o)) /* string is dead (but was not collected yet)? */ - changewhite(o); /* resurrect it */ - return ts; - } - } - return newshrstr(L, str, l, h); /* not found; create a new string */ -} - - -/* -** new string (with explicit length) -*/ -TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { - if (l <= LUAI_MAXSHORTLEN) /* short string? */ - return internshrstr(L, str, l); - else { - if (l + 1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) - luaM_toobig(L); - return createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed, NULL); - } -} - - -/* -** new zero-terminated string -*/ -TString *luaS_new (lua_State *L, const char *str) { - return luaS_newlstr(L, str, strlen(str)); -} - - -Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { - Udata *u; - if (s > MAX_SIZET - sizeof(Udata)) - luaM_toobig(L); - u = &luaC_newobj(L, LUA_TUSERDATA, sizeof(Udata) + s, NULL, 0)->u; - u->uv.len = s; - u->uv.metatable = NULL; - u->uv.env = e; - return u; -} - diff --git a/contrib/lua/lua/src/lstring.h b/contrib/lua/lua/src/lstring.h deleted file mode 100644 index d312ff3d2b1..00000000000 --- a/contrib/lua/lua/src/lstring.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -** $Id: lstring.h,v 1.49 2012/02/01 21:57:15 roberto Exp $ -** String table (keep all strings handled by Lua) -** See Copyright Notice in lua.h -*/ - -#ifndef lstring_h -#define lstring_h - -#include "lgc.h" -#include "lobject.h" -#include "lstate.h" - - -#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char)) - -#define sizeudata(u) (sizeof(union Udata)+(u)->len) - -#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ - (sizeof(s)/sizeof(char))-1)) - -#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) - - -/* -** test whether a string is a reserved word -*/ -#define isreserved(s) ((s)->tsv.tt == LUA_TSHRSTR && (s)->tsv.extra > 0) - - -/* -** equality for short strings, which are always internalized -*/ -#define eqshrstr(a,b) check_exp((a)->tsv.tt == LUA_TSHRSTR, (a) == (b)) - - -LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed); -LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b); -LUAI_FUNC int luaS_eqstr (TString *a, TString *b); -LUAI_FUNC void luaS_resize (lua_State *L, int newsize); -LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); -LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); -LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); - - -#endif diff --git a/contrib/lua/lua/src/lstrlib.c b/contrib/lua/lua/src/lstrlib.c deleted file mode 100644 index fcc61c9a624..00000000000 --- a/contrib/lua/lua/src/lstrlib.c +++ /dev/null @@ -1,1019 +0,0 @@ -/* -** $Id: lstrlib.c,v 1.178 2012/08/14 18:12:34 roberto Exp $ -** Standard library for string operations and pattern-matching -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include -#include -#include - -#define lstrlib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -/* -** maximum number of captures that a pattern can do during -** pattern-matching. This limit is arbitrary. -*/ -#if !defined(LUA_MAXCAPTURES) -#define LUA_MAXCAPTURES 32 -#endif - - -/* macro to `unsign' a character */ -#define uchar(c) ((unsigned char)(c)) - - - -static int str_len (lua_State *L) { - size_t l; - luaL_checklstring(L, 1, &l); - lua_pushinteger(L, (lua_Integer)l); - return 1; -} - - -/* translate a relative string position: negative means back from end */ -static size_t posrelat (ptrdiff_t pos, size_t len) { - if (pos >= 0) return (size_t)pos; - else if (0u - (size_t)pos > len) return 0; - else return len - ((size_t)-pos) + 1; -} - - -static int str_sub (lua_State *L) { - size_t l; - const char *s = luaL_checklstring(L, 1, &l); - size_t start = posrelat(luaL_checkinteger(L, 2), l); - size_t end = posrelat(luaL_optinteger(L, 3, -1), l); - if (start < 1) start = 1; - if (end > l) end = l; - if (start <= end) - lua_pushlstring(L, s + start - 1, end - start + 1); - else lua_pushliteral(L, ""); - return 1; -} - - -static int str_reverse (lua_State *L) { - size_t l, i; - luaL_Buffer b; - const char *s = luaL_checklstring(L, 1, &l); - char *p = luaL_buffinitsize(L, &b, l); - for (i = 0; i < l; i++) - p[i] = s[l - i - 1]; - luaL_pushresultsize(&b, l); - return 1; -} - - -static int str_lower (lua_State *L) { - size_t l; - size_t i; - luaL_Buffer b; - const char *s = luaL_checklstring(L, 1, &l); - char *p = luaL_buffinitsize(L, &b, l); - for (i=0; i> 1) - -static int str_rep (lua_State *L) { - size_t l, lsep; - const char *s = luaL_checklstring(L, 1, &l); - int n = luaL_checkint(L, 2); - const char *sep = luaL_optlstring(L, 3, "", &lsep); - if (n <= 0) lua_pushliteral(L, ""); - else if (l + lsep < l || l + lsep >= MAXSIZE / n) /* may overflow? */ - return luaL_error(L, "resulting string too large"); - else { - size_t totallen = n * l + (n - 1) * lsep; - luaL_Buffer b; - char *p = luaL_buffinitsize(L, &b, totallen); - while (n-- > 1) { /* first n-1 copies (followed by separator) */ - memcpy(p, s, l * sizeof(char)); p += l; - if (lsep > 0) { /* avoid empty 'memcpy' (may be expensive) */ - memcpy(p, sep, lsep * sizeof(char)); p += lsep; - } - } - memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */ - luaL_pushresultsize(&b, totallen); - } - return 1; -} - - -static int str_byte (lua_State *L) { - size_t l; - const char *s = luaL_checklstring(L, 1, &l); - size_t posi = posrelat(luaL_optinteger(L, 2, 1), l); - size_t pose = posrelat(luaL_optinteger(L, 3, posi), l); - int n, i; - if (posi < 1) posi = 1; - if (pose > l) pose = l; - if (posi > pose) return 0; /* empty interval; return no values */ - n = (int)(pose - posi + 1); - if (posi + n <= pose) /* (size_t -> int) overflow? */ - return luaL_error(L, "string slice too long"); - luaL_checkstack(L, n, "string slice too long"); - for (i=0; i= ms->level || ms->capture[l].len == CAP_UNFINISHED) - return luaL_error(ms->L, "invalid capture index %%%d", l + 1); - return l; -} - - -static int capture_to_close (MatchState *ms) { - int level = ms->level; - for (level--; level>=0; level--) - if (ms->capture[level].len == CAP_UNFINISHED) return level; - return luaL_error(ms->L, "invalid pattern capture"); -} - - -static const char *classend (MatchState *ms, const char *p) { - switch (*p++) { - case L_ESC: { - if (p == ms->p_end) - luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); - return p+1; - } - case '[': { - if (*p == '^') p++; - do { /* look for a `]' */ - if (p == ms->p_end) - luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); - if (*(p++) == L_ESC && p < ms->p_end) - p++; /* skip escapes (e.g. `%]') */ - } while (*p != ']'); - return p+1; - } - default: { - return p; - } - } -} - - -static int match_class (int c, int cl) { - int res; - switch (tolower(cl)) { - case 'a' : res = isalpha(c); break; - case 'c' : res = iscntrl(c); break; - case 'd' : res = isdigit(c); break; - case 'g' : res = isgraph(c); break; - case 'l' : res = islower(c); break; - case 'p' : res = ispunct(c); break; - case 's' : res = isspace(c); break; - case 'u' : res = isupper(c); break; - case 'w' : res = isalnum(c); break; - case 'x' : res = isxdigit(c); break; - case 'z' : res = (c == 0); break; /* deprecated option */ - default: return (cl == c); - } - return (islower(cl) ? res : !res); -} - - -static int matchbracketclass (int c, const char *p, const char *ec) { - int sig = 1; - if (*(p+1) == '^') { - sig = 0; - p++; /* skip the `^' */ - } - while (++p < ec) { - if (*p == L_ESC) { - p++; - if (match_class(c, uchar(*p))) - return sig; - } - else if ((*(p+1) == '-') && (p+2 < ec)) { - p+=2; - if (uchar(*(p-2)) <= c && c <= uchar(*p)) - return sig; - } - else if (uchar(*p) == c) return sig; - } - return !sig; -} - - -static int singlematch (MatchState *ms, const char *s, const char *p, - const char *ep) { - if (s >= ms->src_end) - return 0; - else { - int c = uchar(*s); - switch (*p) { - case '.': return 1; /* matches any char */ - case L_ESC: return match_class(c, uchar(*(p+1))); - case '[': return matchbracketclass(c, p, ep-1); - default: return (uchar(*p) == c); - } - } -} - - -static const char *matchbalance (MatchState *ms, const char *s, - const char *p) { - if (p >= ms->p_end - 1) - luaL_error(ms->L, "malformed pattern " - "(missing arguments to " LUA_QL("%%b") ")"); - if (*s != *p) return NULL; - else { - int b = *p; - int e = *(p+1); - int cont = 1; - while (++s < ms->src_end) { - if (*s == e) { - if (--cont == 0) return s+1; - } - else if (*s == b) cont++; - } - } - return NULL; /* string ends out of balance */ -} - - -static const char *max_expand (MatchState *ms, const char *s, - const char *p, const char *ep) { - ptrdiff_t i = 0; /* counts maximum expand for item */ - while (singlematch(ms, s + i, p, ep)) - i++; - /* keeps trying to match with the maximum repetitions */ - while (i>=0) { - const char *res = match(ms, (s+i), ep+1); - if (res) return res; - i--; /* else didn't match; reduce 1 repetition to try again */ - } - return NULL; -} - - -static const char *min_expand (MatchState *ms, const char *s, - const char *p, const char *ep) { - for (;;) { - const char *res = match(ms, s, ep+1); - if (res != NULL) - return res; - else if (singlematch(ms, s, p, ep)) - s++; /* try with one more repetition */ - else return NULL; - } -} - - -static const char *start_capture (MatchState *ms, const char *s, - const char *p, int what) { - const char *res; - int level = ms->level; - if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures"); - ms->capture[level].init = s; - ms->capture[level].len = what; - ms->level = level+1; - if ((res=match(ms, s, p)) == NULL) /* match failed? */ - ms->level--; /* undo capture */ - return res; -} - - -static const char *end_capture (MatchState *ms, const char *s, - const char *p) { - int l = capture_to_close(ms); - const char *res; - ms->capture[l].len = s - ms->capture[l].init; /* close capture */ - if ((res = match(ms, s, p)) == NULL) /* match failed? */ - ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ - return res; -} - - -static const char *match_capture (MatchState *ms, const char *s, int l) { - size_t len; - l = check_capture(ms, l); - len = ms->capture[l].len; - if ((size_t)(ms->src_end-s) >= len && - memcmp(ms->capture[l].init, s, len) == 0) - return s+len; - else return NULL; -} - - -static const char *match (MatchState *ms, const char *s, const char *p) { - if (ms->matchdepth-- == 0) - luaL_error(ms->L, "pattern too complex"); - init: /* using goto's to optimize tail recursion */ - if (p != ms->p_end) { /* end of pattern? */ - switch (*p) { - case '(': { /* start capture */ - if (*(p + 1) == ')') /* position capture? */ - s = start_capture(ms, s, p + 2, CAP_POSITION); - else - s = start_capture(ms, s, p + 1, CAP_UNFINISHED); - break; - } - case ')': { /* end capture */ - s = end_capture(ms, s, p + 1); - break; - } - case '$': { - if ((p + 1) != ms->p_end) /* is the `$' the last char in pattern? */ - goto dflt; /* no; go to default */ - s = (s == ms->src_end) ? s : NULL; /* check end of string */ - break; - } - case L_ESC: { /* escaped sequences not in the format class[*+?-]? */ - switch (*(p + 1)) { - case 'b': { /* balanced string? */ - s = matchbalance(ms, s, p + 2); - if (s != NULL) { - p += 4; goto init; /* return match(ms, s, p + 4); */ - } /* else fail (s == NULL) */ - break; - } - case 'f': { /* frontier? */ - const char *ep; char previous; - p += 2; - if (*p != '[') - luaL_error(ms->L, "missing " LUA_QL("[") " after " - LUA_QL("%%f") " in pattern"); - ep = classend(ms, p); /* points to what is next */ - previous = (s == ms->src_init) ? '\0' : *(s - 1); - if (!matchbracketclass(uchar(previous), p, ep - 1) && - matchbracketclass(uchar(*s), p, ep - 1)) { - p = ep; goto init; /* return match(ms, s, ep); */ - } - s = NULL; /* match failed */ - break; - } - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - case '8': case '9': { /* capture results (%0-%9)? */ - s = match_capture(ms, s, uchar(*(p + 1))); - if (s != NULL) { - p += 2; goto init; /* return match(ms, s, p + 2) */ - } - break; - } - default: goto dflt; - } - break; - } - default: dflt: { /* pattern class plus optional suffix */ - const char *ep = classend(ms, p); /* points to optional suffix */ - /* does not match at least once? */ - if (!singlematch(ms, s, p, ep)) { - if (*ep == '*' || *ep == '?' || *ep == '-') { /* accept empty? */ - p = ep + 1; goto init; /* return match(ms, s, ep + 1); */ - } - else /* '+' or no suffix */ - s = NULL; /* fail */ - } - else { /* matched once */ - switch (*ep) { /* handle optional suffix */ - case '?': { /* optional */ - const char *res; - if ((res = match(ms, s + 1, ep + 1)) != NULL) - s = res; - else { - p = ep + 1; goto init; /* else return match(ms, s, ep + 1); */ - } - break; - } - case '+': /* 1 or more repetitions */ - s++; /* 1 match already done */ - /* go through */ - case '*': /* 0 or more repetitions */ - s = max_expand(ms, s, p, ep); - break; - case '-': /* 0 or more repetitions (minimum) */ - s = min_expand(ms, s, p, ep); - break; - default: /* no suffix */ - s++; p = ep; goto init; /* return match(ms, s + 1, ep); */ - } - } - break; - } - } - } - ms->matchdepth++; - return s; -} - - - -static const char *lmemfind (const char *s1, size_t l1, - const char *s2, size_t l2) { - if (l2 == 0) return s1; /* empty strings are everywhere */ - else if (l2 > l1) return NULL; /* avoids a negative `l1' */ - else { - const char *init; /* to search for a `*s2' inside `s1' */ - l2--; /* 1st char will be checked by `memchr' */ - l1 = l1-l2; /* `s2' cannot be found after that */ - while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { - init++; /* 1st char is already checked */ - if (memcmp(init, s2+1, l2) == 0) - return init-1; - else { /* correct `l1' and `s1' to try again */ - l1 -= init-s1; - s1 = init; - } - } - return NULL; /* not found */ - } -} - - -static void push_onecapture (MatchState *ms, int i, const char *s, - const char *e) { - if (i >= ms->level) { - if (i == 0) /* ms->level == 0, too */ - lua_pushlstring(ms->L, s, e - s); /* add whole match */ - else - luaL_error(ms->L, "invalid capture index"); - } - else { - ptrdiff_t l = ms->capture[i].len; - if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); - if (l == CAP_POSITION) - lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1); - else - lua_pushlstring(ms->L, ms->capture[i].init, l); - } -} - - -static int push_captures (MatchState *ms, const char *s, const char *e) { - int i; - int nlevels = (ms->level == 0 && s) ? 1 : ms->level; - luaL_checkstack(ms->L, nlevels, "too many captures"); - for (i = 0; i < nlevels; i++) - push_onecapture(ms, i, s, e); - return nlevels; /* number of strings pushed */ -} - - -/* check whether pattern has no special characters */ -static int nospecials (const char *p, size_t l) { - size_t upto = 0; - do { - if (strpbrk(p + upto, SPECIALS)) - return 0; /* pattern has a special character */ - upto += strlen(p + upto) + 1; /* may have more after \0 */ - } while (upto <= l); - return 1; /* no special chars found */ -} - - -static int str_find_aux (lua_State *L, int find) { - size_t ls, lp; - const char *s = luaL_checklstring(L, 1, &ls); - const char *p = luaL_checklstring(L, 2, &lp); - size_t init = posrelat(luaL_optinteger(L, 3, 1), ls); - if (init < 1) init = 1; - else if (init > ls + 1) { /* start after string's end? */ - lua_pushnil(L); /* cannot find anything */ - return 1; - } - /* explicit request or no special characters? */ - if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) { - /* do a plain search */ - const char *s2 = lmemfind(s + init - 1, ls - init + 1, p, lp); - if (s2) { - lua_pushinteger(L, s2 - s + 1); - lua_pushinteger(L, s2 - s + lp); - return 2; - } - } - else { - MatchState ms; - const char *s1 = s + init - 1; - int anchor = (*p == '^'); - if (anchor) { - p++; lp--; /* skip anchor character */ - } - ms.L = L; - ms.matchdepth = MAXCCALLS; - ms.src_init = s; - ms.src_end = s + ls; - ms.p_end = p + lp; - do { - const char *res; - ms.level = 0; - lua_assert(ms.matchdepth == MAXCCALLS); - if ((res=match(&ms, s1, p)) != NULL) { - if (find) { - lua_pushinteger(L, s1 - s + 1); /* start */ - lua_pushinteger(L, res - s); /* end */ - return push_captures(&ms, NULL, 0) + 2; - } - else - return push_captures(&ms, s1, res); - } - } while (s1++ < ms.src_end && !anchor); - } - lua_pushnil(L); /* not found */ - return 1; -} - - -static int str_find (lua_State *L) { - return str_find_aux(L, 1); -} - - -static int str_match (lua_State *L) { - return str_find_aux(L, 0); -} - - -static int gmatch_aux (lua_State *L) { - MatchState ms; - size_t ls, lp; - const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); - const char *p = lua_tolstring(L, lua_upvalueindex(2), &lp); - const char *src; - ms.L = L; - ms.matchdepth = MAXCCALLS; - ms.src_init = s; - ms.src_end = s+ls; - ms.p_end = p + lp; - for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); - src <= ms.src_end; - src++) { - const char *e; - ms.level = 0; - lua_assert(ms.matchdepth == MAXCCALLS); - if ((e = match(&ms, src, p)) != NULL) { - lua_Integer newstart = e-s; - if (e == src) newstart++; /* empty match? go at least one position */ - lua_pushinteger(L, newstart); - lua_replace(L, lua_upvalueindex(3)); - return push_captures(&ms, src, e); - } - } - return 0; /* not found */ -} - - -static int gmatch (lua_State *L) { - luaL_checkstring(L, 1); - luaL_checkstring(L, 2); - lua_settop(L, 2); - lua_pushinteger(L, 0); - lua_pushcclosure(L, gmatch_aux, 3); - return 1; -} - - -static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, - const char *e) { - size_t l, i; - const char *news = lua_tolstring(ms->L, 3, &l); - for (i = 0; i < l; i++) { - if (news[i] != L_ESC) - luaL_addchar(b, news[i]); - else { - i++; /* skip ESC */ - if (!isdigit(uchar(news[i]))) { - if (news[i] != L_ESC) - luaL_error(ms->L, "invalid use of " LUA_QL("%c") - " in replacement string", L_ESC); - luaL_addchar(b, news[i]); - } - else if (news[i] == '0') - luaL_addlstring(b, s, e - s); - else { - push_onecapture(ms, news[i] - '1', s, e); - luaL_addvalue(b); /* add capture to accumulated result */ - } - } - } -} - - -static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, - const char *e, int tr) { - lua_State *L = ms->L; - switch (tr) { - case LUA_TFUNCTION: { - int n; - lua_pushvalue(L, 3); - n = push_captures(ms, s, e); - lua_call(L, n, 1); - break; - } - case LUA_TTABLE: { - push_onecapture(ms, 0, s, e); - lua_gettable(L, 3); - break; - } - default: { /* LUA_TNUMBER or LUA_TSTRING */ - add_s(ms, b, s, e); - return; - } - } - if (!lua_toboolean(L, -1)) { /* nil or false? */ - lua_pop(L, 1); - lua_pushlstring(L, s, e - s); /* keep original text */ - } - else if (!lua_isstring(L, -1)) - luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); - luaL_addvalue(b); /* add result to accumulator */ -} - - -static int str_gsub (lua_State *L) { - size_t srcl, lp; - const char *src = luaL_checklstring(L, 1, &srcl); - const char *p = luaL_checklstring(L, 2, &lp); - int tr = lua_type(L, 3); - size_t max_s = luaL_optinteger(L, 4, srcl+1); - int anchor = (*p == '^'); - size_t n = 0; - MatchState ms; - luaL_Buffer b; - luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || - tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, - "string/function/table expected"); - luaL_buffinit(L, &b); - if (anchor) { - p++; lp--; /* skip anchor character */ - } - ms.L = L; - ms.matchdepth = MAXCCALLS; - ms.src_init = src; - ms.src_end = src+srcl; - ms.p_end = p + lp; - while (n < max_s) { - const char *e; - ms.level = 0; - lua_assert(ms.matchdepth == MAXCCALLS); - e = match(&ms, src, p); - if (e) { - n++; - add_value(&ms, &b, src, e, tr); - } - if (e && e>src) /* non empty match? */ - src = e; /* skip it */ - else if (src < ms.src_end) - luaL_addchar(&b, *src++); - else break; - if (anchor) break; - } - luaL_addlstring(&b, src, ms.src_end-src); - luaL_pushresult(&b); - lua_pushinteger(L, n); /* number of substitutions */ - return 2; -} - -/* }====================================================== */ - - - -/* -** {====================================================== -** STRING FORMAT -** ======================================================= -*/ - -/* -** LUA_INTFRMLEN is the length modifier for integer conversions in -** 'string.format'; LUA_INTFRM_T is the integer type corresponding to -** the previous length -*/ -#if !defined(LUA_INTFRMLEN) /* { */ -#if defined(LUA_USE_LONGLONG) - -#define LUA_INTFRMLEN "ll" -#define LUA_INTFRM_T long long - -#else - -#define LUA_INTFRMLEN "l" -#define LUA_INTFRM_T long - -#endif -#endif /* } */ - - -/* -** LUA_FLTFRMLEN is the length modifier for float conversions in -** 'string.format'; LUA_FLTFRM_T is the float type corresponding to -** the previous length -*/ -#if !defined(LUA_FLTFRMLEN) - -#define LUA_FLTFRMLEN "" -#define LUA_FLTFRM_T double - -#endif - - -/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ -#define MAX_ITEM 512 -/* valid flags in a format specification */ -#define FLAGS "-+ #0" -/* -** maximum size of each format specification (such as '%-099.99d') -** (+10 accounts for %99.99x plus margin of error) -*/ -#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) - - -static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { - size_t l; - const char *s = luaL_checklstring(L, arg, &l); - luaL_addchar(b, '"'); - while (l--) { - if (*s == '"' || *s == '\\' || *s == '\n') { - luaL_addchar(b, '\\'); - luaL_addchar(b, *s); - } - else if (*s == '\0' || iscntrl(uchar(*s))) { - char buff[10]; - if (!isdigit(uchar(*(s+1)))) - sprintf(buff, "\\%d", (int)uchar(*s)); - else - sprintf(buff, "\\%03d", (int)uchar(*s)); - luaL_addstring(b, buff); - } - else - luaL_addchar(b, *s); - s++; - } - luaL_addchar(b, '"'); -} - -static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { - const char *p = strfrmt; - while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ - if ((size_t)(p - strfrmt) >= sizeof(FLAGS)/sizeof(char)) - luaL_error(L, "invalid format (repeated flags)"); - if (isdigit(uchar(*p))) p++; /* skip width */ - if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ - if (*p == '.') { - p++; - if (isdigit(uchar(*p))) p++; /* skip precision */ - if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ - } - if (isdigit(uchar(*p))) - luaL_error(L, "invalid format (width or precision too long)"); - *(form++) = '%'; - memcpy(form, strfrmt, (p - strfrmt + 1) * sizeof(char)); - form += p - strfrmt + 1; - *form = '\0'; - return p; -} - - -/* -** add length modifier into formats -*/ -static void addlenmod (char *form, const char *lenmod) { - size_t l = strlen(form); - size_t lm = strlen(lenmod); - char spec = form[l - 1]; - strcpy(form + l - 1, lenmod); - form[l + lm - 1] = spec; - form[l + lm] = '\0'; -} - - -static int str_format (lua_State *L) { - int top = lua_gettop(L); - int arg = 1; - size_t sfl; - const char *strfrmt = luaL_checklstring(L, arg, &sfl); - const char *strfrmt_end = strfrmt+sfl; - luaL_Buffer b; - luaL_buffinit(L, &b); - while (strfrmt < strfrmt_end) { - if (*strfrmt != L_ESC) - luaL_addchar(&b, *strfrmt++); - else if (*++strfrmt == L_ESC) - luaL_addchar(&b, *strfrmt++); /* %% */ - else { /* format item */ - char form[MAX_FORMAT]; /* to store the format (`%...') */ - char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */ - int nb = 0; /* number of bytes in added item */ - if (++arg > top) - luaL_argerror(L, arg, "no value"); - strfrmt = scanformat(L, strfrmt, form); - switch (*strfrmt++) { - case 'c': { - nb = sprintf(buff, form, luaL_checkint(L, arg)); - break; - } - case 'd': case 'i': { - lua_Number n = luaL_checknumber(L, arg); - LUA_INTFRM_T ni = (LUA_INTFRM_T)n; - lua_Number diff = n - (lua_Number)ni; - luaL_argcheck(L, -1 < diff && diff < 1, arg, - "not a number in proper range"); - addlenmod(form, LUA_INTFRMLEN); - nb = sprintf(buff, form, ni); - break; - } - case 'o': case 'u': case 'x': case 'X': { - lua_Number n = luaL_checknumber(L, arg); - unsigned LUA_INTFRM_T ni = (unsigned LUA_INTFRM_T)n; - lua_Number diff = n - (lua_Number)ni; - luaL_argcheck(L, -1 < diff && diff < 1, arg, - "not a non-negative number in proper range"); - addlenmod(form, LUA_INTFRMLEN); - nb = sprintf(buff, form, ni); - break; - } - case 'e': case 'E': case 'f': -#if defined(LUA_USE_AFORMAT) - case 'a': case 'A': -#endif - case 'g': case 'G': { - addlenmod(form, LUA_FLTFRMLEN); - nb = sprintf(buff, form, (LUA_FLTFRM_T)luaL_checknumber(L, arg)); - break; - } - case 'q': { - addquoted(L, &b, arg); - break; - } - case 's': { - size_t l; - const char *s = luaL_tolstring(L, arg, &l); - if (!strchr(form, '.') && l >= 100) { - /* no precision and string is too long to be formatted; - keep original string */ - luaL_addvalue(&b); - break; - } - else { - nb = sprintf(buff, form, s); - lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ - break; - } - } - default: { /* also treat cases `pnLlh' */ - return luaL_error(L, "invalid option " LUA_QL("%%%c") " to " - LUA_QL("format"), *(strfrmt - 1)); - } - } - luaL_addsize(&b, nb); - } - } - luaL_pushresult(&b); - return 1; -} - -/* }====================================================== */ - - -static const luaL_Reg strlib[] = { - {"byte", str_byte}, - {"char", str_char}, - {"dump", str_dump}, - {"find", str_find}, - {"format", str_format}, - {"gmatch", gmatch}, - {"gsub", str_gsub}, - {"len", str_len}, - {"lower", str_lower}, - {"match", str_match}, - {"rep", str_rep}, - {"reverse", str_reverse}, - {"sub", str_sub}, - {"upper", str_upper}, - {NULL, NULL} -}; - - -static void createmetatable (lua_State *L) { - lua_createtable(L, 0, 1); /* table to be metatable for strings */ - lua_pushliteral(L, ""); /* dummy string */ - lua_pushvalue(L, -2); /* copy table */ - lua_setmetatable(L, -2); /* set table as metatable for strings */ - lua_pop(L, 1); /* pop dummy string */ - lua_pushvalue(L, -2); /* get string library */ - lua_setfield(L, -2, "__index"); /* metatable.__index = string */ - lua_pop(L, 1); /* pop metatable */ -} - - -/* -** Open string library -*/ -LUAMOD_API int luaopen_string (lua_State *L) { - luaL_newlib(L, strlib); - createmetatable(L); - return 1; -} - diff --git a/contrib/lua/lua/src/ltable.c b/contrib/lua/lua/src/ltable.c deleted file mode 100644 index 420391fc745..00000000000 --- a/contrib/lua/lua/src/ltable.c +++ /dev/null @@ -1,588 +0,0 @@ -/* -** $Id: ltable.c,v 2.72 2012/09/11 19:37:16 roberto Exp $ -** Lua tables (hash) -** See Copyright Notice in lua.h -*/ - - -/* -** Implementation of tables (aka arrays, objects, or hash tables). -** Tables keep its elements in two parts: an array part and a hash part. -** Non-negative integer keys are all candidates to be kept in the array -** part. The actual size of the array is the largest `n' such that at -** least half the slots between 0 and n are in use. -** Hash uses a mix of chained scatter table with Brent's variation. -** A main invariant of these tables is that, if an element is not -** in its main position (i.e. the `original' position that its hash gives -** to it), then the colliding element is in its own main position. -** Hence even when the load factor reaches 100%, performance remains good. -*/ - -#include - -#define ltable_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "lvm.h" - - -/* -** max size of array part is 2^MAXBITS -*/ -#if LUAI_BITSINT >= 32 -#define MAXBITS 30 -#else -#define MAXBITS (LUAI_BITSINT-2) -#endif - -#define MAXASIZE (1 << MAXBITS) - - -#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) - -#define hashstr(t,str) hashpow2(t, (str)->tsv.hash) -#define hashboolean(t,p) hashpow2(t, p) - - -/* -** for some types, it is better to avoid modulus by power of 2, as -** they tend to have many 2 factors. -*/ -#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) - - -#define hashpointer(t,p) hashmod(t, IntPoint(p)) - - -#define dummynode (&dummynode_) - -#define isdummy(n) ((n) == dummynode) - -static const Node dummynode_ = { - {NILCONSTANT}, /* value */ - {{NILCONSTANT, NULL}} /* key */ -}; - - -/* -** hash for lua_Numbers -*/ -static Node *hashnum (const Table *t, lua_Number n) { - int i; - luai_hashnum(i, n); - if (i < 0) { - if (cast(unsigned int, i) == 0u - i) /* use unsigned to avoid overflows */ - i = 0; /* handle INT_MIN */ - i = -i; /* must be a positive value */ - } - return hashmod(t, i); -} - - - -/* -** returns the `main' position of an element in a table (that is, the index -** of its hash value) -*/ -static Node *mainposition (const Table *t, const TValue *key) { - switch (ttype(key)) { - case LUA_TNUMBER: - return hashnum(t, nvalue(key)); - case LUA_TLNGSTR: { - TString *s = rawtsvalue(key); - if (s->tsv.extra == 0) { /* no hash? */ - s->tsv.hash = luaS_hash(getstr(s), s->tsv.len, s->tsv.hash); - s->tsv.extra = 1; /* now it has its hash */ - } - return hashstr(t, rawtsvalue(key)); - } - case LUA_TSHRSTR: - return hashstr(t, rawtsvalue(key)); - case LUA_TBOOLEAN: - return hashboolean(t, bvalue(key)); - case LUA_TLIGHTUSERDATA: - return hashpointer(t, pvalue(key)); - case LUA_TLCF: - return hashpointer(t, fvalue(key)); - default: - return hashpointer(t, gcvalue(key)); - } -} - - -/* -** returns the index for `key' if `key' is an appropriate key to live in -** the array part of the table, -1 otherwise. -*/ -static int arrayindex (const TValue *key) { - if (ttisnumber(key)) { - lua_Number n = nvalue(key); - int k; - lua_number2int(k, n); - if (luai_numeq(cast_num(k), n)) - return k; - } - return -1; /* `key' did not match some condition */ -} - - -/* -** returns the index of a `key' for table traversals. First goes all -** elements in the array part, then elements in the hash part. The -** beginning of a traversal is signaled by -1. -*/ -static int findindex (lua_State *L, Table *t, StkId key) { - int i; - if (ttisnil(key)) return -1; /* first iteration */ - i = arrayindex(key); - if (0 < i && i <= t->sizearray) /* is `key' inside array part? */ - return i-1; /* yes; that's the index (corrected to C) */ - else { - Node *n = mainposition(t, key); - for (;;) { /* check whether `key' is somewhere in the chain */ - /* key may be dead already, but it is ok to use it in `next' */ - if (luaV_rawequalobj(gkey(n), key) || - (ttisdeadkey(gkey(n)) && iscollectable(key) && - deadvalue(gkey(n)) == gcvalue(key))) { - i = cast_int(n - gnode(t, 0)); /* key index in hash table */ - /* hash elements are numbered after array ones */ - return i + t->sizearray; - } - else n = gnext(n); - if (n == NULL) - luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ - } - } -} - - -int luaH_next (lua_State *L, Table *t, StkId key) { - int i = findindex(L, t, key); /* find original element */ - for (i++; i < t->sizearray; i++) { /* try first array part */ - if (!ttisnil(&t->array[i])) { /* a non-nil value? */ - setnvalue(key, cast_num(i+1)); - setobj2s(L, key+1, &t->array[i]); - return 1; - } - } - for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ - if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ - setobj2s(L, key, gkey(gnode(t, i))); - setobj2s(L, key+1, gval(gnode(t, i))); - return 1; - } - } - return 0; /* no more elements */ -} - - -/* -** {============================================================= -** Rehash -** ============================================================== -*/ - - -static int computesizes (int nums[], int *narray) { - int i; - int twotoi; /* 2^i */ - int a = 0; /* number of elements smaller than 2^i */ - int na = 0; /* number of elements to go to array part */ - int n = 0; /* optimal size for array part */ - for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) { - if (nums[i] > 0) { - a += nums[i]; - if (a > twotoi/2) { /* more than half elements present? */ - n = twotoi; /* optimal size (till now) */ - na = a; /* all elements smaller than n will go to array part */ - } - } - if (a == *narray) break; /* all elements already counted */ - } - *narray = n; - lua_assert(*narray/2 <= na && na <= *narray); - return na; -} - - -static int countint (const TValue *key, int *nums) { - int k = arrayindex(key); - if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ - nums[luaO_ceillog2(k)]++; /* count as such */ - return 1; - } - else - return 0; -} - - -static int numusearray (const Table *t, int *nums) { - int lg; - int ttlg; /* 2^lg */ - int ause = 0; /* summation of `nums' */ - int i = 1; /* count to traverse all array keys */ - for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) { /* for each slice */ - int lc = 0; /* counter */ - int lim = ttlg; - if (lim > t->sizearray) { - lim = t->sizearray; /* adjust upper limit */ - if (i > lim) - break; /* no more elements to count */ - } - /* count elements in range (2^(lg-1), 2^lg] */ - for (; i <= lim; i++) { - if (!ttisnil(&t->array[i-1])) - lc++; - } - nums[lg] += lc; - ause += lc; - } - return ause; -} - - -static int numusehash (const Table *t, int *nums, int *pnasize) { - int totaluse = 0; /* total number of elements */ - int ause = 0; /* summation of `nums' */ - int i = sizenode(t); - while (i--) { - Node *n = &t->node[i]; - if (!ttisnil(gval(n))) { - ause += countint(gkey(n), nums); - totaluse++; - } - } - *pnasize += ause; - return totaluse; -} - - -static void setarrayvector (lua_State *L, Table *t, int size) { - int i; - luaM_reallocvector(L, t->array, t->sizearray, size, TValue); - for (i=t->sizearray; iarray[i]); - t->sizearray = size; -} - - -static void setnodevector (lua_State *L, Table *t, int size) { - int lsize; - if (size == 0) { /* no elements to hash part? */ - t->node = cast(Node *, dummynode); /* use common `dummynode' */ - lsize = 0; - } - else { - int i; - lsize = luaO_ceillog2(size); - if (lsize > MAXBITS) - luaG_runerror(L, "table overflow"); - size = twoto(lsize); - t->node = luaM_newvector(L, size, Node); - for (i=0; ilsizenode = cast_byte(lsize); - t->lastfree = gnode(t, size); /* all positions are free */ -} - - -void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize) { - int i; - int oldasize = t->sizearray; - int oldhsize = t->lsizenode; - Node *nold = t->node; /* save old hash ... */ - if (nasize > oldasize) /* array part must grow? */ - setarrayvector(L, t, nasize); - /* create new hash part with appropriate size */ - setnodevector(L, t, nhsize); - if (nasize < oldasize) { /* array part must shrink? */ - t->sizearray = nasize; - /* re-insert elements from vanishing slice */ - for (i=nasize; iarray[i])) - luaH_setint(L, t, i + 1, &t->array[i]); - } - /* shrink array */ - luaM_reallocvector(L, t->array, oldasize, nasize, TValue); - } - /* re-insert elements from hash part */ - for (i = twoto(oldhsize) - 1; i >= 0; i--) { - Node *old = nold+i; - if (!ttisnil(gval(old))) { - /* doesn't need barrier/invalidate cache, as entry was - already present in the table */ - setobjt2t(L, luaH_set(L, t, gkey(old)), gval(old)); - } - } - if (!isdummy(nold)) - luaM_freearray(L, nold, cast(size_t, twoto(oldhsize))); /* free old array */ -} - - -void luaH_resizearray (lua_State *L, Table *t, int nasize) { - int nsize = isdummy(t->node) ? 0 : sizenode(t); - luaH_resize(L, t, nasize, nsize); -} - - -static void rehash (lua_State *L, Table *t, const TValue *ek) { - int nasize, na; - int nums[MAXBITS+1]; /* nums[i] = number of keys with 2^(i-1) < k <= 2^i */ - int i; - int totaluse; - for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */ - nasize = numusearray(t, nums); /* count keys in array part */ - totaluse = nasize; /* all those keys are integer keys */ - totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */ - /* count extra key */ - nasize += countint(ek, nums); - totaluse++; - /* compute new size for array part */ - na = computesizes(nums, &nasize); - /* resize the table to new computed sizes */ - luaH_resize(L, t, nasize, totaluse - na); -} - - - -/* -** }============================================================= -*/ - - -Table *luaH_new (lua_State *L) { - Table *t = &luaC_newobj(L, LUA_TTABLE, sizeof(Table), NULL, 0)->h; - t->metatable = NULL; - t->flags = cast_byte(~0); - t->array = NULL; - t->sizearray = 0; - setnodevector(L, t, 0); - return t; -} - - -void luaH_free (lua_State *L, Table *t) { - if (!isdummy(t->node)) - luaM_freearray(L, t->node, cast(size_t, sizenode(t))); - luaM_freearray(L, t->array, t->sizearray); - luaM_free(L, t); -} - - -static Node *getfreepos (Table *t) { - while (t->lastfree > t->node) { - t->lastfree--; - if (ttisnil(gkey(t->lastfree))) - return t->lastfree; - } - return NULL; /* could not find a free place */ -} - - - -/* -** inserts a new key into a hash table; first, check whether key's main -** position is free. If not, check whether colliding node is in its main -** position or not: if it is not, move colliding node to an empty place and -** put new key in its main position; otherwise (colliding node is in its main -** position), new key goes to an empty position. -*/ -TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { - Node *mp; - if (ttisnil(key)) luaG_runerror(L, "table index is nil"); - else if (ttisnumber(key) && luai_numisnan(L, nvalue(key))) - luaG_runerror(L, "table index is NaN"); - mp = mainposition(t, key); - if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ - Node *othern; - Node *n = getfreepos(t); /* get a free place */ - if (n == NULL) { /* cannot find a free place? */ - rehash(L, t, key); /* grow table */ - /* whatever called 'newkey' take care of TM cache and GC barrier */ - return luaH_set(L, t, key); /* insert key into grown table */ - } - lua_assert(!isdummy(n)); - othern = mainposition(t, gkey(mp)); - if (othern != mp) { /* is colliding node out of its main position? */ - /* yes; move colliding node into free position */ - while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ - gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ - *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ - gnext(mp) = NULL; /* now `mp' is free */ - setnilvalue(gval(mp)); - } - else { /* colliding node is in its own main position */ - /* new node will go into free position */ - gnext(n) = gnext(mp); /* chain new position */ - gnext(mp) = n; - mp = n; - } - } - setobj2t(L, gkey(mp), key); - luaC_barrierback(L, obj2gco(t), key); - lua_assert(ttisnil(gval(mp))); - return gval(mp); -} - - -/* -** search function for integers -*/ -const TValue *luaH_getint (Table *t, int key) { - /* (1 <= key && key <= t->sizearray) */ - if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) - return &t->array[key-1]; - else { - lua_Number nk = cast_num(key); - Node *n = hashnum(t, nk); - do { /* check whether `key' is somewhere in the chain */ - if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) - return gval(n); /* that's it */ - else n = gnext(n); - } while (n); - return luaO_nilobject; - } -} - - -/* -** search function for short strings -*/ -const TValue *luaH_getstr (Table *t, TString *key) { - Node *n = hashstr(t, key); - lua_assert(key->tsv.tt == LUA_TSHRSTR); - do { /* check whether `key' is somewhere in the chain */ - if (ttisshrstring(gkey(n)) && eqshrstr(rawtsvalue(gkey(n)), key)) - return gval(n); /* that's it */ - else n = gnext(n); - } while (n); - return luaO_nilobject; -} - - -/* -** main search function -*/ -const TValue *luaH_get (Table *t, const TValue *key) { - switch (ttype(key)) { - case LUA_TSHRSTR: return luaH_getstr(t, rawtsvalue(key)); - case LUA_TNIL: return luaO_nilobject; - case LUA_TNUMBER: { - int k; - lua_Number n = nvalue(key); - lua_number2int(k, n); - if (luai_numeq(cast_num(k), n)) /* index is int? */ - return luaH_getint(t, k); /* use specialized version */ - /* else go through */ - } - default: { - Node *n = mainposition(t, key); - do { /* check whether `key' is somewhere in the chain */ - if (luaV_rawequalobj(gkey(n), key)) - return gval(n); /* that's it */ - else n = gnext(n); - } while (n); - return luaO_nilobject; - } - } -} - - -/* -** beware: when using this function you probably need to check a GC -** barrier and invalidate the TM cache. -*/ -TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { - const TValue *p = luaH_get(t, key); - if (p != luaO_nilobject) - return cast(TValue *, p); - else return luaH_newkey(L, t, key); -} - - -void luaH_setint (lua_State *L, Table *t, int key, TValue *value) { - const TValue *p = luaH_getint(t, key); - TValue *cell; - if (p != luaO_nilobject) - cell = cast(TValue *, p); - else { - TValue k; - setnvalue(&k, cast_num(key)); - cell = luaH_newkey(L, t, &k); - } - setobj2t(L, cell, value); -} - - -static int unbound_search (Table *t, unsigned int j) { - unsigned int i = j; /* i is zero or a present index */ - j++; - /* find `i' and `j' such that i is present and j is not */ - while (!ttisnil(luaH_getint(t, j))) { - i = j; - j *= 2; - if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ - /* table was built with bad purposes: resort to linear search */ - i = 1; - while (!ttisnil(luaH_getint(t, i))) i++; - return i - 1; - } - } - /* now do a binary search between them */ - while (j - i > 1) { - unsigned int m = (i+j)/2; - if (ttisnil(luaH_getint(t, m))) j = m; - else i = m; - } - return i; -} - - -/* -** Try to find a boundary in table `t'. A `boundary' is an integer index -** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). -*/ -int luaH_getn (Table *t) { - unsigned int j = t->sizearray; - if (j > 0 && ttisnil(&t->array[j - 1])) { - /* there is a boundary in the array part: (binary) search for it */ - unsigned int i = 0; - while (j - i > 1) { - unsigned int m = (i+j)/2; - if (ttisnil(&t->array[m - 1])) j = m; - else i = m; - } - return i; - } - /* else must find a boundary in hash part */ - else if (isdummy(t->node)) /* hash part is empty? */ - return j; /* that is easy... */ - else return unbound_search(t, j); -} - - - -#if defined(LUA_DEBUG) - -Node *luaH_mainposition (const Table *t, const TValue *key) { - return mainposition(t, key); -} - -int luaH_isdummy (Node *n) { return isdummy(n); } - -#endif diff --git a/contrib/lua/lua/src/ltable.h b/contrib/lua/lua/src/ltable.h deleted file mode 100644 index 2f6f5c2dc85..00000000000 --- a/contrib/lua/lua/src/ltable.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -** $Id: ltable.h,v 2.16 2011/08/17 20:26:47 roberto Exp $ -** Lua tables (hash) -** See Copyright Notice in lua.h -*/ - -#ifndef ltable_h -#define ltable_h - -#include "lobject.h" - - -#define gnode(t,i) (&(t)->node[i]) -#define gkey(n) (&(n)->i_key.tvk) -#define gval(n) (&(n)->i_val) -#define gnext(n) ((n)->i_key.nk.next) - -#define invalidateTMcache(t) ((t)->flags = 0) - - -LUAI_FUNC const TValue *luaH_getint (Table *t, int key); -LUAI_FUNC void luaH_setint (lua_State *L, Table *t, int key, TValue *value); -LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); -LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); -LUAI_FUNC TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key); -LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); -LUAI_FUNC Table *luaH_new (lua_State *L); -LUAI_FUNC void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize); -LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize); -LUAI_FUNC void luaH_free (lua_State *L, Table *t); -LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); -LUAI_FUNC int luaH_getn (Table *t); - - -#if defined(LUA_DEBUG) -LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); -LUAI_FUNC int luaH_isdummy (Node *n); -#endif - - -#endif diff --git a/contrib/lua/lua/src/ltablib.c b/contrib/lua/lua/src/ltablib.c deleted file mode 100644 index ad798b4e2aa..00000000000 --- a/contrib/lua/lua/src/ltablib.c +++ /dev/null @@ -1,283 +0,0 @@ -/* -** $Id: ltablib.c,v 1.65 2013/03/07 18:17:24 roberto Exp $ -** Library for Table Manipulation -** See Copyright Notice in lua.h -*/ - - -#include - -#define ltablib_c -#define LUA_LIB - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_len(L, n)) - - - -#if defined(LUA_COMPAT_MAXN) -static int maxn (lua_State *L) { - lua_Number max = 0; - luaL_checktype(L, 1, LUA_TTABLE); - lua_pushnil(L); /* first key */ - while (lua_next(L, 1)) { - lua_pop(L, 1); /* remove value */ - if (lua_type(L, -1) == LUA_TNUMBER) { - lua_Number v = lua_tonumber(L, -1); - if (v > max) max = v; - } - } - lua_pushnumber(L, max); - return 1; -} -#endif - - -static int tinsert (lua_State *L) { - int e = aux_getn(L, 1) + 1; /* first empty element */ - int pos; /* where to insert new element */ - switch (lua_gettop(L)) { - case 2: { /* called with only 2 arguments */ - pos = e; /* insert new element at the end */ - break; - } - case 3: { - int i; - pos = luaL_checkint(L, 2); /* 2nd argument is the position */ - luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds"); - for (i = e; i > pos; i--) { /* move up elements */ - lua_rawgeti(L, 1, i-1); - lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ - } - break; - } - default: { - return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); - } - } - lua_rawseti(L, 1, pos); /* t[pos] = v */ - return 0; -} - - -static int tremove (lua_State *L) { - int size = aux_getn(L, 1); - int pos = luaL_optint(L, 2, size); - if (pos != size) /* validate 'pos' if given */ - luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds"); - lua_rawgeti(L, 1, pos); /* result = t[pos] */ - for ( ; pos < size; pos++) { - lua_rawgeti(L, 1, pos+1); - lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */ - } - lua_pushnil(L); - lua_rawseti(L, 1, pos); /* t[pos] = nil */ - return 1; -} - - -static void addfield (lua_State *L, luaL_Buffer *b, int i) { - lua_rawgeti(L, 1, i); - if (!lua_isstring(L, -1)) - luaL_error(L, "invalid value (%s) at index %d in table for " - LUA_QL("concat"), luaL_typename(L, -1), i); - luaL_addvalue(b); -} - - -static int tconcat (lua_State *L) { - luaL_Buffer b; - size_t lsep; - int i, last; - const char *sep = luaL_optlstring(L, 2, "", &lsep); - luaL_checktype(L, 1, LUA_TTABLE); - i = luaL_optint(L, 3, 1); - last = luaL_opt(L, luaL_checkint, 4, luaL_len(L, 1)); - luaL_buffinit(L, &b); - for (; i < last; i++) { - addfield(L, &b, i); - luaL_addlstring(&b, sep, lsep); - } - if (i == last) /* add last value (if interval was not empty) */ - addfield(L, &b, i); - luaL_pushresult(&b); - return 1; -} - - -/* -** {====================================================== -** Pack/unpack -** ======================================================= -*/ - -static int pack (lua_State *L) { - int n = lua_gettop(L); /* number of elements to pack */ - lua_createtable(L, n, 1); /* create result table */ - lua_pushinteger(L, n); - lua_setfield(L, -2, "n"); /* t.n = number of elements */ - if (n > 0) { /* at least one element? */ - int i; - lua_pushvalue(L, 1); - lua_rawseti(L, -2, 1); /* insert first element */ - lua_replace(L, 1); /* move table into index 1 */ - for (i = n; i >= 2; i--) /* assign other elements */ - lua_rawseti(L, 1, i); - } - return 1; /* return table */ -} - - -static int unpack (lua_State *L) { - int i, e, n; - luaL_checktype(L, 1, LUA_TTABLE); - i = luaL_optint(L, 2, 1); - e = luaL_opt(L, luaL_checkint, 3, luaL_len(L, 1)); - if (i > e) return 0; /* empty range */ - n = e - i + 1; /* number of elements */ - if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ - return luaL_error(L, "too many results to unpack"); - lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ - while (i++ < e) /* push arg[i + 1...e] */ - lua_rawgeti(L, 1, i); - return n; -} - -/* }====================================================== */ - - - -/* -** {====================================================== -** Quicksort -** (based on `Algorithms in MODULA-3', Robert Sedgewick; -** Addison-Wesley, 1993.) -** ======================================================= -*/ - - -static void set2 (lua_State *L, int i, int j) { - lua_rawseti(L, 1, i); - lua_rawseti(L, 1, j); -} - -static int sort_comp (lua_State *L, int a, int b) { - if (!lua_isnil(L, 2)) { /* function? */ - int res; - lua_pushvalue(L, 2); - lua_pushvalue(L, a-1); /* -1 to compensate function */ - lua_pushvalue(L, b-2); /* -2 to compensate function and `a' */ - lua_call(L, 2, 1); - res = lua_toboolean(L, -1); - lua_pop(L, 1); - return res; - } - else /* a < b? */ - return lua_compare(L, a, b, LUA_OPLT); -} - -static void auxsort (lua_State *L, int l, int u) { - while (l < u) { /* for tail recursion */ - int i, j; - /* sort elements a[l], a[(l+u)/2] and a[u] */ - lua_rawgeti(L, 1, l); - lua_rawgeti(L, 1, u); - if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */ - set2(L, l, u); /* swap a[l] - a[u] */ - else - lua_pop(L, 2); - if (u-l == 1) break; /* only 2 elements */ - i = (l+u)/2; - lua_rawgeti(L, 1, i); - lua_rawgeti(L, 1, l); - if (sort_comp(L, -2, -1)) /* a[i]= P */ - while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { - if (i>=u) luaL_error(L, "invalid order function for sorting"); - lua_pop(L, 1); /* remove a[i] */ - } - /* repeat --j until a[j] <= P */ - while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { - if (j<=l) luaL_error(L, "invalid order function for sorting"); - lua_pop(L, 1); /* remove a[j] */ - } - if (j - -#define ltm_c -#define LUA_CORE - -#include "lua.h" - -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" - - -static const char udatatypename[] = "userdata"; - -LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTAGS] = { - "no value", - "nil", "boolean", udatatypename, "number", - "string", "table", "function", udatatypename, "thread", - "proto", "upval" /* these last two cases are used for tests only */ -}; - - -void luaT_init (lua_State *L) { - static const char *const luaT_eventname[] = { /* ORDER TM */ - "__index", "__newindex", - "__gc", "__mode", "__len", "__eq", - "__add", "__sub", "__mul", "__div", "__mod", - "__pow", "__unm", "__lt", "__le", - "__concat", "__call" - }; - int i; - for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); - luaS_fix(G(L)->tmname[i]); /* never collect these names */ - } -} - - -/* -** function to be used with macro "fasttm": optimized for absence of -** tag methods -*/ -const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { - const TValue *tm = luaH_getstr(events, ename); - lua_assert(event <= TM_EQ); - if (ttisnil(tm)) { /* no tag method? */ - events->flags |= cast_byte(1u<metatable; - break; - case LUA_TUSERDATA: - mt = uvalue(o)->metatable; - break; - default: - mt = G(L)->mt[ttypenv(o)]; - } - return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); -} - diff --git a/contrib/lua/lua/src/ltm.h b/contrib/lua/lua/src/ltm.h deleted file mode 100644 index 89bdc19a1e1..00000000000 --- a/contrib/lua/lua/src/ltm.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -** $Id: ltm.h,v 2.11 2011/02/28 17:32:10 roberto Exp $ -** Tag methods -** See Copyright Notice in lua.h -*/ - -#ifndef ltm_h -#define ltm_h - - -#include "lobject.h" - - -/* -* WARNING: if you change the order of this enumeration, -* grep "ORDER TM" -*/ -typedef enum { - TM_INDEX, - TM_NEWINDEX, - TM_GC, - TM_MODE, - TM_LEN, - TM_EQ, /* last tag method with `fast' access */ - TM_ADD, - TM_SUB, - TM_MUL, - TM_DIV, - TM_MOD, - TM_POW, - TM_UNM, - TM_LT, - TM_LE, - TM_CONCAT, - TM_CALL, - TM_N /* number of elements in the enum */ -} TMS; - - - -#define gfasttm(g,et,e) ((et) == NULL ? NULL : \ - ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) - -#define fasttm(l,et,e) gfasttm(G(l), et, e) - -#define ttypename(x) luaT_typenames_[(x) + 1] -#define objtypename(x) ttypename(ttypenv(x)) - -LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS]; - - -LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); -LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, - TMS event); -LUAI_FUNC void luaT_init (lua_State *L); - -#endif diff --git a/contrib/lua/lua/src/lua.c b/contrib/lua/lua/src/lua.c deleted file mode 100644 index 6a007129202..00000000000 --- a/contrib/lua/lua/src/lua.c +++ /dev/null @@ -1,497 +0,0 @@ -/* -** $Id: lua.c,v 1.206 2012/09/29 20:07:06 roberto Exp $ -** Lua stand-alone interpreter -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include -#include - -#define lua_c - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - -#if !defined(LUA_PROMPT) -#define LUA_PROMPT "> " -#define LUA_PROMPT2 ">> " -#endif - -#if !defined(LUA_PROGNAME) -#define LUA_PROGNAME "lua" -#endif - -#if !defined(LUA_MAXINPUT) -#define LUA_MAXINPUT 512 -#endif - -#if !defined(LUA_INIT) -#define LUA_INIT "LUA_INIT" -#endif - -#define LUA_INITVERSION \ - LUA_INIT "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR - - -/* -** lua_stdin_is_tty detects whether the standard input is a 'tty' (that -** is, whether we're running lua interactively). -*/ -#if defined(LUA_USE_ISATTY) -#include -#define lua_stdin_is_tty() isatty(0) -#elif defined(LUA_WIN) -#include -#include -#define lua_stdin_is_tty() _isatty(_fileno(stdin)) -#else -#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ -#endif - - -/* -** lua_readline defines how to show a prompt and then read a line from -** the standard input. -** lua_saveline defines how to "save" a read line in a "history". -** lua_freeline defines how to free a line read by lua_readline. -*/ -#if defined(LUA_USE_READLINE) - -#include -#include -#include -#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) -#define lua_saveline(L,idx) \ - if (lua_rawlen(L,idx) > 0) /* non-empty line? */ \ - add_history(lua_tostring(L, idx)); /* add it to history */ -#define lua_freeline(L,b) ((void)L, free(b)) - -#elif !defined(lua_readline) - -#define lua_readline(L,b,p) \ - ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ - fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ -#define lua_saveline(L,idx) { (void)L; (void)idx; } -#define lua_freeline(L,b) { (void)L; (void)b; } - -#endif - - - - -static lua_State *globalL = NULL; - -static const char *progname = LUA_PROGNAME; - - - -static void lstop (lua_State *L, lua_Debug *ar) { - (void)ar; /* unused arg. */ - lua_sethook(L, NULL, 0, 0); - luaL_error(L, "interrupted!"); -} - - -static void laction (int i) { - signal(i, SIG_DFL); /* if another SIGINT happens before lstop, - terminate process (default action) */ - lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); -} - - -static void print_usage (const char *badoption) { - luai_writestringerror("%s: ", progname); - if (badoption[1] == 'e' || badoption[1] == 'l') - luai_writestringerror("'%s' needs argument\n", badoption); - else - luai_writestringerror("unrecognized option '%s'\n", badoption); - luai_writestringerror( - "usage: %s [options] [script [args]]\n" - "Available options are:\n" - " -e stat execute string " LUA_QL("stat") "\n" - " -i enter interactive mode after executing " LUA_QL("script") "\n" - " -l name require library " LUA_QL("name") "\n" - " -v show version information\n" - " -E ignore environment variables\n" - " -- stop handling options\n" - " - stop handling options and execute stdin\n" - , - progname); -} - - -static void l_message (const char *pname, const char *msg) { - if (pname) luai_writestringerror("%s: ", pname); - luai_writestringerror("%s\n", msg); -} - - -static int report (lua_State *L, int status) { - if (status != LUA_OK && !lua_isnil(L, -1)) { - const char *msg = lua_tostring(L, -1); - if (msg == NULL) msg = "(error object is not a string)"; - l_message(progname, msg); - lua_pop(L, 1); - /* force a complete garbage collection in case of errors */ - lua_gc(L, LUA_GCCOLLECT, 0); - } - return status; -} - - -/* the next function is called unprotected, so it must avoid errors */ -static void finalreport (lua_State *L, int status) { - if (status != LUA_OK) { - const char *msg = (lua_type(L, -1) == LUA_TSTRING) ? lua_tostring(L, -1) - : NULL; - if (msg == NULL) msg = "(error object is not a string)"; - l_message(progname, msg); - lua_pop(L, 1); - } -} - - -static int traceback (lua_State *L) { - const char *msg = lua_tostring(L, 1); - if (msg) - luaL_traceback(L, L, msg, 1); - else if (!lua_isnoneornil(L, 1)) { /* is there an error object? */ - if (!luaL_callmeta(L, 1, "__tostring")) /* try its 'tostring' metamethod */ - lua_pushliteral(L, "(no error message)"); - } - return 1; -} - - -static int docall (lua_State *L, int narg, int nres) { - int status; - int base = lua_gettop(L) - narg; /* function index */ - lua_pushcfunction(L, traceback); /* push traceback function */ - lua_insert(L, base); /* put it under chunk and args */ - globalL = L; /* to be available to 'laction' */ - signal(SIGINT, laction); - status = lua_pcall(L, narg, nres, base); - signal(SIGINT, SIG_DFL); - lua_remove(L, base); /* remove traceback function */ - return status; -} - - -static void print_version (void) { - luai_writestring(LUA_COPYRIGHT, strlen(LUA_COPYRIGHT)); - luai_writeline(); -} - - -static int getargs (lua_State *L, char **argv, int n) { - int narg; - int i; - int argc = 0; - while (argv[argc]) argc++; /* count total number of arguments */ - narg = argc - (n + 1); /* number of arguments to the script */ - luaL_checkstack(L, narg + 3, "too many arguments to script"); - for (i=n+1; i < argc; i++) - lua_pushstring(L, argv[i]); - lua_createtable(L, narg, n + 1); - for (i=0; i < argc; i++) { - lua_pushstring(L, argv[i]); - lua_rawseti(L, -2, i - n); - } - return narg; -} - - -static int dofile (lua_State *L, const char *name) { - int status = luaL_loadfile(L, name); - if (status == LUA_OK) status = docall(L, 0, 0); - return report(L, status); -} - - -static int dostring (lua_State *L, const char *s, const char *name) { - int status = luaL_loadbuffer(L, s, strlen(s), name); - if (status == LUA_OK) status = docall(L, 0, 0); - return report(L, status); -} - - -static int dolibrary (lua_State *L, const char *name) { - int status; - lua_getglobal(L, "require"); - lua_pushstring(L, name); - status = docall(L, 1, 1); /* call 'require(name)' */ - if (status == LUA_OK) - lua_setglobal(L, name); /* global[name] = require return */ - return report(L, status); -} - - -static const char *get_prompt (lua_State *L, int firstline) { - const char *p; - lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2"); - p = lua_tostring(L, -1); - if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2); - return p; -} - -/* mark in error messages for incomplete statements */ -#define EOFMARK "" -#define marklen (sizeof(EOFMARK)/sizeof(char) - 1) - -static int incomplete (lua_State *L, int status) { - if (status == LUA_ERRSYNTAX) { - size_t lmsg; - const char *msg = lua_tolstring(L, -1, &lmsg); - if (lmsg >= marklen && strcmp(msg + lmsg - marklen, EOFMARK) == 0) { - lua_pop(L, 1); - return 1; - } - } - return 0; /* else... */ -} - - -static int pushline (lua_State *L, int firstline) { - char buffer[LUA_MAXINPUT]; - char *b = buffer; - size_t l; - const char *prmt = get_prompt(L, firstline); - int readstatus = lua_readline(L, b, prmt); - lua_pop(L, 1); /* remove result from 'get_prompt' */ - if (readstatus == 0) - return 0; /* no input */ - l = strlen(b); - if (l > 0 && b[l-1] == '\n') /* line ends with newline? */ - b[l-1] = '\0'; /* remove it */ - if (firstline && b[0] == '=') /* first line starts with `=' ? */ - lua_pushfstring(L, "return %s", b+1); /* change it to `return' */ - else - lua_pushstring(L, b); - lua_freeline(L, b); - return 1; -} - - -static int loadline (lua_State *L) { - int status; - lua_settop(L, 0); - if (!pushline(L, 1)) - return -1; /* no input */ - for (;;) { /* repeat until gets a complete line */ - size_t l; - const char *line = lua_tolstring(L, 1, &l); - status = luaL_loadbuffer(L, line, l, "=stdin"); - if (!incomplete(L, status)) break; /* cannot try to add lines? */ - if (!pushline(L, 0)) /* no more input? */ - return -1; - lua_pushliteral(L, "\n"); /* add a new line... */ - lua_insert(L, -2); /* ...between the two lines */ - lua_concat(L, 3); /* join them */ - } - lua_saveline(L, 1); - lua_remove(L, 1); /* remove line */ - return status; -} - - -static void dotty (lua_State *L) { - int status; - const char *oldprogname = progname; - progname = NULL; - while ((status = loadline(L)) != -1) { - if (status == LUA_OK) status = docall(L, 0, LUA_MULTRET); - report(L, status); - if (status == LUA_OK && lua_gettop(L) > 0) { /* any result to print? */ - luaL_checkstack(L, LUA_MINSTACK, "too many results to print"); - lua_getglobal(L, "print"); - lua_insert(L, 1); - if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != LUA_OK) - l_message(progname, lua_pushfstring(L, - "error calling " LUA_QL("print") " (%s)", - lua_tostring(L, -1))); - } - } - lua_settop(L, 0); /* clear stack */ - luai_writeline(); - progname = oldprogname; -} - - -static int handle_script (lua_State *L, char **argv, int n) { - int status; - const char *fname; - int narg = getargs(L, argv, n); /* collect arguments */ - lua_setglobal(L, "arg"); - fname = argv[n]; - if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0) - fname = NULL; /* stdin */ - status = luaL_loadfile(L, fname); - lua_insert(L, -(narg+1)); - if (status == LUA_OK) - status = docall(L, narg, LUA_MULTRET); - else - lua_pop(L, narg); - return report(L, status); -} - - -/* check that argument has no extra characters at the end */ -#define noextrachars(x) {if ((x)[2] != '\0') return -1;} - - -/* indices of various argument indicators in array args */ -#define has_i 0 /* -i */ -#define has_v 1 /* -v */ -#define has_e 2 /* -e */ -#define has_E 3 /* -E */ - -#define num_has 4 /* number of 'has_*' */ - - -static int collectargs (char **argv, int *args) { - int i; - for (i = 1; argv[i] != NULL; i++) { - if (argv[i][0] != '-') /* not an option? */ - return i; - switch (argv[i][1]) { /* option */ - case '-': - noextrachars(argv[i]); - return (argv[i+1] != NULL ? i+1 : 0); - case '\0': - return i; - case 'E': - args[has_E] = 1; - break; - case 'i': - noextrachars(argv[i]); - args[has_i] = 1; /* go through */ - case 'v': - noextrachars(argv[i]); - args[has_v] = 1; - break; - case 'e': - args[has_e] = 1; /* go through */ - case 'l': /* both options need an argument */ - if (argv[i][2] == '\0') { /* no concatenated argument? */ - i++; /* try next 'argv' */ - if (argv[i] == NULL || argv[i][0] == '-') - return -(i - 1); /* no next argument or it is another option */ - } - break; - default: /* invalid option; return its index... */ - return -i; /* ...as a negative value */ - } - } - return 0; -} - - -static int runargs (lua_State *L, char **argv, int n) { - int i; - for (i = 1; i < n; i++) { - lua_assert(argv[i][0] == '-'); - switch (argv[i][1]) { /* option */ - case 'e': { - const char *chunk = argv[i] + 2; - if (*chunk == '\0') chunk = argv[++i]; - lua_assert(chunk != NULL); - if (dostring(L, chunk, "=(command line)") != LUA_OK) - return 0; - break; - } - case 'l': { - const char *filename = argv[i] + 2; - if (*filename == '\0') filename = argv[++i]; - lua_assert(filename != NULL); - if (dolibrary(L, filename) != LUA_OK) - return 0; /* stop if file fails */ - break; - } - default: break; - } - } - return 1; -} - - -static int handle_luainit (lua_State *L) { - const char *name = "=" LUA_INITVERSION; - const char *init = getenv(name + 1); - if (init == NULL) { - name = "=" LUA_INIT; - init = getenv(name + 1); /* try alternative name */ - } - if (init == NULL) return LUA_OK; - else if (init[0] == '@') - return dofile(L, init+1); - else - return dostring(L, init, name); -} - - -static int pmain (lua_State *L) { - int argc = (int)lua_tointeger(L, 1); - char **argv = (char **)lua_touserdata(L, 2); - int script; - int args[num_has]; - args[has_i] = args[has_v] = args[has_e] = args[has_E] = 0; - if (argv[0] && argv[0][0]) progname = argv[0]; - script = collectargs(argv, args); - if (script < 0) { /* invalid arg? */ - print_usage(argv[-script]); - return 0; - } - if (args[has_v]) print_version(); - if (args[has_E]) { /* option '-E'? */ - lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */ - lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); - } - /* open standard libraries */ - luaL_checkversion(L); - lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */ - luaL_openlibs(L); /* open libraries */ - lua_gc(L, LUA_GCRESTART, 0); - if (!args[has_E] && handle_luainit(L) != LUA_OK) - return 0; /* error running LUA_INIT */ - /* execute arguments -e and -l */ - if (!runargs(L, argv, (script > 0) ? script : argc)) return 0; - /* execute main script (if there is one) */ - if (script && handle_script(L, argv, script) != LUA_OK) return 0; - if (args[has_i]) /* -i option? */ - dotty(L); - else if (script == 0 && !args[has_e] && !args[has_v]) { /* no arguments? */ - if (lua_stdin_is_tty()) { - print_version(); - dotty(L); - } - else dofile(L, NULL); /* executes stdin as a file */ - } - lua_pushboolean(L, 1); /* signal no errors */ - return 1; -} - - -int main (int argc, char **argv) { - int status, result; - lua_State *L = luaL_newstate(); /* create state */ - if (L == NULL) { - l_message(argv[0], "cannot create state: not enough memory"); - return EXIT_FAILURE; - } - /* call 'pmain' in protected mode */ - lua_pushcfunction(L, &pmain); - lua_pushinteger(L, argc); /* 1st argument */ - lua_pushlightuserdata(L, argv); /* 2nd argument */ - status = lua_pcall(L, 2, 1, 0); - result = lua_toboolean(L, -1); /* get result */ - finalreport(L, status); - lua_close(L); - return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE; -} - diff --git a/contrib/lua/lua/src/lua.h b/contrib/lua/lua/src/lua.h deleted file mode 100644 index eb0482b8f47..00000000000 --- a/contrib/lua/lua/src/lua.h +++ /dev/null @@ -1,444 +0,0 @@ -/* -** $Id: lua.h,v 1.285 2013/03/15 13:04:22 roberto Exp $ -** Lua - A Scripting Language -** Lua.org, PUC-Rio, Brazil (http://www.lua.org) -** See Copyright Notice at the end of this file -*/ - - -#ifndef lua_h -#define lua_h - -#include -#include - - -#include "luaconf.h" - - -#define LUA_VERSION_MAJOR "5" -#define LUA_VERSION_MINOR "2" -#define LUA_VERSION_NUM 502 -#define LUA_VERSION_RELEASE "2" - -#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR -#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE -#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2013 Lua.org, PUC-Rio" -#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" - - -/* mark for precompiled code ('Lua') */ -#define LUA_SIGNATURE "\033Lua" - -/* option for multiple returns in 'lua_pcall' and 'lua_call' */ -#define LUA_MULTRET (-1) - - -/* -** pseudo-indices -*/ -#define LUA_REGISTRYINDEX LUAI_FIRSTPSEUDOIDX -#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) - - -/* thread status */ -#define LUA_OK 0 -#define LUA_YIELD 1 -#define LUA_ERRRUN 2 -#define LUA_ERRSYNTAX 3 -#define LUA_ERRMEM 4 -#define LUA_ERRGCMM 5 -#define LUA_ERRERR 6 - - -typedef struct lua_State lua_State; - -typedef int (*lua_CFunction) (lua_State *L); - - -/* -** functions that read/write blocks when loading/dumping Lua chunks -*/ -typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); - -typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); - - -/* -** prototype for memory-allocation functions -*/ -typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); - - -/* -** basic types -*/ -#define LUA_TNONE (-1) - -#define LUA_TNIL 0 -#define LUA_TBOOLEAN 1 -#define LUA_TLIGHTUSERDATA 2 -#define LUA_TNUMBER 3 -#define LUA_TSTRING 4 -#define LUA_TTABLE 5 -#define LUA_TFUNCTION 6 -#define LUA_TUSERDATA 7 -#define LUA_TTHREAD 8 - -#define LUA_NUMTAGS 9 - - - -/* minimum Lua stack available to a C function */ -#define LUA_MINSTACK 20 - - -/* predefined values in the registry */ -#define LUA_RIDX_MAINTHREAD 1 -#define LUA_RIDX_GLOBALS 2 -#define LUA_RIDX_LAST LUA_RIDX_GLOBALS - - -/* type of numbers in Lua */ -typedef LUA_NUMBER lua_Number; - - -/* type for integer functions */ -typedef LUA_INTEGER lua_Integer; - -/* unsigned integer type */ -typedef LUA_UNSIGNED lua_Unsigned; - - - -/* -** generic extra include file -*/ -#if defined(LUA_USER_H) -#include LUA_USER_H -#endif - - -/* -** RCS ident string -*/ -extern const char lua_ident[]; - - -/* -** state manipulation -*/ -LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); -LUA_API void (lua_close) (lua_State *L); -LUA_API lua_State *(lua_newthread) (lua_State *L); - -LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); - - -LUA_API const lua_Number *(lua_version) (lua_State *L); - - -/* -** basic stack manipulation -*/ -LUA_API int (lua_absindex) (lua_State *L, int idx); -LUA_API int (lua_gettop) (lua_State *L); -LUA_API void (lua_settop) (lua_State *L, int idx); -LUA_API void (lua_pushvalue) (lua_State *L, int idx); -LUA_API void (lua_remove) (lua_State *L, int idx); -LUA_API void (lua_insert) (lua_State *L, int idx); -LUA_API void (lua_replace) (lua_State *L, int idx); -LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx); -LUA_API int (lua_checkstack) (lua_State *L, int sz); - -LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); - - -/* -** access functions (stack -> C) -*/ - -LUA_API int (lua_isnumber) (lua_State *L, int idx); -LUA_API int (lua_isstring) (lua_State *L, int idx); -LUA_API int (lua_iscfunction) (lua_State *L, int idx); -LUA_API int (lua_isuserdata) (lua_State *L, int idx); -LUA_API int (lua_type) (lua_State *L, int idx); -LUA_API const char *(lua_typename) (lua_State *L, int tp); - -LUA_API lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum); -LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum); -LUA_API lua_Unsigned (lua_tounsignedx) (lua_State *L, int idx, int *isnum); -LUA_API int (lua_toboolean) (lua_State *L, int idx); -LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); -LUA_API size_t (lua_rawlen) (lua_State *L, int idx); -LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); -LUA_API void *(lua_touserdata) (lua_State *L, int idx); -LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); -LUA_API const void *(lua_topointer) (lua_State *L, int idx); - - -/* -** Comparison and arithmetic functions -*/ - -#define LUA_OPADD 0 /* ORDER TM */ -#define LUA_OPSUB 1 -#define LUA_OPMUL 2 -#define LUA_OPDIV 3 -#define LUA_OPMOD 4 -#define LUA_OPPOW 5 -#define LUA_OPUNM 6 - -LUA_API void (lua_arith) (lua_State *L, int op); - -#define LUA_OPEQ 0 -#define LUA_OPLT 1 -#define LUA_OPLE 2 - -LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); -LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op); - - -/* -** push functions (C -> stack) -*/ -LUA_API void (lua_pushnil) (lua_State *L); -LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); -LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); -LUA_API void (lua_pushunsigned) (lua_State *L, lua_Unsigned n); -LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t l); -LUA_API const char *(lua_pushstring) (lua_State *L, const char *s); -LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, - va_list argp); -LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); -LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); -LUA_API void (lua_pushboolean) (lua_State *L, int b); -LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); -LUA_API int (lua_pushthread) (lua_State *L); - - -/* -** get functions (Lua -> stack) -*/ -LUA_API void (lua_getglobal) (lua_State *L, const char *var); -LUA_API void (lua_gettable) (lua_State *L, int idx); -LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); -LUA_API void (lua_rawget) (lua_State *L, int idx); -LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); -LUA_API void (lua_rawgetp) (lua_State *L, int idx, const void *p); -LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); -LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); -LUA_API int (lua_getmetatable) (lua_State *L, int objindex); -LUA_API void (lua_getuservalue) (lua_State *L, int idx); - - -/* -** set functions (stack -> Lua) -*/ -LUA_API void (lua_setglobal) (lua_State *L, const char *var); -LUA_API void (lua_settable) (lua_State *L, int idx); -LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); -LUA_API void (lua_rawset) (lua_State *L, int idx); -LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); -LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p); -LUA_API int (lua_setmetatable) (lua_State *L, int objindex); -LUA_API void (lua_setuservalue) (lua_State *L, int idx); - - -/* -** 'load' and 'call' functions (load and run Lua code) -*/ -LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, int ctx, - lua_CFunction k); -#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) - -LUA_API int (lua_getctx) (lua_State *L, int *ctx); - -LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, - int ctx, lua_CFunction k); -#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) - -LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, - const char *chunkname, - const char *mode); - -LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); - - -/* -** coroutine functions -*/ -LUA_API int (lua_yieldk) (lua_State *L, int nresults, int ctx, - lua_CFunction k); -#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) -LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg); -LUA_API int (lua_status) (lua_State *L); - -/* -** garbage-collection function and options -*/ - -#define LUA_GCSTOP 0 -#define LUA_GCRESTART 1 -#define LUA_GCCOLLECT 2 -#define LUA_GCCOUNT 3 -#define LUA_GCCOUNTB 4 -#define LUA_GCSTEP 5 -#define LUA_GCSETPAUSE 6 -#define LUA_GCSETSTEPMUL 7 -#define LUA_GCSETMAJORINC 8 -#define LUA_GCISRUNNING 9 -#define LUA_GCGEN 10 -#define LUA_GCINC 11 - -LUA_API int (lua_gc) (lua_State *L, int what, int data); - - -/* -** miscellaneous functions -*/ - -LUA_API int (lua_error) (lua_State *L); - -LUA_API int (lua_next) (lua_State *L, int idx); - -LUA_API void (lua_concat) (lua_State *L, int n); -LUA_API void (lua_len) (lua_State *L, int idx); - -LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); -LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); - - - -/* -** =============================================================== -** some useful macros -** =============================================================== -*/ - -#define lua_tonumber(L,i) lua_tonumberx(L,i,NULL) -#define lua_tointeger(L,i) lua_tointegerx(L,i,NULL) -#define lua_tounsigned(L,i) lua_tounsignedx(L,i,NULL) - -#define lua_pop(L,n) lua_settop(L, -(n)-1) - -#define lua_newtable(L) lua_createtable(L, 0, 0) - -#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) - -#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) - -#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) -#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) -#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) -#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) -#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) -#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) -#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) -#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) - -#define lua_pushliteral(L, s) \ - lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) - -#define lua_pushglobaltable(L) \ - lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS) - -#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) - - - -/* -** {====================================================================== -** Debug API -** ======================================================================= -*/ - - -/* -** Event codes -*/ -#define LUA_HOOKCALL 0 -#define LUA_HOOKRET 1 -#define LUA_HOOKLINE 2 -#define LUA_HOOKCOUNT 3 -#define LUA_HOOKTAILCALL 4 - - -/* -** Event masks -*/ -#define LUA_MASKCALL (1 << LUA_HOOKCALL) -#define LUA_MASKRET (1 << LUA_HOOKRET) -#define LUA_MASKLINE (1 << LUA_HOOKLINE) -#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) - -typedef struct lua_Debug lua_Debug; /* activation record */ - - -/* Functions to be called by the debugger in specific events */ -typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); - - -LUA_API int (lua_getstack) (lua_State *L, int level, lua_Debug *ar); -LUA_API int (lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar); -LUA_API const char *(lua_getlocal) (lua_State *L, const lua_Debug *ar, int n); -LUA_API const char *(lua_setlocal) (lua_State *L, const lua_Debug *ar, int n); -LUA_API const char *(lua_getupvalue) (lua_State *L, int funcindex, int n); -LUA_API const char *(lua_setupvalue) (lua_State *L, int funcindex, int n); - -LUA_API void *(lua_upvalueid) (lua_State *L, int fidx, int n); -LUA_API void (lua_upvaluejoin) (lua_State *L, int fidx1, int n1, - int fidx2, int n2); - -LUA_API int (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count); -LUA_API lua_Hook (lua_gethook) (lua_State *L); -LUA_API int (lua_gethookmask) (lua_State *L); -LUA_API int (lua_gethookcount) (lua_State *L); - - -struct lua_Debug { - int event; - const char *name; /* (n) */ - const char *namewhat; /* (n) 'global', 'local', 'field', 'method' */ - const char *what; /* (S) 'Lua', 'C', 'main', 'tail' */ - const char *source; /* (S) */ - int currentline; /* (l) */ - int linedefined; /* (S) */ - int lastlinedefined; /* (S) */ - unsigned char nups; /* (u) number of upvalues */ - unsigned char nparams;/* (u) number of parameters */ - char isvararg; /* (u) */ - char istailcall; /* (t) */ - char short_src[LUA_IDSIZE]; /* (S) */ - /* private part */ - struct CallInfo *i_ci; /* active function */ -}; - -/* }====================================================================== */ - - -/****************************************************************************** -* Copyright (C) 1994-2013 Lua.org, PUC-Rio. -* -* Permission is hereby granted, free of charge, to any person obtaining -* a copy of this software and associated documentation files (the -* "Software"), to deal in the Software without restriction, including -* without limitation the rights to use, copy, modify, merge, publish, -* distribute, sublicense, and/or sell copies of the Software, and to -* permit persons to whom the Software is furnished to do so, subject to -* the following conditions: -* -* The above copyright notice and this permission notice shall be -* included in all copies or substantial portions of the Software. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -******************************************************************************/ - - -#endif diff --git a/contrib/lua/lua/src/lua.hpp b/contrib/lua/lua/src/lua.hpp deleted file mode 100644 index ec417f59469..00000000000 --- a/contrib/lua/lua/src/lua.hpp +++ /dev/null @@ -1,9 +0,0 @@ -// lua.hpp -// Lua header files for C++ -// <> not supplied automatically because Lua also compiles as C++ - -extern "C" { -#include "lua.h" -#include "lualib.h" -#include "lauxlib.h" -} diff --git a/contrib/lua/lua/src/luac.c b/contrib/lua/lua/src/luac.c deleted file mode 100644 index 5081836d4cb..00000000000 --- a/contrib/lua/lua/src/luac.c +++ /dev/null @@ -1,432 +0,0 @@ -/* -** $Id: luac.c,v 1.69 2011/11/29 17:46:33 lhf Exp $ -** Lua compiler (saves bytecodes to files; also list bytecodes) -** See Copyright Notice in lua.h -*/ - -#include -#include -#include -#include - -#define luac_c -#define LUA_CORE - -#include "lua.h" -#include "lauxlib.h" - -#include "lobject.h" -#include "lstate.h" -#include "lundump.h" - -static void PrintFunction(const Proto* f, int full); -#define luaU_print PrintFunction - -#define PROGNAME "luac" /* default program name */ -#define OUTPUT PROGNAME ".out" /* default output file */ - -static int listing=0; /* list bytecodes? */ -static int dumping=1; /* dump bytecodes? */ -static int stripping=0; /* strip debug information? */ -static char Output[]={ OUTPUT }; /* default output file name */ -static const char* output=Output; /* actual output file name */ -static const char* progname=PROGNAME; /* actual program name */ - -static void fatal(const char* message) -{ - fprintf(stderr,"%s: %s\n",progname,message); - exit(EXIT_FAILURE); -} - -static void cannot(const char* what) -{ - fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno)); - exit(EXIT_FAILURE); -} - -static void usage(const char* message) -{ - if (*message=='-') - fprintf(stderr,"%s: unrecognized option " LUA_QS "\n",progname,message); - else - fprintf(stderr,"%s: %s\n",progname,message); - fprintf(stderr, - "usage: %s [options] [filenames]\n" - "Available options are:\n" - " -l list (use -l -l for full listing)\n" - " -o name output to file " LUA_QL("name") " (default is \"%s\")\n" - " -p parse only\n" - " -s strip debug information\n" - " -v show version information\n" - " -- stop handling options\n" - " - stop handling options and process stdin\n" - ,progname,Output); - exit(EXIT_FAILURE); -} - -#define IS(s) (strcmp(argv[i],s)==0) - -static int doargs(int argc, char* argv[]) -{ - int i; - int version=0; - if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0]; - for (i=1; itop+(i)) - -static const Proto* combine(lua_State* L, int n) -{ - if (n==1) - return toproto(L,-1); - else - { - Proto* f; - int i=n; - if (lua_load(L,reader,&i,"=(" PROGNAME ")",NULL)!=LUA_OK) fatal(lua_tostring(L,-1)); - f=toproto(L,-1); - for (i=0; ip[i]=toproto(L,i-n-1); - if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0; - } - f->sizelineinfo=0; - return f; - } -} - -static int writer(lua_State* L, const void* p, size_t size, void* u) -{ - UNUSED(L); - return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0); -} - -static int pmain(lua_State* L) -{ - int argc=(int)lua_tointeger(L,1); - char** argv=(char**)lua_touserdata(L,2); - const Proto* f; - int i; - if (!lua_checkstack(L,argc)) fatal("too many input files"); - for (i=0; i1); - if (dumping) - { - FILE* D= (output==NULL) ? stdout : fopen(output,"wb"); - if (D==NULL) cannot("open"); - lua_lock(L); - luaU_dump(L,f,writer,D,stripping); - lua_unlock(L); - if (ferror(D)) cannot("write"); - if (fclose(D)) cannot("close"); - } - return 0; -} - -int main(int argc, char* argv[]) -{ - lua_State* L; - int i=doargs(argc,argv); - argc-=i; argv+=i; - if (argc<=0) usage("no input files given"); - L=luaL_newstate(); - if (L==NULL) fatal("cannot create state: not enough memory"); - lua_pushcfunction(L,&pmain); - lua_pushinteger(L,argc); - lua_pushlightuserdata(L,argv); - if (lua_pcall(L,2,0,0)!=LUA_OK) fatal(lua_tostring(L,-1)); - lua_close(L); - return EXIT_SUCCESS; -} - -/* -** $Id: print.c,v 1.68 2011/09/30 10:21:20 lhf Exp $ -** print bytecodes -** See Copyright Notice in lua.h -*/ - -#include -#include - -#define luac_c -#define LUA_CORE - -#include "ldebug.h" -#include "lobject.h" -#include "lopcodes.h" - -#define VOID(p) ((const void*)(p)) - -static void PrintString(const TString* ts) -{ - const char* s=getstr(ts); - size_t i,n=ts->tsv.len; - printf("%c",'"'); - for (i=0; ik[i]; - switch (ttype(o)) - { - case LUA_TNIL: - printf("nil"); - break; - case LUA_TBOOLEAN: - printf(bvalue(o) ? "true" : "false"); - break; - case LUA_TNUMBER: - printf(LUA_NUMBER_FMT,nvalue(o)); - break; - case LUA_TSTRING: - PrintString(rawtsvalue(o)); - break; - default: /* cannot happen */ - printf("? type=%d",ttype(o)); - break; - } -} - -#define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-") -#define MYK(x) (-1-(x)) - -static void PrintCode(const Proto* f) -{ - const Instruction* code=f->code; - int pc,n=f->sizecode; - for (pc=0; pc0) printf("[%d]\t",line); else printf("[-]\t"); - printf("%-9s\t",luaP_opnames[o]); - switch (getOpMode(o)) - { - case iABC: - printf("%d",a); - if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (MYK(INDEXK(b))) : b); - if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (MYK(INDEXK(c))) : c); - break; - case iABx: - printf("%d",a); - if (getBMode(o)==OpArgK) printf(" %d",MYK(bx)); - if (getBMode(o)==OpArgU) printf(" %d",bx); - break; - case iAsBx: - printf("%d %d",a,sbx); - break; - case iAx: - printf("%d",MYK(ax)); - break; - } - switch (o) - { - case OP_LOADK: - printf("\t; "); PrintConstant(f,bx); - break; - case OP_GETUPVAL: - case OP_SETUPVAL: - printf("\t; %s",UPVALNAME(b)); - break; - case OP_GETTABUP: - printf("\t; %s",UPVALNAME(b)); - if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } - break; - case OP_SETTABUP: - printf("\t; %s",UPVALNAME(a)); - if (ISK(b)) { printf(" "); PrintConstant(f,INDEXK(b)); } - if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } - break; - case OP_GETTABLE: - case OP_SELF: - if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); } - break; - case OP_SETTABLE: - case OP_ADD: - case OP_SUB: - case OP_MUL: - case OP_DIV: - case OP_POW: - case OP_EQ: - case OP_LT: - case OP_LE: - if (ISK(b) || ISK(c)) - { - printf("\t; "); - if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-"); - printf(" "); - if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-"); - } - break; - case OP_JMP: - case OP_FORLOOP: - case OP_FORPREP: - case OP_TFORLOOP: - printf("\t; to %d",sbx+pc+2); - break; - case OP_CLOSURE: - printf("\t; %p",VOID(f->p[bx])); - break; - case OP_SETLIST: - if (c==0) printf("\t; %d",(int)code[++pc]); else printf("\t; %d",c); - break; - case OP_EXTRAARG: - printf("\t; "); PrintConstant(f,ax); - break; - default: - break; - } - printf("\n"); - } -} - -#define SS(x) ((x==1)?"":"s") -#define S(x) (int)(x),SS(x) - -static void PrintHeader(const Proto* f) -{ - const char* s=f->source ? getstr(f->source) : "=?"; - if (*s=='@' || *s=='=') - s++; - else if (*s==LUA_SIGNATURE[0]) - s="(bstring)"; - else - s="(string)"; - printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n", - (f->linedefined==0)?"main":"function",s, - f->linedefined,f->lastlinedefined, - S(f->sizecode),VOID(f)); - printf("%d%s param%s, %d slot%s, %d upvalue%s, ", - (int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams), - S(f->maxstacksize),S(f->sizeupvalues)); - printf("%d local%s, %d constant%s, %d function%s\n", - S(f->sizelocvars),S(f->sizek),S(f->sizep)); -} - -static void PrintDebug(const Proto* f) -{ - int i,n; - n=f->sizek; - printf("constants (%d) for %p:\n",n,VOID(f)); - for (i=0; isizelocvars; - printf("locals (%d) for %p:\n",n,VOID(f)); - for (i=0; ilocvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1); - } - n=f->sizeupvalues; - printf("upvalues (%d) for %p:\n",n,VOID(f)); - for (i=0; iupvalues[i].instack,f->upvalues[i].idx); - } -} - -static void PrintFunction(const Proto* f, int full) -{ - int i,n=f->sizep; - PrintHeader(f); - PrintCode(f); - if (full) PrintDebug(f); - for (i=0; ip[i],full); -} diff --git a/contrib/lua/lua/src/luaconf.h b/contrib/lua/lua/src/luaconf.h deleted file mode 100644 index df802c9526f..00000000000 --- a/contrib/lua/lua/src/luaconf.h +++ /dev/null @@ -1,551 +0,0 @@ -/* -** $Id: luaconf.h,v 1.176 2013/03/16 21:10:18 roberto Exp $ -** Configuration file for Lua -** See Copyright Notice in lua.h -*/ - - -#ifndef lconfig_h -#define lconfig_h - -#include -#include - - -/* -** ================================================================== -** Search for "@@" to find all configurable definitions. -** =================================================================== -*/ - - -/* -@@ LUA_ANSI controls the use of non-ansi features. -** CHANGE it (define it) if you want Lua to avoid the use of any -** non-ansi feature or library. -*/ -#if !defined(LUA_ANSI) && defined(__STRICT_ANSI__) -#define LUA_ANSI -#endif - - -#if !defined(LUA_ANSI) && defined(_WIN32) && !defined(_WIN32_WCE) -#define LUA_WIN /* enable goodies for regular Windows platforms */ -#endif - -#if defined(LUA_WIN) -#define LUA_DL_DLL -#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ -#endif - - - -#if defined(LUA_USE_LINUX) -#define LUA_USE_POSIX -#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ -#define LUA_USE_READLINE /* needs some extra libraries */ -#define LUA_USE_STRTODHEX /* assume 'strtod' handles hex formats */ -#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ -#define LUA_USE_LONGLONG /* assume support for long long */ -#endif - -#if defined(LUA_USE_MACOSX) -#define LUA_USE_POSIX -#define LUA_USE_DLOPEN /* does not need -ldl */ -#define LUA_USE_READLINE /* needs an extra library: -lreadline */ -#define LUA_USE_STRTODHEX /* assume 'strtod' handles hex formats */ -#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ -#define LUA_USE_LONGLONG /* assume support for long long */ -#endif - - - -/* -@@ LUA_USE_POSIX includes all functionality listed as X/Open System -@* Interfaces Extension (XSI). -** CHANGE it (define it) if your system is XSI compatible. -*/ -#if defined(LUA_USE_POSIX) -#define LUA_USE_MKSTEMP -#define LUA_USE_ISATTY -#define LUA_USE_POPEN -#define LUA_USE_ULONGJMP -#define LUA_USE_GMTIME_R -#endif - - - -/* -@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for -@* Lua libraries. -@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for -@* C libraries. -** CHANGE them if your machine has a non-conventional directory -** hierarchy or if you want to install your libraries in -** non-conventional directories. -*/ -#if defined(_WIN32) /* { */ -/* -** In Windows, any exclamation mark ('!') in the path is replaced by the -** path of the directory of the executable file of the current process. -*/ -#define LUA_LDIR "!\\lua\\" -#define LUA_CDIR "!\\" -#define LUA_PATH_DEFAULT \ - LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ - LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" ".\\?.lua" -#define LUA_CPATH_DEFAULT \ - LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll;" ".\\?.dll" - -#else /* }{ */ - -#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR "/" -#define LUA_ROOT "/usr/local/" -#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR -#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR -#define LUA_PATH_DEFAULT \ - LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ - LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" "./?.lua" -#define LUA_CPATH_DEFAULT \ - LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" -#endif /* } */ - - -/* -@@ LUA_DIRSEP is the directory separator (for submodules). -** CHANGE it if your machine does not use "/" as the directory separator -** and is not Windows. (On Windows Lua automatically uses "\".) -*/ -#if defined(_WIN32) -#define LUA_DIRSEP "\\" -#else -#define LUA_DIRSEP "/" -#endif - - -/* -@@ LUA_ENV is the name of the variable that holds the current -@@ environment, used to access global names. -** CHANGE it if you do not like this name. -*/ -#define LUA_ENV "_ENV" - - -/* -@@ LUA_API is a mark for all core API functions. -@@ LUALIB_API is a mark for all auxiliary library functions. -@@ LUAMOD_API is a mark for all standard library opening functions. -** CHANGE them if you need to define those functions in some special way. -** For instance, if you want to create one Windows DLL with the core and -** the libraries, you may want to use the following definition (define -** LUA_BUILD_AS_DLL to get it). -*/ -#if defined(LUA_BUILD_AS_DLL) /* { */ - -#if defined(LUA_CORE) || defined(LUA_LIB) /* { */ -#define LUA_API __declspec(dllexport) -#else /* }{ */ -#define LUA_API __declspec(dllimport) -#endif /* } */ - -#else /* }{ */ - -#define LUA_API extern - -#endif /* } */ - - -/* more often than not the libs go together with the core */ -#define LUALIB_API LUA_API -#define LUAMOD_API LUALIB_API - - -/* -@@ LUAI_FUNC is a mark for all extern functions that are not to be -@* exported to outside modules. -@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables -@* that are not to be exported to outside modules (LUAI_DDEF for -@* definitions and LUAI_DDEC for declarations). -** CHANGE them if you need to mark them in some special way. Elf/gcc -** (versions 3.2 and later) mark them as "hidden" to optimize access -** when Lua is compiled as a shared library. Not all elf targets support -** this attribute. Unfortunately, gcc does not offer a way to check -** whether the target offers that support, and those without support -** give a warning about it. To avoid these warnings, change to the -** default definition. -*/ -#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ - defined(__ELF__) /* { */ -#define LUAI_FUNC __attribute__((visibility("hidden"))) extern -#define LUAI_DDEC LUAI_FUNC -#define LUAI_DDEF /* empty */ - -#else /* }{ */ -#define LUAI_FUNC extern -#define LUAI_DDEC extern -#define LUAI_DDEF /* empty */ -#endif /* } */ - - - -/* -@@ LUA_QL describes how error messages quote program elements. -** CHANGE it if you want a different appearance. -*/ -#define LUA_QL(x) "'" x "'" -#define LUA_QS LUA_QL("%s") - - -/* -@@ LUA_IDSIZE gives the maximum size for the description of the source -@* of a function in debug information. -** CHANGE it if you want a different size. -*/ -#define LUA_IDSIZE 60 - - -/* -@@ luai_writestring/luai_writeline define how 'print' prints its results. -** They are only used in libraries and the stand-alone program. (The #if -** avoids including 'stdio.h' everywhere.) -*/ -#if defined(LUA_LIB) || defined(lua_c) -#include -#define luai_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) -#define luai_writeline() (luai_writestring("\n", 1), fflush(stdout)) -#endif - -/* -@@ luai_writestringerror defines how to print error messages. -** (A format string with one argument is enough for Lua...) -*/ -#define luai_writestringerror(s,p) \ - (fprintf(stderr, (s), (p)), fflush(stderr)) - - -/* -@@ LUAI_MAXSHORTLEN is the maximum length for short strings, that is, -** strings that are internalized. (Cannot be smaller than reserved words -** or tags for metamethods, as these strings must be internalized; -** #("function") = 8, #("__newindex") = 10.) -*/ -#define LUAI_MAXSHORTLEN 40 - - - -/* -** {================================================================== -** Compatibility with previous versions -** =================================================================== -*/ - -/* -@@ LUA_COMPAT_ALL controls all compatibility options. -** You can define it to get all options, or change specific options -** to fit your specific needs. -*/ -#if defined(LUA_COMPAT_ALL) /* { */ - -/* -@@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'. -** You can replace it with 'table.unpack'. -*/ -#define LUA_COMPAT_UNPACK - -/* -@@ LUA_COMPAT_LOADERS controls the presence of table 'package.loaders'. -** You can replace it with 'package.searchers'. -*/ -#define LUA_COMPAT_LOADERS - -/* -@@ macro 'lua_cpcall' emulates deprecated function lua_cpcall. -** You can call your C function directly (with light C functions). -*/ -#define lua_cpcall(L,f,u) \ - (lua_pushcfunction(L, (f)), \ - lua_pushlightuserdata(L,(u)), \ - lua_pcall(L,1,0,0)) - - -/* -@@ LUA_COMPAT_LOG10 defines the function 'log10' in the math library. -** You can rewrite 'log10(x)' as 'log(x, 10)'. -*/ -#define LUA_COMPAT_LOG10 - -/* -@@ LUA_COMPAT_LOADSTRING defines the function 'loadstring' in the base -** library. You can rewrite 'loadstring(s)' as 'load(s)'. -*/ -#define LUA_COMPAT_LOADSTRING - -/* -@@ LUA_COMPAT_MAXN defines the function 'maxn' in the table library. -*/ -#define LUA_COMPAT_MAXN - -/* -@@ The following macros supply trivial compatibility for some -** changes in the API. The macros themselves document how to -** change your code to avoid using them. -*/ -#define lua_strlen(L,i) lua_rawlen(L, (i)) - -#define lua_objlen(L,i) lua_rawlen(L, (i)) - -#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) -#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT) - -/* -@@ LUA_COMPAT_MODULE controls compatibility with previous -** module functions 'module' (Lua) and 'luaL_register' (C). -*/ -#define LUA_COMPAT_MODULE - -#endif /* } */ - -/* }================================================================== */ - - - -/* -@@ LUAI_BITSINT defines the number of bits in an int. -** CHANGE here if Lua cannot automatically detect the number of bits of -** your machine. Probably you do not need to change this. -*/ -/* avoid overflows in comparison */ -#if INT_MAX-20 < 32760 /* { */ -#define LUAI_BITSINT 16 -#elif INT_MAX > 2147483640L /* }{ */ -/* int has at least 32 bits */ -#define LUAI_BITSINT 32 -#else /* }{ */ -#error "you must define LUA_BITSINT with number of bits in an integer" -#endif /* } */ - - -/* -@@ LUA_INT32 is an signed integer with exactly 32 bits. -@@ LUAI_UMEM is an unsigned integer big enough to count the total -@* memory used by Lua. -@@ LUAI_MEM is a signed integer big enough to count the total memory -@* used by Lua. -** CHANGE here if for some weird reason the default definitions are not -** good enough for your machine. Probably you do not need to change -** this. -*/ -#if LUAI_BITSINT >= 32 /* { */ -#define LUA_INT32 int -#define LUAI_UMEM size_t -#define LUAI_MEM ptrdiff_t -#else /* }{ */ -/* 16-bit ints */ -#define LUA_INT32 long -#define LUAI_UMEM unsigned long -#define LUAI_MEM long -#endif /* } */ - - -/* -@@ LUAI_MAXSTACK limits the size of the Lua stack. -** CHANGE it if you need a different limit. This limit is arbitrary; -** its only purpose is to stop Lua to consume unlimited stack -** space (and to reserve some numbers for pseudo-indices). -*/ -#if LUAI_BITSINT >= 32 -#define LUAI_MAXSTACK 1000000 -#else -#define LUAI_MAXSTACK 15000 -#endif - -/* reserve some space for error handling */ -#define LUAI_FIRSTPSEUDOIDX (-LUAI_MAXSTACK - 1000) - - - - -/* -@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. -** CHANGE it if it uses too much C-stack space. -*/ -#define LUAL_BUFFERSIZE BUFSIZ - - - - -/* -** {================================================================== -@@ LUA_NUMBER is the type of numbers in Lua. -** CHANGE the following definitions only if you want to build Lua -** with a number type different from double. You may also need to -** change lua_number2int & lua_number2integer. -** =================================================================== -*/ - -#define LUA_NUMBER_DOUBLE -#define LUA_NUMBER double - -/* -@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' -@* over a number. -*/ -#define LUAI_UACNUMBER double - - -/* -@@ LUA_NUMBER_SCAN is the format for reading numbers. -@@ LUA_NUMBER_FMT is the format for writing numbers. -@@ lua_number2str converts a number to a string. -@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. -*/ -#define LUA_NUMBER_SCAN "%lf" -#define LUA_NUMBER_FMT "%.14g" -#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) -#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ - - -/* -@@ l_mathop allows the addition of an 'l' or 'f' to all math operations -*/ -#define l_mathop(x) (x) - - -/* -@@ lua_str2number converts a decimal numeric string to a number. -@@ lua_strx2number converts an hexadecimal numeric string to a number. -** In C99, 'strtod' does both conversions. C89, however, has no function -** to convert floating hexadecimal strings to numbers. For these -** systems, you can leave 'lua_strx2number' undefined and Lua will -** provide its own implementation. -*/ -#define lua_str2number(s,p) strtod((s), (p)) - -#if defined(LUA_USE_STRTODHEX) -#define lua_strx2number(s,p) strtod((s), (p)) -#endif - - -/* -@@ The luai_num* macros define the primitive operations over numbers. -*/ - -/* the following operations need the math library */ -#if defined(lobject_c) || defined(lvm_c) -#include -#define luai_nummod(L,a,b) ((a) - l_mathop(floor)((a)/(b))*(b)) -#define luai_numpow(L,a,b) (l_mathop(pow)(a,b)) -#endif - -/* these are quite standard operations */ -#if defined(LUA_CORE) -#define luai_numadd(L,a,b) ((a)+(b)) -#define luai_numsub(L,a,b) ((a)-(b)) -#define luai_nummul(L,a,b) ((a)*(b)) -#define luai_numdiv(L,a,b) ((a)/(b)) -#define luai_numunm(L,a) (-(a)) -#define luai_numeq(a,b) ((a)==(b)) -#define luai_numlt(L,a,b) ((a)<(b)) -#define luai_numle(L,a,b) ((a)<=(b)) -#define luai_numisnan(L,a) (!luai_numeq((a), (a))) -#endif - - - -/* -@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. -** CHANGE that if ptrdiff_t is not adequate on your machine. (On most -** machines, ptrdiff_t gives a good choice between int or long.) -*/ -#define LUA_INTEGER ptrdiff_t - -/* -@@ LUA_UNSIGNED is the integral type used by lua_pushunsigned/lua_tounsigned. -** It must have at least 32 bits. -*/ -#define LUA_UNSIGNED unsigned LUA_INT32 - - - -/* -** Some tricks with doubles -*/ - -#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */ -/* -** The next definitions activate some tricks to speed up the -** conversion from doubles to integer types, mainly to LUA_UNSIGNED. -** -@@ LUA_MSASMTRICK uses Microsoft assembler to avoid clashes with a -** DirectX idiosyncrasy. -** -@@ LUA_IEEE754TRICK uses a trick that should work on any machine -** using IEEE754 with a 32-bit integer type. -** -@@ LUA_IEEELL extends the trick to LUA_INTEGER; should only be -** defined when LUA_INTEGER is a 32-bit integer. -** -@@ LUA_IEEEENDIAN is the endianness of doubles in your machine -** (0 for little endian, 1 for big endian); if not defined, Lua will -** check it dynamically for LUA_IEEE754TRICK (but not for LUA_NANTRICK). -** -@@ LUA_NANTRICK controls the use of a trick to pack all types into -** a single double value, using NaN values to represent non-number -** values. The trick only works on 32-bit machines (ints and pointers -** are 32-bit values) with numbers represented as IEEE 754-2008 doubles -** with conventional endianess (12345678 or 87654321), in CPUs that do -** not produce signaling NaN values (all NaNs are quiet). -*/ - -/* Microsoft compiler on a Pentium (32 bit) ? */ -#if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */ - -#define LUA_MSASMTRICK -#define LUA_IEEEENDIAN 0 -#define LUA_NANTRICK - - -/* pentium 32 bits? */ -#elif defined(__i386__) || defined(__i386) || defined(__X86__) /* }{ */ - -#define LUA_IEEE754TRICK -#define LUA_IEEELL -#define LUA_IEEEENDIAN 0 -#define LUA_NANTRICK - -/* pentium 64 bits? */ -#elif defined(__x86_64) /* }{ */ - -#define LUA_IEEE754TRICK -#define LUA_IEEEENDIAN 0 - -#elif defined(__POWERPC__) || defined(__ppc__) /* }{ */ - -#define LUA_IEEE754TRICK -#define LUA_IEEEENDIAN 1 - -#else /* }{ */ - -/* assume IEEE754 and a 32-bit integer type */ -#define LUA_IEEE754TRICK - -#endif /* } */ - -#endif /* } */ - -/* }================================================================== */ - - - - -/* =================================================================== */ - -/* -** Local configuration. You can use this space to add your redefinitions -** without modifying the main part of the file. -*/ - - - -#endif - diff --git a/contrib/lua/lua/src/lualib.h b/contrib/lua/lua/src/lualib.h deleted file mode 100644 index 9fd126bf78e..00000000000 --- a/contrib/lua/lua/src/lualib.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -** $Id: lualib.h,v 1.43 2011/12/08 12:11:37 roberto Exp $ -** Lua standard libraries -** See Copyright Notice in lua.h -*/ - - -#ifndef lualib_h -#define lualib_h - -#include "lua.h" - - - -LUAMOD_API int (luaopen_base) (lua_State *L); - -#define LUA_COLIBNAME "coroutine" -LUAMOD_API int (luaopen_coroutine) (lua_State *L); - -#define LUA_TABLIBNAME "table" -LUAMOD_API int (luaopen_table) (lua_State *L); - -#define LUA_IOLIBNAME "io" -LUAMOD_API int (luaopen_io) (lua_State *L); - -#define LUA_OSLIBNAME "os" -LUAMOD_API int (luaopen_os) (lua_State *L); - -#define LUA_STRLIBNAME "string" -LUAMOD_API int (luaopen_string) (lua_State *L); - -#define LUA_BITLIBNAME "bit32" -LUAMOD_API int (luaopen_bit32) (lua_State *L); - -#define LUA_MATHLIBNAME "math" -LUAMOD_API int (luaopen_math) (lua_State *L); - -#define LUA_DBLIBNAME "debug" -LUAMOD_API int (luaopen_debug) (lua_State *L); - -#define LUA_LOADLIBNAME "package" -LUAMOD_API int (luaopen_package) (lua_State *L); - - -/* open all previous libraries */ -LUALIB_API void (luaL_openlibs) (lua_State *L); - - - -#if !defined(lua_assert) -#define lua_assert(x) ((void)0) -#endif - - -#endif diff --git a/contrib/lua/lua/src/lundump.c b/contrib/lua/lua/src/lundump.c deleted file mode 100644 index 54de011a45d..00000000000 --- a/contrib/lua/lua/src/lundump.c +++ /dev/null @@ -1,258 +0,0 @@ -/* -** $Id: lundump.c,v 2.22 2012/05/08 13:53:33 roberto Exp $ -** load precompiled Lua chunks -** See Copyright Notice in lua.h -*/ - -#include - -#define lundump_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstring.h" -#include "lundump.h" -#include "lzio.h" - -typedef struct { - lua_State* L; - ZIO* Z; - Mbuffer* b; - const char* name; -} LoadState; - -static l_noret error(LoadState* S, const char* why) -{ - luaO_pushfstring(S->L,"%s: %s precompiled chunk",S->name,why); - luaD_throw(S->L,LUA_ERRSYNTAX); -} - -#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) -#define LoadByte(S) (lu_byte)LoadChar(S) -#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) -#define LoadVector(S,b,n,size) LoadMem(S,b,n,size) - -#if !defined(luai_verifycode) -#define luai_verifycode(L,b,f) /* empty */ -#endif - -static void LoadBlock(LoadState* S, void* b, size_t size) -{ - if (luaZ_read(S->Z,b,size)!=0) error(S,"truncated"); -} - -static int LoadChar(LoadState* S) -{ - char x; - LoadVar(S,x); - return x; -} - -static int LoadInt(LoadState* S) -{ - int x; - LoadVar(S,x); - if (x<0) error(S,"corrupted"); - return x; -} - -static lua_Number LoadNumber(LoadState* S) -{ - lua_Number x; - LoadVar(S,x); - return x; -} - -static TString* LoadString(LoadState* S) -{ - size_t size; - LoadVar(S,size); - if (size==0) - return NULL; - else - { - char* s=luaZ_openspace(S->L,S->b,size); - LoadBlock(S,s,size*sizeof(char)); - return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ - } -} - -static void LoadCode(LoadState* S, Proto* f) -{ - int n=LoadInt(S); - f->code=luaM_newvector(S->L,n,Instruction); - f->sizecode=n; - LoadVector(S,f->code,n,sizeof(Instruction)); -} - -static void LoadFunction(LoadState* S, Proto* f); - -static void LoadConstants(LoadState* S, Proto* f) -{ - int i,n; - n=LoadInt(S); - f->k=luaM_newvector(S->L,n,TValue); - f->sizek=n; - for (i=0; ik[i]); - for (i=0; ik[i]; - int t=LoadChar(S); - switch (t) - { - case LUA_TNIL: - setnilvalue(o); - break; - case LUA_TBOOLEAN: - setbvalue(o,LoadChar(S)); - break; - case LUA_TNUMBER: - setnvalue(o,LoadNumber(S)); - break; - case LUA_TSTRING: - setsvalue2n(S->L,o,LoadString(S)); - break; - default: lua_assert(0); - } - } - n=LoadInt(S); - f->p=luaM_newvector(S->L,n,Proto*); - f->sizep=n; - for (i=0; ip[i]=NULL; - for (i=0; ip[i]=luaF_newproto(S->L); - LoadFunction(S,f->p[i]); - } -} - -static void LoadUpvalues(LoadState* S, Proto* f) -{ - int i,n; - n=LoadInt(S); - f->upvalues=luaM_newvector(S->L,n,Upvaldesc); - f->sizeupvalues=n; - for (i=0; iupvalues[i].name=NULL; - for (i=0; iupvalues[i].instack=LoadByte(S); - f->upvalues[i].idx=LoadByte(S); - } -} - -static void LoadDebug(LoadState* S, Proto* f) -{ - int i,n; - f->source=LoadString(S); - n=LoadInt(S); - f->lineinfo=luaM_newvector(S->L,n,int); - f->sizelineinfo=n; - LoadVector(S,f->lineinfo,n,sizeof(int)); - n=LoadInt(S); - f->locvars=luaM_newvector(S->L,n,LocVar); - f->sizelocvars=n; - for (i=0; ilocvars[i].varname=NULL; - for (i=0; ilocvars[i].varname=LoadString(S); - f->locvars[i].startpc=LoadInt(S); - f->locvars[i].endpc=LoadInt(S); - } - n=LoadInt(S); - for (i=0; iupvalues[i].name=LoadString(S); -} - -static void LoadFunction(LoadState* S, Proto* f) -{ - f->linedefined=LoadInt(S); - f->lastlinedefined=LoadInt(S); - f->numparams=LoadByte(S); - f->is_vararg=LoadByte(S); - f->maxstacksize=LoadByte(S); - LoadCode(S,f); - LoadConstants(S,f); - LoadUpvalues(S,f); - LoadDebug(S,f); -} - -/* the code below must be consistent with the code in luaU_header */ -#define N0 LUAC_HEADERSIZE -#define N1 (sizeof(LUA_SIGNATURE)-sizeof(char)) -#define N2 N1+2 -#define N3 N2+6 - -static void LoadHeader(LoadState* S) -{ - lu_byte h[LUAC_HEADERSIZE]; - lu_byte s[LUAC_HEADERSIZE]; - luaU_header(h); - memcpy(s,h,sizeof(char)); /* first char already read */ - LoadBlock(S,s+sizeof(char),LUAC_HEADERSIZE-sizeof(char)); - if (memcmp(h,s,N0)==0) return; - if (memcmp(h,s,N1)!=0) error(S,"not a"); - if (memcmp(h,s,N2)!=0) error(S,"version mismatch in"); - if (memcmp(h,s,N3)!=0) error(S,"incompatible"); else error(S,"corrupted"); -} - -/* -** load precompiled chunk -*/ -Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) -{ - LoadState S; - Closure* cl; - if (*name=='@' || *name=='=') - S.name=name+1; - else if (*name==LUA_SIGNATURE[0]) - S.name="binary string"; - else - S.name=name; - S.L=L; - S.Z=Z; - S.b=buff; - LoadHeader(&S); - cl=luaF_newLclosure(L,1); - setclLvalue(L,L->top,cl); incr_top(L); - cl->l.p=luaF_newproto(L); - LoadFunction(&S,cl->l.p); - if (cl->l.p->sizeupvalues != 1) - { - Proto* p=cl->l.p; - cl=luaF_newLclosure(L,cl->l.p->sizeupvalues); - cl->l.p=p; - setclLvalue(L,L->top-1,cl); - } - luai_verifycode(L,buff,cl->l.p); - return cl; -} - -#define MYINT(s) (s[0]-'0') -#define VERSION MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR) -#define FORMAT 0 /* this is the official format */ - -/* -* make header for precompiled chunks -* if you change the code below be sure to update LoadHeader and FORMAT above -* and LUAC_HEADERSIZE in lundump.h -*/ -void luaU_header (lu_byte* h) -{ - int x=1; - memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-sizeof(char)); - h+=sizeof(LUA_SIGNATURE)-sizeof(char); - *h++=cast_byte(VERSION); - *h++=cast_byte(FORMAT); - *h++=cast_byte(*(char*)&x); /* endianness */ - *h++=cast_byte(sizeof(int)); - *h++=cast_byte(sizeof(size_t)); - *h++=cast_byte(sizeof(Instruction)); - *h++=cast_byte(sizeof(lua_Number)); - *h++=cast_byte(((lua_Number)0.5)==0); /* is lua_Number integral? */ - memcpy(h,LUAC_TAIL,sizeof(LUAC_TAIL)-sizeof(char)); -} diff --git a/contrib/lua/lua/src/lundump.h b/contrib/lua/lua/src/lundump.h deleted file mode 100644 index 2b8accecb8a..00000000000 --- a/contrib/lua/lua/src/lundump.h +++ /dev/null @@ -1,28 +0,0 @@ -/* -** $Id: lundump.h,v 1.39 2012/05/08 13:53:33 roberto Exp $ -** load precompiled Lua chunks -** See Copyright Notice in lua.h -*/ - -#ifndef lundump_h -#define lundump_h - -#include "lobject.h" -#include "lzio.h" - -/* load one chunk; from lundump.c */ -LUAI_FUNC Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name); - -/* make header; from lundump.c */ -LUAI_FUNC void luaU_header (lu_byte* h); - -/* dump one chunk; from ldump.c */ -LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); - -/* data to catch conversion errors */ -#define LUAC_TAIL "\x19\x93\r\n\x1a\n" - -/* size in bytes of header of binary files */ -#define LUAC_HEADERSIZE (sizeof(LUA_SIGNATURE)-sizeof(char)+2+6+sizeof(LUAC_TAIL)-sizeof(char)) - -#endif diff --git a/contrib/lua/lua/src/lvm.c b/contrib/lua/lua/src/lvm.c deleted file mode 100644 index 657d5c456a7..00000000000 --- a/contrib/lua/lua/src/lvm.c +++ /dev/null @@ -1,867 +0,0 @@ -/* -** $Id: lvm.c,v 2.155 2013/03/16 21:10:18 roberto Exp $ -** Lua virtual machine -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include - -#define lvm_c -#define LUA_CORE - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lvm.h" - - - -/* limit for table tag-method chains (to avoid loops) */ -#define MAXTAGLOOP 100 - - -const TValue *luaV_tonumber (const TValue *obj, TValue *n) { - lua_Number num; - if (ttisnumber(obj)) return obj; - if (ttisstring(obj) && luaO_str2d(svalue(obj), tsvalue(obj)->len, &num)) { - setnvalue(n, num); - return n; - } - else - return NULL; -} - - -int luaV_tostring (lua_State *L, StkId obj) { - if (!ttisnumber(obj)) - return 0; - else { - char s[LUAI_MAXNUMBER2STR]; - lua_Number n = nvalue(obj); - int l = lua_number2str(s, n); - setsvalue2s(L, obj, luaS_newlstr(L, s, l)); - return 1; - } -} - - -static void traceexec (lua_State *L) { - CallInfo *ci = L->ci; - lu_byte mask = L->hookmask; - int counthook = ((mask & LUA_MASKCOUNT) && L->hookcount == 0); - if (counthook) - resethookcount(L); /* reset count */ - if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */ - ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ - return; /* do not call hook again (VM yielded, so it did not move) */ - } - if (counthook) - luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */ - if (mask & LUA_MASKLINE) { - Proto *p = ci_func(ci)->p; - int npc = pcRel(ci->u.l.savedpc, p); - int newline = getfuncline(p, npc); - if (npc == 0 || /* call linehook when enter a new function, */ - ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */ - newline != getfuncline(p, pcRel(L->oldpc, p))) /* enter a new line */ - luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */ - } - L->oldpc = ci->u.l.savedpc; - if (L->status == LUA_YIELD) { /* did hook yield? */ - if (counthook) - L->hookcount = 1; /* undo decrement to zero */ - ci->u.l.savedpc--; /* undo increment (resume will increment it again) */ - ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */ - ci->func = L->top - 1; /* protect stack below results */ - luaD_throw(L, LUA_YIELD); - } -} - - -static void callTM (lua_State *L, const TValue *f, const TValue *p1, - const TValue *p2, TValue *p3, int hasres) { - ptrdiff_t result = savestack(L, p3); - setobj2s(L, L->top++, f); /* push function */ - setobj2s(L, L->top++, p1); /* 1st argument */ - setobj2s(L, L->top++, p2); /* 2nd argument */ - if (!hasres) /* no result? 'p3' is third argument */ - setobj2s(L, L->top++, p3); /* 3rd argument */ - /* metamethod may yield only when called from Lua code */ - luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci)); - if (hasres) { /* if has result, move it to its place */ - p3 = restorestack(L, result); - setobjs2s(L, p3, --L->top); - } -} - - -void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { - int loop; - for (loop = 0; loop < MAXTAGLOOP; loop++) { - const TValue *tm; - if (ttistable(t)) { /* `t' is a table? */ - Table *h = hvalue(t); - const TValue *res = luaH_get(h, key); /* do a primitive get */ - if (!ttisnil(res) || /* result is not nil? */ - (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ - setobj2s(L, val, res); - return; - } - /* else will try the tag method */ - } - else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) - luaG_typeerror(L, t, "index"); - if (ttisfunction(tm)) { - callTM(L, tm, t, key, val, 1); - return; - } - t = tm; /* else repeat with 'tm' */ - } - luaG_runerror(L, "loop in gettable"); -} - - -void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { - int loop; - for (loop = 0; loop < MAXTAGLOOP; loop++) { - const TValue *tm; - if (ttistable(t)) { /* `t' is a table? */ - Table *h = hvalue(t); - TValue *oldval = cast(TValue *, luaH_get(h, key)); - /* if previous value is not nil, there must be a previous entry - in the table; moreover, a metamethod has no relevance */ - if (!ttisnil(oldval) || - /* previous value is nil; must check the metamethod */ - ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL && - /* no metamethod; is there a previous entry in the table? */ - (oldval != luaO_nilobject || - /* no previous entry; must create one. (The next test is - always true; we only need the assignment.) */ - (oldval = luaH_newkey(L, h, key), 1)))) { - /* no metamethod and (now) there is an entry with given key */ - setobj2t(L, oldval, val); /* assign new value to that entry */ - invalidateTMcache(h); - luaC_barrierback(L, obj2gco(h), val); - return; - } - /* else will try the metamethod */ - } - else /* not a table; check metamethod */ - if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) - luaG_typeerror(L, t, "index"); - /* there is a metamethod */ - if (ttisfunction(tm)) { - callTM(L, tm, t, key, val, 0); - return; - } - t = tm; /* else repeat with 'tm' */ - } - luaG_runerror(L, "loop in settable"); -} - - -static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2, - StkId res, TMS event) { - const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ - if (ttisnil(tm)) - tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ - if (ttisnil(tm)) return 0; - callTM(L, tm, p1, p2, res, 1); - return 1; -} - - -static const TValue *get_equalTM (lua_State *L, Table *mt1, Table *mt2, - TMS event) { - const TValue *tm1 = fasttm(L, mt1, event); - const TValue *tm2; - if (tm1 == NULL) return NULL; /* no metamethod */ - if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ - tm2 = fasttm(L, mt2, event); - if (tm2 == NULL) return NULL; /* no metamethod */ - if (luaV_rawequalobj(tm1, tm2)) /* same metamethods? */ - return tm1; - return NULL; -} - - -static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2, - TMS event) { - if (!call_binTM(L, p1, p2, L->top, event)) - return -1; /* no metamethod */ - else - return !l_isfalse(L->top); -} - - -static int l_strcmp (const TString *ls, const TString *rs) { - const char *l = getstr(ls); - size_t ll = ls->tsv.len; - const char *r = getstr(rs); - size_t lr = rs->tsv.len; - for (;;) { - int temp = strcoll(l, r); - if (temp != 0) return temp; - else { /* strings are equal up to a `\0' */ - size_t len = strlen(l); /* index of first `\0' in both strings */ - if (len == lr) /* r is finished? */ - return (len == ll) ? 0 : 1; - else if (len == ll) /* l is finished? */ - return -1; /* l is smaller than r (because r is not finished) */ - /* both strings longer than `len'; go on comparing (after the `\0') */ - len++; - l += len; ll -= len; r += len; lr -= len; - } - } -} - - -int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { - int res; - if (ttisnumber(l) && ttisnumber(r)) - return luai_numlt(L, nvalue(l), nvalue(r)); - else if (ttisstring(l) && ttisstring(r)) - return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; - else if ((res = call_orderTM(L, l, r, TM_LT)) < 0) - luaG_ordererror(L, l, r); - return res; -} - - -int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { - int res; - if (ttisnumber(l) && ttisnumber(r)) - return luai_numle(L, nvalue(l), nvalue(r)); - else if (ttisstring(l) && ttisstring(r)) - return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; - else if ((res = call_orderTM(L, l, r, TM_LE)) >= 0) /* first try `le' */ - return res; - else if ((res = call_orderTM(L, r, l, TM_LT)) < 0) /* else try `lt' */ - luaG_ordererror(L, l, r); - return !res; -} - - -/* -** equality of Lua values. L == NULL means raw equality (no metamethods) -*/ -int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2) { - const TValue *tm; - lua_assert(ttisequal(t1, t2)); - switch (ttype(t1)) { - case LUA_TNIL: return 1; - case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); - case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ - case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); - case LUA_TLCF: return fvalue(t1) == fvalue(t2); - case LUA_TSHRSTR: return eqshrstr(rawtsvalue(t1), rawtsvalue(t2)); - case LUA_TLNGSTR: return luaS_eqlngstr(rawtsvalue(t1), rawtsvalue(t2)); - case LUA_TUSERDATA: { - if (uvalue(t1) == uvalue(t2)) return 1; - else if (L == NULL) return 0; - tm = get_equalTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, TM_EQ); - break; /* will try TM */ - } - case LUA_TTABLE: { - if (hvalue(t1) == hvalue(t2)) return 1; - else if (L == NULL) return 0; - tm = get_equalTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); - break; /* will try TM */ - } - default: - lua_assert(iscollectable(t1)); - return gcvalue(t1) == gcvalue(t2); - } - if (tm == NULL) return 0; /* no TM? */ - callTM(L, tm, t1, t2, L->top, 1); /* call TM */ - return !l_isfalse(L->top); -} - - -void luaV_concat (lua_State *L, int total) { - lua_assert(total >= 2); - do { - StkId top = L->top; - int n = 2; /* number of elements handled in this pass (at least 2) */ - if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { - if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) - luaG_concaterror(L, top-2, top-1); - } - else if (tsvalue(top-1)->len == 0) /* second operand is empty? */ - (void)tostring(L, top - 2); /* result is first operand */ - else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) { - setobjs2s(L, top - 2, top - 1); /* result is second op. */ - } - else { - /* at least two non-empty string values; get as many as possible */ - size_t tl = tsvalue(top-1)->len; - char *buffer; - int i; - /* collect total length */ - for (i = 1; i < total && tostring(L, top-i-1); i++) { - size_t l = tsvalue(top-i-1)->len; - if (l >= (MAX_SIZET/sizeof(char)) - tl) - luaG_runerror(L, "string length overflow"); - tl += l; - } - buffer = luaZ_openspace(L, &G(L)->buff, tl); - tl = 0; - n = i; - do { /* concat all strings */ - size_t l = tsvalue(top-i)->len; - memcpy(buffer+tl, svalue(top-i), l * sizeof(char)); - tl += l; - } while (--i > 0); - setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); - } - total -= n-1; /* got 'n' strings to create 1 new */ - L->top -= n-1; /* popped 'n' strings and pushed one */ - } while (total > 1); /* repeat until only 1 result left */ -} - - -void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { - const TValue *tm; - switch (ttypenv(rb)) { - case LUA_TTABLE: { - Table *h = hvalue(rb); - tm = fasttm(L, h->metatable, TM_LEN); - if (tm) break; /* metamethod? break switch to call it */ - setnvalue(ra, cast_num(luaH_getn(h))); /* else primitive len */ - return; - } - case LUA_TSTRING: { - setnvalue(ra, cast_num(tsvalue(rb)->len)); - return; - } - default: { /* try metamethod */ - tm = luaT_gettmbyobj(L, rb, TM_LEN); - if (ttisnil(tm)) /* no metamethod? */ - luaG_typeerror(L, rb, "get length of"); - break; - } - } - callTM(L, tm, rb, rb, ra, 1); -} - - -void luaV_arith (lua_State *L, StkId ra, const TValue *rb, - const TValue *rc, TMS op) { - TValue tempb, tempc; - const TValue *b, *c; - if ((b = luaV_tonumber(rb, &tempb)) != NULL && - (c = luaV_tonumber(rc, &tempc)) != NULL) { - lua_Number res = luaO_arith(op - TM_ADD + LUA_OPADD, nvalue(b), nvalue(c)); - setnvalue(ra, res); - } - else if (!call_binTM(L, rb, rc, ra, op)) - luaG_aritherror(L, rb, rc); -} - - -/* -** check whether cached closure in prototype 'p' may be reused, that is, -** whether there is a cached closure with the same upvalues needed by -** new closure to be created. -*/ -static Closure *getcached (Proto *p, UpVal **encup, StkId base) { - Closure *c = p->cache; - if (c != NULL) { /* is there a cached closure? */ - int nup = p->sizeupvalues; - Upvaldesc *uv = p->upvalues; - int i; - for (i = 0; i < nup; i++) { /* check whether it has right upvalues */ - TValue *v = uv[i].instack ? base + uv[i].idx : encup[uv[i].idx]->v; - if (c->l.upvals[i]->v != v) - return NULL; /* wrong upvalue; cannot reuse closure */ - } - } - return c; /* return cached closure (or NULL if no cached closure) */ -} - - -/* -** create a new Lua closure, push it in the stack, and initialize -** its upvalues. Note that the call to 'luaC_barrierproto' must come -** before the assignment to 'p->cache', as the function needs the -** original value of that field. -*/ -static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, - StkId ra) { - int nup = p->sizeupvalues; - Upvaldesc *uv = p->upvalues; - int i; - Closure *ncl = luaF_newLclosure(L, nup); - ncl->l.p = p; - setclLvalue(L, ra, ncl); /* anchor new closure in stack */ - for (i = 0; i < nup; i++) { /* fill in its upvalues */ - if (uv[i].instack) /* upvalue refers to local variable? */ - ncl->l.upvals[i] = luaF_findupval(L, base + uv[i].idx); - else /* get upvalue from enclosing function */ - ncl->l.upvals[i] = encup[uv[i].idx]; - } - luaC_barrierproto(L, p, ncl); - p->cache = ncl; /* save it on cache for reuse */ -} - - -/* -** finish execution of an opcode interrupted by an yield -*/ -void luaV_finishOp (lua_State *L) { - CallInfo *ci = L->ci; - StkId base = ci->u.l.base; - Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ - OpCode op = GET_OPCODE(inst); - switch (op) { /* finish its execution */ - case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: - case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN: - case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: { - setobjs2s(L, base + GETARG_A(inst), --L->top); - break; - } - case OP_LE: case OP_LT: case OP_EQ: { - int res = !l_isfalse(L->top - 1); - L->top--; - /* metamethod should not be called when operand is K */ - lua_assert(!ISK(GETARG_B(inst))); - if (op == OP_LE && /* "<=" using "<" instead? */ - ttisnil(luaT_gettmbyobj(L, base + GETARG_B(inst), TM_LE))) - res = !res; /* invert result */ - lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); - if (res != GETARG_A(inst)) /* condition failed? */ - ci->u.l.savedpc++; /* skip jump instruction */ - break; - } - case OP_CONCAT: { - StkId top = L->top - 1; /* top when 'call_binTM' was called */ - int b = GETARG_B(inst); /* first element to concatenate */ - int total = cast_int(top - 1 - (base + b)); /* yet to concatenate */ - setobj2s(L, top - 2, top); /* put TM result in proper position */ - if (total > 1) { /* are there elements to concat? */ - L->top = top - 1; /* top is one after last element (at top-2) */ - luaV_concat(L, total); /* concat them (may yield again) */ - } - /* move final result to final position */ - setobj2s(L, ci->u.l.base + GETARG_A(inst), L->top - 1); - L->top = ci->top; /* restore top */ - break; - } - case OP_TFORCALL: { - lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP); - L->top = ci->top; /* correct top */ - break; - } - case OP_CALL: { - if (GETARG_C(inst) - 1 >= 0) /* nresults >= 0? */ - L->top = ci->top; /* adjust results */ - break; - } - case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE: - break; - default: lua_assert(0); - } -} - - - -/* -** some macros for common tasks in `luaV_execute' -*/ - -#if !defined luai_runtimecheck -#define luai_runtimecheck(L, c) /* void */ -#endif - - -#define RA(i) (base+GETARG_A(i)) -/* to be used after possible stack reallocation */ -#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) -#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) -#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ - ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) -#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ - ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) -#define KBx(i) \ - (k + (GETARG_Bx(i) != 0 ? GETARG_Bx(i) - 1 : GETARG_Ax(*ci->u.l.savedpc++))) - - -/* execute a jump instruction */ -#define dojump(ci,i,e) \ - { int a = GETARG_A(i); \ - if (a > 0) luaF_close(L, ci->u.l.base + a - 1); \ - ci->u.l.savedpc += GETARG_sBx(i) + e; } - -/* for test instructions, execute the jump instruction that follows it */ -#define donextjump(ci) { i = *ci->u.l.savedpc; dojump(ci, i, 1); } - - -#define Protect(x) { {x;}; base = ci->u.l.base; } - -#define checkGC(L,c) \ - Protect( luaC_condGC(L,{L->top = (c); /* limit of live values */ \ - luaC_step(L); \ - L->top = ci->top;}) /* restore top */ \ - luai_threadyield(L); ) - - -#define arith_op(op,tm) { \ - TValue *rb = RKB(i); \ - TValue *rc = RKC(i); \ - if (ttisnumber(rb) && ttisnumber(rc)) { \ - lua_Number nb = nvalue(rb), nc = nvalue(rc); \ - setnvalue(ra, op(L, nb, nc)); \ - } \ - else { Protect(luaV_arith(L, ra, rb, rc, tm)); } } - - -#define vmdispatch(o) switch(o) -#define vmcase(l,b) case l: {b} break; -#define vmcasenb(l,b) case l: {b} /* nb = no break */ - -void luaV_execute (lua_State *L) { - CallInfo *ci = L->ci; - LClosure *cl; - TValue *k; - StkId base; - newframe: /* reentry point when frame changes (call/return) */ - lua_assert(ci == L->ci); - cl = clLvalue(ci->func); - k = cl->p->k; - base = ci->u.l.base; - /* main loop of interpreter */ - for (;;) { - Instruction i = *(ci->u.l.savedpc++); - StkId ra; - if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && - (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { - Protect(traceexec(L)); - } - /* WARNING: several calls may realloc the stack and invalidate `ra' */ - ra = RA(i); - lua_assert(base == ci->u.l.base); - lua_assert(base <= L->top && L->top < L->stack + L->stacksize); - vmdispatch (GET_OPCODE(i)) { - vmcase(OP_MOVE, - setobjs2s(L, ra, RB(i)); - ) - vmcase(OP_LOADK, - TValue *rb = k + GETARG_Bx(i); - setobj2s(L, ra, rb); - ) - vmcase(OP_LOADKX, - TValue *rb; - lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); - rb = k + GETARG_Ax(*ci->u.l.savedpc++); - setobj2s(L, ra, rb); - ) - vmcase(OP_LOADBOOL, - setbvalue(ra, GETARG_B(i)); - if (GETARG_C(i)) ci->u.l.savedpc++; /* skip next instruction (if C) */ - ) - vmcase(OP_LOADNIL, - int b = GETARG_B(i); - do { - setnilvalue(ra++); - } while (b--); - ) - vmcase(OP_GETUPVAL, - int b = GETARG_B(i); - setobj2s(L, ra, cl->upvals[b]->v); - ) - vmcase(OP_GETTABUP, - int b = GETARG_B(i); - Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra)); - ) - vmcase(OP_GETTABLE, - Protect(luaV_gettable(L, RB(i), RKC(i), ra)); - ) - vmcase(OP_SETTABUP, - int a = GETARG_A(i); - Protect(luaV_settable(L, cl->upvals[a]->v, RKB(i), RKC(i))); - ) - vmcase(OP_SETUPVAL, - UpVal *uv = cl->upvals[GETARG_B(i)]; - setobj(L, uv->v, ra); - luaC_barrier(L, uv, ra); - ) - vmcase(OP_SETTABLE, - Protect(luaV_settable(L, ra, RKB(i), RKC(i))); - ) - vmcase(OP_NEWTABLE, - int b = GETARG_B(i); - int c = GETARG_C(i); - Table *t = luaH_new(L); - sethvalue(L, ra, t); - if (b != 0 || c != 0) - luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c)); - checkGC(L, ra + 1); - ) - vmcase(OP_SELF, - StkId rb = RB(i); - setobjs2s(L, ra+1, rb); - Protect(luaV_gettable(L, rb, RKC(i), ra)); - ) - vmcase(OP_ADD, - arith_op(luai_numadd, TM_ADD); - ) - vmcase(OP_SUB, - arith_op(luai_numsub, TM_SUB); - ) - vmcase(OP_MUL, - arith_op(luai_nummul, TM_MUL); - ) - vmcase(OP_DIV, - arith_op(luai_numdiv, TM_DIV); - ) - vmcase(OP_MOD, - arith_op(luai_nummod, TM_MOD); - ) - vmcase(OP_POW, - arith_op(luai_numpow, TM_POW); - ) - vmcase(OP_UNM, - TValue *rb = RB(i); - if (ttisnumber(rb)) { - lua_Number nb = nvalue(rb); - setnvalue(ra, luai_numunm(L, nb)); - } - else { - Protect(luaV_arith(L, ra, rb, rb, TM_UNM)); - } - ) - vmcase(OP_NOT, - TValue *rb = RB(i); - int res = l_isfalse(rb); /* next assignment may change this value */ - setbvalue(ra, res); - ) - vmcase(OP_LEN, - Protect(luaV_objlen(L, ra, RB(i))); - ) - vmcase(OP_CONCAT, - int b = GETARG_B(i); - int c = GETARG_C(i); - StkId rb; - L->top = base + c + 1; /* mark the end of concat operands */ - Protect(luaV_concat(L, c - b + 1)); - ra = RA(i); /* 'luav_concat' may invoke TMs and move the stack */ - rb = b + base; - setobjs2s(L, ra, rb); - checkGC(L, (ra >= rb ? ra + 1 : rb)); - L->top = ci->top; /* restore top */ - ) - vmcase(OP_JMP, - dojump(ci, i, 0); - ) - vmcase(OP_EQ, - TValue *rb = RKB(i); - TValue *rc = RKC(i); - Protect( - if (cast_int(equalobj(L, rb, rc)) != GETARG_A(i)) - ci->u.l.savedpc++; - else - donextjump(ci); - ) - ) - vmcase(OP_LT, - Protect( - if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) - ci->u.l.savedpc++; - else - donextjump(ci); - ) - ) - vmcase(OP_LE, - Protect( - if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) - ci->u.l.savedpc++; - else - donextjump(ci); - ) - ) - vmcase(OP_TEST, - if (GETARG_C(i) ? l_isfalse(ra) : !l_isfalse(ra)) - ci->u.l.savedpc++; - else - donextjump(ci); - ) - vmcase(OP_TESTSET, - TValue *rb = RB(i); - if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb)) - ci->u.l.savedpc++; - else { - setobjs2s(L, ra, rb); - donextjump(ci); - } - ) - vmcase(OP_CALL, - int b = GETARG_B(i); - int nresults = GETARG_C(i) - 1; - if (b != 0) L->top = ra+b; /* else previous instruction set top */ - if (luaD_precall(L, ra, nresults)) { /* C function? */ - if (nresults >= 0) L->top = ci->top; /* adjust results */ - base = ci->u.l.base; - } - else { /* Lua function */ - ci = L->ci; - ci->callstatus |= CIST_REENTRY; - goto newframe; /* restart luaV_execute over new Lua function */ - } - ) - vmcase(OP_TAILCALL, - int b = GETARG_B(i); - if (b != 0) L->top = ra+b; /* else previous instruction set top */ - lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); - if (luaD_precall(L, ra, LUA_MULTRET)) /* C function? */ - base = ci->u.l.base; - else { - /* tail call: put called frame (n) in place of caller one (o) */ - CallInfo *nci = L->ci; /* called frame */ - CallInfo *oci = nci->previous; /* caller frame */ - StkId nfunc = nci->func; /* called function */ - StkId ofunc = oci->func; /* caller function */ - /* last stack slot filled by 'precall' */ - StkId lim = nci->u.l.base + getproto(nfunc)->numparams; - int aux; - /* close all upvalues from previous call */ - if (cl->p->sizep > 0) luaF_close(L, oci->u.l.base); - /* move new frame into old one */ - for (aux = 0; nfunc + aux < lim; aux++) - setobjs2s(L, ofunc + aux, nfunc + aux); - oci->u.l.base = ofunc + (nci->u.l.base - nfunc); /* correct base */ - oci->top = L->top = ofunc + (L->top - nfunc); /* correct top */ - oci->u.l.savedpc = nci->u.l.savedpc; - oci->callstatus |= CIST_TAIL; /* function was tail called */ - ci = L->ci = oci; /* remove new frame */ - lua_assert(L->top == oci->u.l.base + getproto(ofunc)->maxstacksize); - goto newframe; /* restart luaV_execute over new Lua function */ - } - ) - vmcasenb(OP_RETURN, - int b = GETARG_B(i); - if (b != 0) L->top = ra+b-1; - if (cl->p->sizep > 0) luaF_close(L, base); - b = luaD_poscall(L, ra); - if (!(ci->callstatus & CIST_REENTRY)) /* 'ci' still the called one */ - return; /* external invocation: return */ - else { /* invocation via reentry: continue execution */ - ci = L->ci; - if (b) L->top = ci->top; - lua_assert(isLua(ci)); - lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL); - goto newframe; /* restart luaV_execute over new Lua function */ - } - ) - vmcase(OP_FORLOOP, - lua_Number step = nvalue(ra+2); - lua_Number idx = luai_numadd(L, nvalue(ra), step); /* increment index */ - lua_Number limit = nvalue(ra+1); - if (luai_numlt(L, 0, step) ? luai_numle(L, idx, limit) - : luai_numle(L, limit, idx)) { - ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ - setnvalue(ra, idx); /* update internal index... */ - setnvalue(ra+3, idx); /* ...and external index */ - } - ) - vmcase(OP_FORPREP, - const TValue *init = ra; - const TValue *plimit = ra+1; - const TValue *pstep = ra+2; - if (!tonumber(init, ra)) - luaG_runerror(L, LUA_QL("for") " initial value must be a number"); - else if (!tonumber(plimit, ra+1)) - luaG_runerror(L, LUA_QL("for") " limit must be a number"); - else if (!tonumber(pstep, ra+2)) - luaG_runerror(L, LUA_QL("for") " step must be a number"); - setnvalue(ra, luai_numsub(L, nvalue(ra), nvalue(pstep))); - ci->u.l.savedpc += GETARG_sBx(i); - ) - vmcasenb(OP_TFORCALL, - StkId cb = ra + 3; /* call base */ - setobjs2s(L, cb+2, ra+2); - setobjs2s(L, cb+1, ra+1); - setobjs2s(L, cb, ra); - L->top = cb + 3; /* func. + 2 args (state and index) */ - Protect(luaD_call(L, cb, GETARG_C(i), 1)); - L->top = ci->top; - i = *(ci->u.l.savedpc++); /* go to next instruction */ - ra = RA(i); - lua_assert(GET_OPCODE(i) == OP_TFORLOOP); - goto l_tforloop; - ) - vmcase(OP_TFORLOOP, - l_tforloop: - if (!ttisnil(ra + 1)) { /* continue loop? */ - setobjs2s(L, ra, ra + 1); /* save control variable */ - ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ - } - ) - vmcase(OP_SETLIST, - int n = GETARG_B(i); - int c = GETARG_C(i); - int last; - Table *h; - if (n == 0) n = cast_int(L->top - ra) - 1; - if (c == 0) { - lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); - c = GETARG_Ax(*ci->u.l.savedpc++); - } - luai_runtimecheck(L, ttistable(ra)); - h = hvalue(ra); - last = ((c-1)*LFIELDS_PER_FLUSH) + n; - if (last > h->sizearray) /* needs more space? */ - luaH_resizearray(L, h, last); /* pre-allocate it at once */ - for (; n > 0; n--) { - TValue *val = ra+n; - luaH_setint(L, h, last--, val); - luaC_barrierback(L, obj2gco(h), val); - } - L->top = ci->top; /* correct top (in case of previous open call) */ - ) - vmcase(OP_CLOSURE, - Proto *p = cl->p->p[GETARG_Bx(i)]; - Closure *ncl = getcached(p, cl->upvals, base); /* cached closure */ - if (ncl == NULL) /* no match? */ - pushclosure(L, p, cl->upvals, base, ra); /* create a new one */ - else - setclLvalue(L, ra, ncl); /* push cashed closure */ - checkGC(L, ra + 1); - ) - vmcase(OP_VARARG, - int b = GETARG_B(i) - 1; - int j; - int n = cast_int(base - ci->func) - cl->p->numparams - 1; - if (b < 0) { /* B == 0? */ - b = n; /* get all var. arguments */ - Protect(luaD_checkstack(L, n)); - ra = RA(i); /* previous call may change the stack */ - L->top = ra + n; - } - for (j = 0; j < b; j++) { - if (j < n) { - setobjs2s(L, ra + j, base - n + j); - } - else { - setnilvalue(ra + j); - } - } - ) - vmcase(OP_EXTRAARG, - lua_assert(0); - ) - } - } -} - diff --git a/contrib/lua/lua/src/lvm.h b/contrib/lua/lua/src/lvm.h deleted file mode 100644 index 07e25f9c64b..00000000000 --- a/contrib/lua/lua/src/lvm.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -** $Id: lvm.h,v 2.18 2013/01/08 14:06:55 roberto Exp $ -** Lua virtual machine -** See Copyright Notice in lua.h -*/ - -#ifndef lvm_h -#define lvm_h - - -#include "ldo.h" -#include "lobject.h" -#include "ltm.h" - - -#define tostring(L,o) (ttisstring(o) || (luaV_tostring(L, o))) - -#define tonumber(o,n) (ttisnumber(o) || (((o) = luaV_tonumber(o,n)) != NULL)) - -#define equalobj(L,o1,o2) (ttisequal(o1, o2) && luaV_equalobj_(L, o1, o2)) - -#define luaV_rawequalobj(o1,o2) equalobj(NULL,o1,o2) - - -/* not to called directly */ -LUAI_FUNC int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2); - - -LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); -LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); -LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n); -LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj); -LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, - StkId val); -LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, - StkId val); -LUAI_FUNC void luaV_finishOp (lua_State *L); -LUAI_FUNC void luaV_execute (lua_State *L); -LUAI_FUNC void luaV_concat (lua_State *L, int total); -LUAI_FUNC void luaV_arith (lua_State *L, StkId ra, const TValue *rb, - const TValue *rc, TMS op); -LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb); - -#endif diff --git a/contrib/lua/lua/src/lzio.c b/contrib/lua/lua/src/lzio.c deleted file mode 100644 index 8b77054e0b8..00000000000 --- a/contrib/lua/lua/src/lzio.c +++ /dev/null @@ -1,76 +0,0 @@ -/* -** $Id: lzio.c,v 1.35 2012/05/14 13:34:18 roberto Exp $ -** Buffered streams -** See Copyright Notice in lua.h -*/ - - -#include - -#define lzio_c -#define LUA_CORE - -#include "lua.h" - -#include "llimits.h" -#include "lmem.h" -#include "lstate.h" -#include "lzio.h" - - -int luaZ_fill (ZIO *z) { - size_t size; - lua_State *L = z->L; - const char *buff; - lua_unlock(L); - buff = z->reader(L, z->data, &size); - lua_lock(L); - if (buff == NULL || size == 0) - return EOZ; - z->n = size - 1; /* discount char being returned */ - z->p = buff; - return cast_uchar(*(z->p++)); -} - - -void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { - z->L = L; - z->reader = reader; - z->data = data; - z->n = 0; - z->p = NULL; -} - - -/* --------------------------------------------------------------- read --- */ -size_t luaZ_read (ZIO *z, void *b, size_t n) { - while (n) { - size_t m; - if (z->n == 0) { /* no bytes in buffer? */ - if (luaZ_fill(z) == EOZ) /* try to read more */ - return n; /* no more input; return number of missing bytes */ - else { - z->n++; /* luaZ_fill consumed first byte; put it back */ - z->p--; - } - } - m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ - memcpy(b, z->p, m); - z->n -= m; - z->p += m; - b = (char *)b + m; - n -= m; - } - return 0; -} - -/* ------------------------------------------------------------------------ */ -char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) { - if (n > buff->buffsize) { - if (n < LUA_MINBUFFER) n = LUA_MINBUFFER; - luaZ_resizebuffer(L, buff, n); - } - return buff->buffer; -} - - diff --git a/contrib/lua/lua/src/lzio.h b/contrib/lua/lua/src/lzio.h deleted file mode 100644 index 08682301e8a..00000000000 --- a/contrib/lua/lua/src/lzio.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -** $Id: lzio.h,v 1.26 2011/07/15 12:48:03 roberto Exp $ -** Buffered streams -** See Copyright Notice in lua.h -*/ - - -#ifndef lzio_h -#define lzio_h - -#include "lua.h" - -#include "lmem.h" - - -#define EOZ (-1) /* end of stream */ - -typedef struct Zio ZIO; - -#define zgetc(z) (((z)->n--)>0 ? cast_uchar(*(z)->p++) : luaZ_fill(z)) - - -typedef struct Mbuffer { - char *buffer; - size_t n; - size_t buffsize; -} Mbuffer; - -#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) - -#define luaZ_buffer(buff) ((buff)->buffer) -#define luaZ_sizebuffer(buff) ((buff)->buffsize) -#define luaZ_bufflen(buff) ((buff)->n) - -#define luaZ_resetbuffer(buff) ((buff)->n = 0) - - -#define luaZ_resizebuffer(L, buff, size) \ - (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \ - (buff)->buffsize = size) - -#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) - - -LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); -LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, - void *data); -LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ - - - -/* --------- Private Part ------------------ */ - -struct Zio { - size_t n; /* bytes still unread */ - const char *p; /* current position in buffer */ - lua_Reader reader; /* reader function */ - void* data; /* additional data */ - lua_State *L; /* Lua state (for reader) */ -}; - - -LUAI_FUNC int luaZ_fill (ZIO *z); - -#endif diff --git a/contrib/lua/luajit b/contrib/lua/luajit new file mode 160000 index 00000000000..b93a1dd0c83 --- /dev/null +++ b/contrib/lua/luajit @@ -0,0 +1 @@ +Subproject commit b93a1dd0c831cab22f98163d0dde792a493c0eef diff --git a/contrib/lua/sol.hpp b/contrib/lua/sol.hpp new file mode 100755 index 00000000000..a39bf93ece8 --- /dev/null +++ b/contrib/lua/sol.hpp @@ -0,0 +1,14018 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// This file was generated with a script. +// Generated 2017-04-25 23:43:53.892903 UTC +// This header was generated with sol v2.17.1 (revision 0db6d99) +// https://github.com/ThePhD/sol2 + +#ifndef SOL_SINGLE_INCLUDE_HPP +#define SOL_SINGLE_INCLUDE_HPP + +// beginning of sol.hpp + +#ifndef SOL_HPP +#define SOL_HPP + +#if defined(UE_BUILD_DEBUG) || defined(UE_BUILD_DEVELOPMENT) || defined(UE_BUILD_TEST) || defined(UE_BUILD_SHIPPING) || defined(UE_SERVER) +#define SOL_INSIDE_UNREAL +#endif // Unreal Engine 4 bullshit + +#ifdef SOL_INSIDE_UNREAL +#ifdef check +#define SOL_INSIDE_UNREAL_REMOVED_CHECK +#undef check +#endif +#endif // Unreal Engine 4 Bullshit + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#pragma GCC diagnostic ignored "-Wconversion" +#elif defined _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4324 ) // structure was padded due to alignment specifier +#endif // g++ + +// beginning of sol/state.hpp + +// beginning of sol/state_view.hpp + +// beginning of sol/error.hpp + +#include +#include + +namespace sol { + namespace detail { + struct direct_error_tag {}; + const auto direct_error = direct_error_tag{}; + } // detail + + class error : public std::runtime_error { + private: + // Because VC++ is a fuccboi + std::string w; + public: + error(const std::string& str) : error(detail::direct_error, "lua: error: " + str) {} + error(std::string&& str) : error(detail::direct_error, "lua: error: " + std::move(str)) {} + error(detail::direct_error_tag, const std::string& str) : std::runtime_error(""), w(str) {} + error(detail::direct_error_tag, std::string&& str) : std::runtime_error(""), w(std::move(str)) {} + + error(const error& e) = default; + error(error&& e) = default; + error& operator=(const error& e) = default; + error& operator=(error&& e) = default; + + virtual const char* what() const noexcept override { + return w.c_str(); + } + }; + +} // sol + +// end of sol/error.hpp + +// beginning of sol/table.hpp + +// beginning of sol/table_core.hpp + +// beginning of sol/proxy.hpp + +// beginning of sol/traits.hpp + +// beginning of sol/tuple.hpp + +#include +#include + +namespace sol { + namespace detail { + using swallow = std::initializer_list; + } // detail + + template + struct types { typedef std::make_index_sequence indices; static constexpr std::size_t size() { return sizeof...(Args); } }; + namespace meta { + namespace detail { + template + struct tuple_types_ { typedef types type; }; + + template + struct tuple_types_> { typedef types type; }; + } // detail + + template + using unqualified = std::remove_cv>; + + template + using unqualified_t = typename unqualified::type; + + template + using tuple_types = typename detail::tuple_types_::type; + + template + struct pop_front_type; + + template + using pop_front_type_t = typename pop_front_type::type; + + template + struct pop_front_type> { typedef void front_type; typedef types type; }; + + template + struct pop_front_type> { typedef Arg front_type; typedef types type; }; + + template + using tuple_element = std::tuple_element>; + + template + using tuple_element_t = std::tuple_element_t>; + + template + using unqualified_tuple_element = unqualified>; + + template + using unqualified_tuple_element_t = unqualified_t>; + + } // meta +} // sol + +// end of sol/tuple.hpp + +// beginning of sol/bind_traits.hpp + +namespace sol { + namespace meta { + namespace meta_detail { + + template + struct check_deducible_signature { + struct nat {}; + template + static auto test(int) -> decltype(&G::operator(), void()); + template + static auto test(...)->nat; + + using type = std::is_void(0))>; + }; + } // meta_detail + + template + struct has_deducible_signature : meta_detail::check_deducible_signature::type { }; + + namespace meta_detail { + + template + struct void_tuple_element : meta::tuple_element {}; + + template + struct void_tuple_element> { typedef void type; }; + + template + using void_tuple_element_t = typename void_tuple_element::type; + + template + struct basic_traits { + private: + typedef std::conditional_t::value, int, T>& first_type; + + public: + static const bool is_member_function = std::is_void::value; + static const bool has_c_var_arg = has_c_variadic; + static const std::size_t arity = sizeof...(Args); + static const std::size_t free_arity = sizeof...(Args)+static_cast(!std::is_void::value); + typedef types args_list; + typedef std::tuple args_tuple; + typedef T object_type; + typedef R return_type; + typedef tuple_types returns_list; + typedef R(function_type)(Args...); + typedef std::conditional_t::value, args_list, types> free_args_list; + typedef std::conditional_t::value, R(Args...), R(first_type, Args...)> free_function_type; + typedef std::conditional_t::value, R(*)(Args...), R(*)(first_type, Args...)> free_function_pointer_type; + typedef std::remove_pointer_t signature_type; + template + using arg_at = void_tuple_element_t; + }; + + template::value> + struct fx_traits : basic_traits {}; + + // Free Functions + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args..., ...); + }; + + template + struct fx_traits : basic_traits { + typedef R(*function_pointer_type)(Args..., ...); + }; + + // Member Functions + /* C-Style Variadics */ + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...); + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...); + }; + + /* Const Volatile */ + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const volatile; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const volatile; + }; + + /* Member Function Qualifiers */ + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) &; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) &; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const &; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const &; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const volatile &; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const volatile &; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) && ; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) && ; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const &&; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const &&; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args...) const volatile &&; + }; + + template + struct fx_traits : basic_traits { + typedef R(T::* function_pointer_type)(Args..., ...) const volatile &&; + }; + + template + struct fx_traits : fx_traits::function_type, false> {}; + + template::value> + struct callable_traits : fx_traits> { + + }; + + template + struct callable_traits { + typedef R Arg; + typedef T object_type; + using signature_type = R(T::*); + static const bool is_member_function = false; + static const std::size_t arity = 1; + static const std::size_t free_arity = 2; + typedef std::tuple args_tuple; + typedef R return_type; + typedef types args_list; + typedef types free_args_list; + typedef meta::tuple_types returns_list; + typedef R(function_type)(T&, R); + typedef R(*function_pointer_type)(T&, R); + typedef R(*free_function_pointer_type)(T&, R); + template + using arg_at = void_tuple_element_t; + }; + } // meta_detail + + template + struct bind_traits : meta_detail::callable_traits {}; + + template + using function_args_t = typename bind_traits::args_list; + + template + using function_signature_t = typename bind_traits::signature_type; + + template + using function_return_t = typename bind_traits::return_type; + + } // meta +} // sol + +// end of sol/bind_traits.hpp + +#include +#include +#include + +namespace sol { + template + using index_value = std::integral_constant; + + namespace meta { + template + struct identity { typedef T type; }; + + template + using identity_t = typename identity::type; + + template + struct is_tuple : std::false_type { }; + + template + struct is_tuple> : std::true_type { }; + + template + struct is_builtin_type : std::integral_constant::value || std::is_pointer::value || std::is_array::value> {}; + + template + struct unwrapped { + typedef T type; + }; + + template + struct unwrapped> { + typedef T type; + }; + + template + using unwrapped_t = typename unwrapped::type; + + template + struct unwrap_unqualified : unwrapped> {}; + + template + using unwrap_unqualified_t = typename unwrap_unqualified::type; + + template + struct remove_member_pointer; + + template + struct remove_member_pointer { + typedef R type; + }; + + template + struct remove_member_pointer { + typedef R type; + }; + + template + using remove_member_pointer_t = remove_member_pointer; + + template class Templ, typename T> + struct is_specialization_of : std::false_type { }; + template class Templ> + struct is_specialization_of> : std::true_type { }; + + template + struct all_same : std::true_type { }; + + template + struct all_same : std::integral_constant ::value && all_same::value> { }; + + template + struct any_same : std::false_type { }; + + template + struct any_same : std::integral_constant ::value || any_same::value> { }; + + template + using invoke_t = typename T::type; + + template + using boolean = std::integral_constant; + + template + using neg = boolean; + + template + using condition = std::conditional_t; + + template + struct all : boolean {}; + + template + struct all : condition, boolean> {}; + + template + struct any : boolean {}; + + template + struct any : condition, any> {}; + + enum class enable_t { + _ + }; + + constexpr const auto enabler = enable_t::_; + + template + using disable_if_t = std::enable_if_t; + + template + using enable = std::enable_if_t::value, enable_t>; + + template + using disable = std::enable_if_t>::value, enable_t>; + + template + using disable_any = std::enable_if_t>::value, enable_t>; + + template + struct find_in_pack_v : boolean { }; + + template + struct find_in_pack_v : any, find_in_pack_v> { }; + + namespace meta_detail { + template + struct index_in_pack : std::integral_constant { }; + + template + struct index_in_pack : std::conditional_t::value, std::integral_constant, index_in_pack> { }; + } + + template + struct index_in_pack : meta_detail::index_in_pack<0, T, Args...> { }; + + template + struct index_in : meta_detail::index_in_pack<0, T, List> { }; + + template + struct index_in> : meta_detail::index_in_pack<0, T, Args...> { }; + + template + struct at_in_pack {}; + + template + using at_in_pack_t = typename at_in_pack::type; + + template + struct at_in_pack : std::conditional> {}; + + template + struct at_in_pack<0, Arg, Args...> { typedef Arg type; }; + + namespace meta_detail { + template class Pred, typename... Ts> + struct count_for_pack : std::integral_constant {}; + template class Pred, typename T, typename... Ts> + struct count_for_pack : std::conditional_t < sizeof...(Ts) == 0 || Limit < 2, + std::integral_constant(Limit != 0 && Pred::value)>, + count_for_pack(Pred::value), Pred, Ts...> + > { }; + template class Pred, typename... Ts> + struct count_2_for_pack : std::integral_constant {}; + template class Pred, typename T, typename U, typename... Ts> + struct count_2_for_pack : std::conditional_t(Pred::value)>, + count_2_for_pack(Pred::value), Pred, Ts...> + > { }; + } // meta_detail + + template class Pred, typename... Ts> + struct count_for_pack : meta_detail::count_for_pack { }; + + template class Pred, typename List> + struct count_for; + + template class Pred, typename... Args> + struct count_for> : count_for_pack {}; + + template class Pred, typename... Ts> + struct count_for_to_pack : meta_detail::count_for_pack { }; + + template class Pred, typename... Ts> + struct count_2_for_pack : meta_detail::count_2_for_pack<0, Pred, Ts...> { }; + + template + struct return_type { + typedef std::tuple type; + }; + + template + struct return_type { + typedef T type; + }; + + template<> + struct return_type<> { + typedef void type; + }; + + template + using return_type_t = typename return_type::type; + + namespace meta_detail { + template struct always_true : std::true_type {}; + struct is_invokable_tester { + template + always_true()(std::declval()...))> static test(int); + template + std::false_type static test(...); + }; + } // meta_detail + + template + struct is_invokable; + template + struct is_invokable : decltype(meta_detail::is_invokable_tester::test(0)) {}; + + namespace meta_detail { + + template>::value> + struct is_callable : std::is_function> {}; + + template + struct is_callable { + using yes = char; + using no = struct { char s[2]; }; + + struct F { void operator()(); }; + struct Derived : T, F {}; + template struct Check; + + template + static no test(Check*); + + template + static yes test(...); + + static const bool value = sizeof(test(0)) == sizeof(yes); + }; + + struct has_begin_end_impl { + template, + typename B = decltype(std::declval().begin()), + typename E = decltype(std::declval().end())> + static std::true_type test(int); + + template + static std::false_type test(...); + }; + + struct has_key_value_pair_impl { + template, + typename V = typename U::value_type, + typename F = decltype(std::declval().first), + typename S = decltype(std::declval().second)> + static std::true_type test(int); + + template + static std::false_type test(...); + }; + + template () < std::declval())> + std::true_type supports_op_less_test(const T&); + std::false_type supports_op_less_test(...); + template () == std::declval())> + std::true_type supports_op_equal_test(const T&); + std::false_type supports_op_equal_test(...); + template () <= std::declval())> + std::true_type supports_op_less_equal_test(const T&); + std::false_type supports_op_less_equal_test(...); + + } // meta_detail + + template + using supports_op_less = decltype(meta_detail::supports_op_less_test(std::declval())); + template + using supports_op_equal = decltype(meta_detail::supports_op_equal_test(std::declval())); + template + using supports_op_less_equal = decltype(meta_detail::supports_op_less_equal_test(std::declval())); + + template + struct is_callable : boolean::value> {}; + + template + struct has_begin_end : decltype(meta_detail::has_begin_end_impl::test(0)) {}; + + template + struct has_key_value_pair : decltype(meta_detail::has_key_value_pair_impl::test(0)) {}; + + template + using is_string_constructible = any, const char*>, std::is_same, char>, std::is_same, std::string>, std::is_same, std::initializer_list>>; + + template + using is_c_str = any< + std::is_same>, const char*>, + std::is_same>, char*>, + std::is_same, std::string> + >; + + template + struct is_move_only : all< + neg>, + neg>>, + std::is_move_constructible> + > {}; + + template + using is_not_move_only = neg>; + + namespace meta_detail { + template >> = meta::enabler> + decltype(auto) force_tuple(T&& x) { + return std::forward_as_tuple(std::forward(x)); + } + + template >> = meta::enabler> + decltype(auto) force_tuple(T&& x) { + return std::forward(x); + } + } // meta_detail + + template + decltype(auto) tuplefy(X&&... x) { + return std::tuple_cat(meta_detail::force_tuple(std::forward(x))...); + } + } // meta + namespace detail { + template + decltype(auto) forward_get(Tuple&& tuple) { + return std::forward>(std::get(tuple)); + } + + template + auto forward_tuple_impl(std::index_sequence, Tuple&& tuple) -> decltype(std::tuple(tuple))...>(forward_get(tuple)...)) { + return std::tuple(tuple))...>(std::move(std::get(tuple))...); + } + + template + auto forward_tuple(Tuple&& tuple) { + auto x = forward_tuple_impl(std::make_index_sequence>::value>(), std::forward(tuple)); + return x; + } + + template + auto unwrap(T&& item) -> decltype(std::forward(item)) { + return std::forward(item); + } + + template + T& unwrap(std::reference_wrapper arg) { + return arg.get(); + } + + template + auto deref(T&& item) -> decltype(std::forward(item)) { + return std::forward(item); + } + + template + inline T& deref(T* item) { + return *item; + } + + template + inline std::add_lvalue_reference_t deref(std::unique_ptr& item) { + return *item; + } + + template + inline std::add_lvalue_reference_t deref(std::shared_ptr& item) { + return *item; + } + + template + inline std::add_lvalue_reference_t deref(const std::unique_ptr& item) { + return *item; + } + + template + inline std::add_lvalue_reference_t deref(const std::shared_ptr& item) { + return *item; + } + + template + inline T* ptr(T& val) { + return std::addressof(val); + } + + template + inline T* ptr(std::reference_wrapper val) { + return std::addressof(val.get()); + } + + template + inline T* ptr(T* val) { + return val; + } + } // detail +} // sol + +// end of sol/traits.hpp + +// beginning of sol/object.hpp + +// beginning of sol/reference.hpp + +// beginning of sol/types.hpp + +// beginning of sol/optional.hpp + +// beginning of sol/compatibility.hpp + +// beginning of sol/compatibility/version.hpp + +#ifdef SOL_USING_CXX_LUA +#include +#include +#include +#else +#ifndef lua_h +#include +#endif +#endif // C++ Mangling for Lua + +#if defined(_WIN32) || defined(_MSC_VER) +#ifndef SOL_CODECVT_SUPPORT +#define SOL_CODECVT_SUPPORT 1 +#endif // sol codecvt support +#elif defined(__GNUC__) +#if __GNUC__ >= 5 +#ifndef SOL_CODECVT_SUPPORT +#define SOL_CODECVT_SUPPORT 1 +#endif // codecvt support +#endif // g++ 5.x.x (MinGW too) +#else +#endif // Windows/VC++ vs. g++ vs Others + +#ifdef LUAJIT_VERSION +#ifndef SOL_LUAJIT +#define SOL_LUAJIT +#define SOL_LUAJIT_VERSION LUAJIT_VERSION_NUM +#endif // sol luajit +#endif // luajit + +#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 502 +#define SOL_LUA_VERSION LUA_VERSION_NUM +#elif defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501 +#define SOL_LUA_VERSION LUA_VERSION_NUM +#elif !defined(LUA_VERSION_NUM) +#define SOL_LUA_VERSION 500 +#else +#define SOL_LUA_VERSION 502 +#endif // Lua Version 502, 501 || luajit, 500 + +#ifdef _MSC_VER +#ifdef _DEBUG +#ifndef NDEBUG +#ifndef SOL_CHECK_ARGUMENTS +#endif // Check Arguments +#ifndef SOL_SAFE_USERTYPE +#define SOL_SAFE_USERTYPE +#endif // Safe Usertypes +#endif // NDEBUG +#endif // Debug + +#ifndef _CPPUNWIND +#ifndef SOL_NO_EXCEPTIONS +#define SOL_NO_EXCEPTIONS 1 +#endif +#endif // Automatic Exceptions + +#ifndef _CPPRTTI +#ifndef SOL_NO_RTTI +#define SOL_NO_RTTI 1 +#endif +#endif // Automatic RTTI + +#elif defined(__GNUC__) || defined(__clang__) + +#ifndef NDEBUG +#ifndef __OPTIMIZE__ +#ifndef SOL_CHECK_ARGUMENTS +#endif // Check Arguments +#ifndef SOL_SAFE_USERTYPE +#define SOL_SAFE_USERTYPE +#endif // Safe Usertypes +#endif // g++ optimizer flag +#endif // Not Debug + +#ifndef __EXCEPTIONS +#ifndef SOL_NO_EXCEPTIONS +#define SOL_NO_EXCEPTIONS 1 +#endif +#endif // No Exceptions + +#ifndef __GXX_RTTI +#ifndef SOL_NO_RTII +#define SOL_NO_RTTI 1 +#endif +#endif // No RTTI + +#endif // vc++ || clang++/g++ + +#ifndef SOL_SAFE_USERTYPE +#ifdef SOL_CHECK_ARGUMENTS +#define SOL_SAFE_USERTYPE +#endif // Turn on Safety for all +#endif // Safe Usertypes + +// end of sol/compatibility/version.hpp + +#ifndef SOL_NO_COMPAT + +#if defined(__cplusplus) && !defined(SOL_USING_CXX_LUA) +extern "C" { +#endif +// beginning of sol/compatibility/5.2.0.h + +#ifndef SOL_5_2_0_H +#define SOL_5_2_0_H + +#if SOL_LUA_VERSION < 503 + +inline int lua_isinteger(lua_State* L, int idx) { + if (lua_type(L, idx) != LUA_TNUMBER) + return 0; + // This is a very slipshod way to do the testing + // but lua_totingerx doesn't play ball nicely + // on older versions... + lua_Number n = lua_tonumber(L, idx); + lua_Integer i = lua_tointeger(L, idx); + if (i != n) + return 0; + // it's DEFINITELY an integer + return 1; +} + +#endif // SOL_LUA_VERSION == 502 +#endif // SOL_5_2_0_H +// end of sol/compatibility/5.2.0.h + +// beginning of sol/compatibility/5.1.0.h + +#ifndef SOL_5_1_0_H +#define SOL_5_1_0_H + +#if SOL_LUA_VERSION == 501 +/* Lua 5.1 */ + +#include +#include +#include + +/* LuaJIT doesn't define these unofficial macros ... */ +#if !defined(LUAI_INT32) +#include +#if INT_MAX-20 < 32760 +#define LUAI_INT32 long +#define LUAI_UINT32 unsigned long +#elif INT_MAX > 2147483640L +#define LUAI_INT32 int +#define LUAI_UINT32 unsigned int +#else +#error "could not detect suitable lua_Unsigned datatype" +#endif +#endif + +/* LuaJIT does not have the updated error codes for thread status/function returns */ +#ifndef LUA_ERRGCMM +#define LUA_ERRGCMM (LUA_ERRERR + 2) +#endif // LUA_ERRGCMM + +/* LuaJIT does not support continuation contexts / return error codes? */ +#ifndef LUA_KCONTEXT +#define LUA_KCONTEXT std::ptrdiff_t +typedef LUA_KCONTEXT lua_KContext; +typedef int(*lua_KFunction) (lua_State *L, int status, lua_KContext ctx); +#endif // LUA_KCONTEXT + +#define LUA_OPADD 0 +#define LUA_OPSUB 1 +#define LUA_OPMUL 2 +#define LUA_OPDIV 3 +#define LUA_OPMOD 4 +#define LUA_OPPOW 5 +#define LUA_OPUNM 6 +#define LUA_OPEQ 0 +#define LUA_OPLT 1 +#define LUA_OPLE 2 + +typedef LUAI_UINT32 lua_Unsigned; + +typedef struct luaL_Buffer_52 { + luaL_Buffer b; /* make incorrect code crash! */ + char *ptr; + size_t nelems; + size_t capacity; + lua_State *L2; +} luaL_Buffer_52; +#define luaL_Buffer luaL_Buffer_52 + +#define lua_tounsigned(L, i) lua_tounsignedx(L, i, NULL) + +#define lua_rawlen(L, i) lua_objlen(L, i) + +inline void lua_callk(lua_State *L, int nargs, int nresults, lua_KContext, lua_KFunction) { + // should probably warn the user of Lua 5.1 that continuation isn't supported... + lua_call(L, nargs, nresults); +} +inline int lua_pcallk(lua_State *L, int nargs, int nresults, int errfunc, lua_KContext, lua_KFunction) { + // should probably warn the user of Lua 5.1 that continuation isn't supported... + return lua_pcall(L, nargs, nresults, errfunc); +} +void lua_arith(lua_State *L, int op); +int lua_compare(lua_State *L, int idx1, int idx2, int op); +void lua_pushunsigned(lua_State *L, lua_Unsigned n); +lua_Unsigned luaL_checkunsigned(lua_State *L, int i); +lua_Unsigned lua_tounsignedx(lua_State *L, int i, int *isnum); +lua_Unsigned luaL_optunsigned(lua_State *L, int i, lua_Unsigned def); +lua_Integer lua_tointegerx(lua_State *L, int i, int *isnum); +void lua_len(lua_State *L, int i); +int luaL_len(lua_State *L, int i); +const char *luaL_tolstring(lua_State *L, int idx, size_t *len); +void luaL_requiref(lua_State *L, char const* modname, lua_CFunction openf, int glb); + +#define luaL_buffinit luaL_buffinit_52 +void luaL_buffinit(lua_State *L, luaL_Buffer_52 *B); + +#define luaL_prepbuffsize luaL_prepbuffsize_52 +char *luaL_prepbuffsize(luaL_Buffer_52 *B, size_t s); + +#define luaL_addlstring luaL_addlstring_52 +void luaL_addlstring(luaL_Buffer_52 *B, const char *s, size_t l); + +#define luaL_addvalue luaL_addvalue_52 +void luaL_addvalue(luaL_Buffer_52 *B); + +#define luaL_pushresult luaL_pushresult_52 +void luaL_pushresult(luaL_Buffer_52 *B); + +#undef luaL_buffinitsize +#define luaL_buffinitsize(L, B, s) \ + (luaL_buffinit(L, B), luaL_prepbuffsize(B, s)) + +#undef luaL_prepbuffer +#define luaL_prepbuffer(B) \ + luaL_prepbuffsize(B, LUAL_BUFFERSIZE) + +#undef luaL_addchar +#define luaL_addchar(B, c) \ + ((void)((B)->nelems < (B)->capacity || luaL_prepbuffsize(B, 1)), \ + ((B)->ptr[(B)->nelems++] = (c))) + +#undef luaL_addsize +#define luaL_addsize(B, s) \ + ((B)->nelems += (s)) + +#undef luaL_addstring +#define luaL_addstring(B, s) \ + luaL_addlstring(B, s, strlen(s)) + +#undef luaL_pushresultsize +#define luaL_pushresultsize(B, s) \ + (luaL_addsize(B, s), luaL_pushresult(B)) + +typedef struct kepler_lua_compat_get_string_view { + const char *s; + size_t size; +} kepler_lua_compat_get_string_view; + +inline const char* kepler_lua_compat_get_string(lua_State* L, void* ud, size_t* size) { + kepler_lua_compat_get_string_view* ls = (kepler_lua_compat_get_string_view*) ud; + (void)L; + if (ls->size == 0) return NULL; + *size = ls->size; + ls->size = 0; + return ls->s; +} + +#if !defined(SOL_LUAJIT) || (SOL_LUAJIT_VERSION < 20100) + +inline int luaL_loadbufferx(lua_State* L, const char* buff, size_t size, const char* name, const char*) { + kepler_lua_compat_get_string_view ls; + ls.s = buff; + ls.size = size; + return lua_load(L, kepler_lua_compat_get_string, &ls, name/*, mode*/); +} + +#endif // LuaJIT 2.1.x beta and beyond + +#endif /* Lua 5.1 */ + +#endif // SOL_5_1_0_H +// end of sol/compatibility/5.1.0.h + +// beginning of sol/compatibility/5.0.0.h + +#ifndef SOL_5_0_0_H +#define SOL_5_0_0_H + +#if SOL_LUA_VERSION < 501 +/* Lua 5.0 */ + +#define LUA_QL(x) "'" x "'" +#define LUA_QS LUA_QL("%s") + +#define luaL_Reg luaL_reg + +#define luaL_opt(L, f, n, d) \ + (lua_isnoneornil(L, n) ? (d) : f(L, n)) + +#define luaL_addchar(B,c) \ + ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ + (*(B)->p++ = (char)(c))) + +#endif // Lua 5.0 + +#endif // SOL_5_0_0_H +// end of sol/compatibility/5.0.0.h + +// beginning of sol/compatibility/5.x.x.h + +#ifndef SOL_5_X_X_H +#define SOL_5_X_X_H + +#if SOL_LUA_VERSION < 502 + +#define LUA_RIDX_GLOBALS LUA_GLOBALSINDEX + +#define LUA_OK 0 + +#define lua_pushglobaltable(L) \ + lua_pushvalue(L, LUA_GLOBALSINDEX) + +#define luaL_newlib(L, l) \ + (lua_newtable((L)),luaL_setfuncs((L), (l), 0)) + +void luaL_checkversion(lua_State *L); + +int lua_absindex(lua_State *L, int i); +void lua_copy(lua_State *L, int from, int to); +void lua_rawgetp(lua_State *L, int i, const void *p); +void lua_rawsetp(lua_State *L, int i, const void *p); +void *luaL_testudata(lua_State *L, int i, const char *tname); +lua_Number lua_tonumberx(lua_State *L, int i, int *isnum); +void lua_getuservalue(lua_State *L, int i); +void lua_setuservalue(lua_State *L, int i); +void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup); +void luaL_setmetatable(lua_State *L, const char *tname); +int luaL_getsubtable(lua_State *L, int i, const char *name); +void luaL_traceback(lua_State *L, lua_State *L1, const char *msg, int level); +int luaL_fileresult(lua_State *L, int stat, const char *fname); + +#endif // Lua 5.1 and below + +#endif // SOL_5_X_X_H +// end of sol/compatibility/5.x.x.h + +// beginning of sol/compatibility/5.x.x.inl + +#ifndef SOL_5_X_X_INL +#define SOL_5_X_X_INL + +#if SOL_LUA_VERSION < 502 + +#include + +#define PACKAGE_KEY "_sol.package" + +inline int lua_absindex(lua_State *L, int i) { + if (i < 0 && i > LUA_REGISTRYINDEX) + i += lua_gettop(L) + 1; + return i; +} + +inline void lua_copy(lua_State *L, int from, int to) { + int abs_to = lua_absindex(L, to); + luaL_checkstack(L, 1, "not enough stack slots"); + lua_pushvalue(L, from); + lua_replace(L, abs_to); +} + +inline void lua_rawgetp(lua_State *L, int i, const void *p) { + int abs_i = lua_absindex(L, i); + lua_pushlightuserdata(L, (void*)p); + lua_rawget(L, abs_i); +} + +inline void lua_rawsetp(lua_State *L, int i, const void *p) { + int abs_i = lua_absindex(L, i); + luaL_checkstack(L, 1, "not enough stack slots"); + lua_pushlightuserdata(L, (void*)p); + lua_insert(L, -2); + lua_rawset(L, abs_i); +} + +inline void *luaL_testudata(lua_State *L, int i, const char *tname) { + void *p = lua_touserdata(L, i); + luaL_checkstack(L, 2, "not enough stack slots"); + if (p == NULL || !lua_getmetatable(L, i)) + return NULL; + else { + int res = 0; + luaL_getmetatable(L, tname); + res = lua_rawequal(L, -1, -2); + lua_pop(L, 2); + if (!res) + p = NULL; + } + return p; +} + +inline lua_Number lua_tonumberx(lua_State *L, int i, int *isnum) { + lua_Number n = lua_tonumber(L, i); + if (isnum != NULL) { + *isnum = (n != 0 || lua_isnumber(L, i)); + } + return n; +} + +inline static void push_package_table(lua_State *L) { + lua_pushliteral(L, PACKAGE_KEY); + lua_rawget(L, LUA_REGISTRYINDEX); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + /* try to get package table from globals */ + lua_pushliteral(L, "package"); + lua_rawget(L, LUA_GLOBALSINDEX); + if (lua_istable(L, -1)) { + lua_pushliteral(L, PACKAGE_KEY); + lua_pushvalue(L, -2); + lua_rawset(L, LUA_REGISTRYINDEX); + } + } +} + +inline void lua_getuservalue(lua_State *L, int i) { + luaL_checktype(L, i, LUA_TUSERDATA); + luaL_checkstack(L, 2, "not enough stack slots"); + lua_getfenv(L, i); + lua_pushvalue(L, LUA_GLOBALSINDEX); + if (lua_rawequal(L, -1, -2)) { + lua_pop(L, 1); + lua_pushnil(L); + lua_replace(L, -2); + } + else { + lua_pop(L, 1); + push_package_table(L); + if (lua_rawequal(L, -1, -2)) { + lua_pop(L, 1); + lua_pushnil(L); + lua_replace(L, -2); + } + else + lua_pop(L, 1); + } +} + +inline void lua_setuservalue(lua_State *L, int i) { + luaL_checktype(L, i, LUA_TUSERDATA); + if (lua_isnil(L, -1)) { + luaL_checkstack(L, 1, "not enough stack slots"); + lua_pushvalue(L, LUA_GLOBALSINDEX); + lua_replace(L, -2); + } + lua_setfenv(L, i); +} + +/* +** Adapted from Lua 5.2.0 +*/ +inline void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup) { + luaL_checkstack(L, nup + 1, "too many upvalues"); + for (; l->name != NULL; l++) { /* fill the table with given functions */ + int i; + lua_pushstring(L, l->name); + for (i = 0; i < nup; i++) /* copy upvalues to the top */ + lua_pushvalue(L, -(nup + 1)); + lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ + lua_settable(L, -(nup + 3)); /* table must be below the upvalues, the name and the closure */ + } + lua_pop(L, nup); /* remove upvalues */ +} + +inline void luaL_setmetatable(lua_State *L, const char *tname) { + luaL_checkstack(L, 1, "not enough stack slots"); + luaL_getmetatable(L, tname); + lua_setmetatable(L, -2); +} + +inline int luaL_getsubtable(lua_State *L, int i, const char *name) { + int abs_i = lua_absindex(L, i); + luaL_checkstack(L, 3, "not enough stack slots"); + lua_pushstring(L, name); + lua_gettable(L, abs_i); + if (lua_istable(L, -1)) + return 1; + lua_pop(L, 1); + lua_newtable(L); + lua_pushstring(L, name); + lua_pushvalue(L, -2); + lua_settable(L, abs_i); + return 0; +} + +#ifndef SOL_LUAJIT +inline static int countlevels(lua_State *L) { + lua_Debug ar; + int li = 1, le = 1; + /* find an upper bound */ + while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } + /* do a binary search */ + while (li < le) { + int m = (li + le) / 2; + if (lua_getstack(L, m, &ar)) li = m + 1; + else le = m; + } + return le - 1; +} + +inline static int findfield(lua_State *L, int objidx, int level) { + if (level == 0 || !lua_istable(L, -1)) + return 0; /* not found */ + lua_pushnil(L); /* start 'next' loop */ + while (lua_next(L, -2)) { /* for each pair in table */ + if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ + if (lua_rawequal(L, objidx, -1)) { /* found object? */ + lua_pop(L, 1); /* remove value (but keep name) */ + return 1; + } + else if (findfield(L, objidx, level - 1)) { /* try recursively */ + lua_remove(L, -2); /* remove table (but keep name) */ + lua_pushliteral(L, "."); + lua_insert(L, -2); /* place '.' between the two names */ + lua_concat(L, 3); + return 1; + } + } + lua_pop(L, 1); /* remove value */ + } + return 0; /* not found */ +} + +inline static int pushglobalfuncname(lua_State *L, lua_Debug *ar) { + int top = lua_gettop(L); + lua_getinfo(L, "f", ar); /* push function */ + lua_pushvalue(L, LUA_GLOBALSINDEX); + if (findfield(L, top + 1, 2)) { + lua_copy(L, -1, top + 1); /* move name to proper place */ + lua_pop(L, 2); /* remove pushed values */ + return 1; + } + else { + lua_settop(L, top); /* remove function and global table */ + return 0; + } +} + +inline static void pushfuncname(lua_State *L, lua_Debug *ar) { + if (*ar->namewhat != '\0') /* is there a name? */ + lua_pushfstring(L, "function " LUA_QS, ar->name); + else if (*ar->what == 'm') /* main? */ + lua_pushliteral(L, "main chunk"); + else if (*ar->what == 'C') { + if (pushglobalfuncname(L, ar)) { + lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1)); + lua_remove(L, -2); /* remove name */ + } + else + lua_pushliteral(L, "?"); + } + else + lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); +} + +#define LEVELS1 12 /* size of the first part of the stack */ +#define LEVELS2 10 /* size of the second part of the stack */ + +inline void luaL_traceback(lua_State *L, lua_State *L1, + const char *msg, int level) { + lua_Debug ar; + int top = lua_gettop(L); + int numlevels = countlevels(L1); + int mark = (numlevels > LEVELS1 + LEVELS2) ? LEVELS1 : 0; + if (msg) lua_pushfstring(L, "%s\n", msg); + lua_pushliteral(L, "stack traceback:"); + while (lua_getstack(L1, level++, &ar)) { + if (level == mark) { /* too many levels? */ + lua_pushliteral(L, "\n\t..."); /* add a '...' */ + level = numlevels - LEVELS2; /* and skip to last ones */ + } + else { + lua_getinfo(L1, "Slnt", &ar); + lua_pushfstring(L, "\n\t%s:", ar.short_src); + if (ar.currentline > 0) + lua_pushfstring(L, "%d:", ar.currentline); + lua_pushliteral(L, " in "); + pushfuncname(L, &ar); + lua_concat(L, lua_gettop(L) - top); + } + } + lua_concat(L, lua_gettop(L) - top); +} +#endif + +inline const lua_Number *lua_version(lua_State *L) { + static const lua_Number version = LUA_VERSION_NUM; + if (L == NULL) return &version; + // TODO: wonky hacks to get at the inside of the incomplete type lua_State? + //else return L->l_G->version; + else return &version; +} + +inline static void luaL_checkversion_(lua_State *L, lua_Number ver) { + const lua_Number* v = lua_version(L); + if (v != lua_version(NULL)) + luaL_error(L, "multiple Lua VMs detected"); + else if (*v != ver) + luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", + ver, *v); + /* check conversions number -> integer types */ + lua_pushnumber(L, -(lua_Number)0x1234); + if (lua_tointeger(L, -1) != -0x1234 || + lua_tounsigned(L, -1) != (lua_Unsigned)-0x1234) + luaL_error(L, "bad conversion number->int;" + " must recompile Lua with proper settings"); + lua_pop(L, 1); +} + +inline void luaL_checkversion(lua_State* L) { + luaL_checkversion_(L, LUA_VERSION_NUM); +} + +#ifndef SOL_LUAJIT +inline int luaL_fileresult(lua_State *L, int stat, const char *fname) { + int en = errno; /* calls to Lua API may change this value */ + if (stat) { + lua_pushboolean(L, 1); + return 1; + } + else { + char buf[1024]; +#if defined(__GLIBC__) || defined(_POSIX_VERSION) + strerror_r(en, buf, 1024); +#else + strerror_s(buf, 1024, en); +#endif + lua_pushnil(L); + if (fname) + lua_pushfstring(L, "%s: %s", fname, buf); + else + lua_pushstring(L, buf); + lua_pushnumber(L, (lua_Number)en); + return 3; + } +} +#endif // luajit +#endif // Lua 5.0 or Lua 5.1 + +#if SOL_LUA_VERSION == 501 + +typedef LUAI_INT32 LUA_INT32; + +/********************************************************************/ +/* extract of 5.2's luaconf.h */ +/* detects proper defines for faster unsigned<->number conversion */ +/* see copyright notice at the end of this file */ +/********************************************************************/ + +#if !defined(LUA_ANSI) && defined(_WIN32) && !defined(_WIN32_WCE) +#define LUA_WIN /* enable goodies for regular Windows platforms */ +#endif + +#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */ + +/* Microsoft compiler on a Pentium (32 bit) ? */ +#if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */ + +#define LUA_MSASMTRICK +#define LUA_IEEEENDIAN 0 +#define LUA_NANTRICK + +/* pentium 32 bits? */ +#elif defined(__i386__) || defined(__i386) || defined(__X86__) /* }{ */ + +#define LUA_IEEE754TRICK +#define LUA_IEEELL +#define LUA_IEEEENDIAN 0 +#define LUA_NANTRICK + +/* pentium 64 bits? */ +#elif defined(__x86_64) /* }{ */ + +#define LUA_IEEE754TRICK +#define LUA_IEEEENDIAN 0 + +#elif defined(__POWERPC__) || defined(__ppc__) /* }{ */ + +#define LUA_IEEE754TRICK +#define LUA_IEEEENDIAN 1 + +#else /* }{ */ + +/* assume IEEE754 and a 32-bit integer type */ +#define LUA_IEEE754TRICK + +#endif /* } */ + +#endif /* } */ + +/********************************************************************/ +/* extract of 5.2's llimits.h */ +/* gives us lua_number2unsigned and lua_unsigned2number */ +/* see copyright notice just below this one here */ +/********************************************************************/ + +/********************************************************************* +* This file contains parts of Lua 5.2's source code: +* +* Copyright (C) 1994-2013 Lua.org, PUC-Rio. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*********************************************************************/ + +#if defined(MS_ASMTRICK) || defined(LUA_MSASMTRICK) /* { */ +/* trick with Microsoft assembler for X86 */ + +#define lua_number2unsigned(i,n) \ + {__int64 l; __asm {__asm fld n __asm fistp l} i = (unsigned int)l;} + +#elif defined(LUA_IEEE754TRICK) /* }{ */ +/* the next trick should work on any machine using IEEE754 with +a 32-bit int type */ + +union compat52_luai_Cast { double l_d; LUA_INT32 l_p[2]; }; + +#if !defined(LUA_IEEEENDIAN) /* { */ +#define LUAI_EXTRAIEEE \ + static const union compat52_luai_Cast ieeeendian = {-(33.0 + 6755399441055744.0)}; +#define LUA_IEEEENDIANLOC (ieeeendian.l_p[1] == 33) +#else +#define LUA_IEEEENDIANLOC LUA_IEEEENDIAN +#define LUAI_EXTRAIEEE /* empty */ +#endif /* } */ + +#define lua_number2int32(i,n,t) \ + { LUAI_EXTRAIEEE \ + volatile union compat52_luai_Cast u; u.l_d = (n) + 6755399441055744.0; \ + (i) = (t)u.l_p[LUA_IEEEENDIANLOC]; } + +#define lua_number2unsigned(i,n) lua_number2int32(i, n, lua_Unsigned) + +#endif /* } */ + +/* the following definitions always work, but may be slow */ + +#if !defined(lua_number2unsigned) /* { */ +/* the following definition assures proper modulo behavior */ +#if defined(LUA_NUMBER_DOUBLE) || defined(LUA_NUMBER_FLOAT) +#include +#define SUPUNSIGNED ((lua_Number)(~(lua_Unsigned)0) + 1) +#define lua_number2unsigned(i,n) \ + ((i)=(lua_Unsigned)((n) - floor((n)/SUPUNSIGNED)*SUPUNSIGNED)) +#else +#define lua_number2unsigned(i,n) ((i)=(lua_Unsigned)(n)) +#endif +#endif /* } */ + +#if !defined(lua_unsigned2number) +/* on several machines, coercion from unsigned to double is slow, +so it may be worth to avoid */ +#define lua_unsigned2number(u) \ + (((u) <= (lua_Unsigned)INT_MAX) ? (lua_Number)(int)(u) : (lua_Number)(u)) +#endif + +/********************************************************************/ + +inline static void compat52_call_lua(lua_State *L, char const code[], size_t len, + int nargs, int nret) { + lua_rawgetp(L, LUA_REGISTRYINDEX, (void*)code); + if (lua_type(L, -1) != LUA_TFUNCTION) { + lua_pop(L, 1); + if (luaL_loadbuffer(L, code, len, "=none")) + lua_error(L); + lua_pushvalue(L, -1); + lua_rawsetp(L, LUA_REGISTRYINDEX, (void*)code); + } + lua_insert(L, -nargs - 1); + lua_call(L, nargs, nret); +} + +static const char compat52_arith_code[] = { + "local op,a,b=...\n" + "if op==0 then return a+b\n" + "elseif op==1 then return a-b\n" + "elseif op==2 then return a*b\n" + "elseif op==3 then return a/b\n" + "elseif op==4 then return a%b\n" + "elseif op==5 then return a^b\n" + "elseif op==6 then return -a\n" + "end\n" +}; + +inline void lua_arith(lua_State *L, int op) { + if (op < LUA_OPADD || op > LUA_OPUNM) + luaL_error(L, "invalid 'op' argument for lua_arith"); + luaL_checkstack(L, 5, "not enough stack slots"); + if (op == LUA_OPUNM) + lua_pushvalue(L, -1); + lua_pushnumber(L, op); + lua_insert(L, -3); + compat52_call_lua(L, compat52_arith_code, + sizeof(compat52_arith_code) - 1, 3, 1); +} + +static const char compat52_compare_code[] = { + "local a,b=...\n" + "return a<=b\n" +}; + +inline int lua_compare(lua_State *L, int idx1, int idx2, int op) { + int result = 0; + switch (op) { + case LUA_OPEQ: + return lua_equal(L, idx1, idx2); + case LUA_OPLT: + return lua_lessthan(L, idx1, idx2); + case LUA_OPLE: + luaL_checkstack(L, 5, "not enough stack slots"); + idx1 = lua_absindex(L, idx1); + idx2 = lua_absindex(L, idx2); + lua_pushvalue(L, idx1); + lua_pushvalue(L, idx2); + compat52_call_lua(L, compat52_compare_code, + sizeof(compat52_compare_code) - 1, 2, 1); + result = lua_toboolean(L, -1); + lua_pop(L, 1); + return result; + default: + luaL_error(L, "invalid 'op' argument for lua_compare"); + } + return 0; +} + +inline void lua_pushunsigned(lua_State *L, lua_Unsigned n) { + lua_pushnumber(L, lua_unsigned2number(n)); +} + +inline lua_Unsigned luaL_checkunsigned(lua_State *L, int i) { + lua_Unsigned result; + lua_Number n = lua_tonumber(L, i); + if (n == 0 && !lua_isnumber(L, i)) + luaL_checktype(L, i, LUA_TNUMBER); + lua_number2unsigned(result, n); + return result; +} + +inline lua_Unsigned lua_tounsignedx(lua_State *L, int i, int *isnum) { + lua_Unsigned result; + lua_Number n = lua_tonumberx(L, i, isnum); + lua_number2unsigned(result, n); + return result; +} + +inline lua_Unsigned luaL_optunsigned(lua_State *L, int i, lua_Unsigned def) { + return luaL_opt(L, luaL_checkunsigned, i, def); +} + +inline lua_Integer lua_tointegerx(lua_State *L, int i, int *isnum) { + lua_Integer n = lua_tointeger(L, i); + if (isnum != NULL) { + *isnum = (n != 0 || lua_isnumber(L, i)); + } + return n; +} + +inline void lua_len(lua_State *L, int i) { + switch (lua_type(L, i)) { + case LUA_TSTRING: /* fall through */ + case LUA_TTABLE: + if (!luaL_callmeta(L, i, "__len")) + lua_pushnumber(L, (int)lua_objlen(L, i)); + break; + case LUA_TUSERDATA: + if (luaL_callmeta(L, i, "__len")) + break; + /* maybe fall through */ + default: + luaL_error(L, "attempt to get length of a %s value", + lua_typename(L, lua_type(L, i))); + } +} + +inline int luaL_len(lua_State *L, int i) { + int res = 0, isnum = 0; + luaL_checkstack(L, 1, "not enough stack slots"); + lua_len(L, i); + res = (int)lua_tointegerx(L, -1, &isnum); + lua_pop(L, 1); + if (!isnum) + luaL_error(L, "object length is not a number"); + return res; +} + +inline const char *luaL_tolstring(lua_State *L, int idx, size_t *len) { + if (!luaL_callmeta(L, idx, "__tostring")) { + int t = lua_type(L, idx); + switch (t) { + case LUA_TNIL: + lua_pushliteral(L, "nil"); + break; + case LUA_TSTRING: + case LUA_TNUMBER: + lua_pushvalue(L, idx); + break; + case LUA_TBOOLEAN: + if (lua_toboolean(L, idx)) + lua_pushliteral(L, "true"); + else + lua_pushliteral(L, "false"); + break; + default: + lua_pushfstring(L, "%s: %p", lua_typename(L, t), + lua_topointer(L, idx)); + break; + } + } + return lua_tolstring(L, -1, len); +} + +inline void luaL_requiref(lua_State *L, char const* modname, + lua_CFunction openf, int glb) { + luaL_checkstack(L, 3, "not enough stack slots"); + lua_pushcfunction(L, openf); + lua_pushstring(L, modname); + lua_call(L, 1, 1); + lua_getglobal(L, "package"); + if (lua_istable(L, -1) == 0) { + lua_pop(L, 1); + lua_createtable(L, 0, 16); + lua_setglobal(L, "package"); + lua_getglobal(L, "package"); + } + lua_getfield(L, -1, "loaded"); + if (lua_istable(L, -1) == 0) { + lua_pop(L, 1); + lua_createtable(L, 0, 1); + lua_setfield(L, -2, "loaded"); + lua_getfield(L, -1, "loaded"); + } + lua_replace(L, -2); + lua_pushvalue(L, -2); + lua_setfield(L, -2, modname); + lua_pop(L, 1); + if (glb) { + lua_pushvalue(L, -1); + lua_setglobal(L, modname); + } +} + +inline void luaL_buffinit(lua_State *L, luaL_Buffer_52 *B) { + /* make it crash if used via pointer to a 5.1-style luaL_Buffer */ + B->b.p = NULL; + B->b.L = NULL; + B->b.lvl = 0; + /* reuse the buffer from the 5.1-style luaL_Buffer though! */ + B->ptr = B->b.buffer; + B->capacity = LUAL_BUFFERSIZE; + B->nelems = 0; + B->L2 = L; +} + +inline char *luaL_prepbuffsize(luaL_Buffer_52 *B, size_t s) { + if (B->capacity - B->nelems < s) { /* needs to grow */ + char* newptr = NULL; + size_t newcap = B->capacity * 2; + if (newcap - B->nelems < s) + newcap = B->nelems + s; + if (newcap < B->capacity) /* overflow */ + luaL_error(B->L2, "buffer too large"); + newptr = (char*)lua_newuserdata(B->L2, newcap); + memcpy(newptr, B->ptr, B->nelems); + if (B->ptr != B->b.buffer) + lua_replace(B->L2, -2); /* remove old buffer */ + B->ptr = newptr; + B->capacity = newcap; + } + return B->ptr + B->nelems; +} + +inline void luaL_addlstring(luaL_Buffer_52 *B, const char *s, size_t l) { + memcpy(luaL_prepbuffsize(B, l), s, l); + luaL_addsize(B, l); +} + +inline void luaL_addvalue(luaL_Buffer_52 *B) { + size_t len = 0; + const char *s = lua_tolstring(B->L2, -1, &len); + if (!s) + luaL_error(B->L2, "cannot convert value to string"); + if (B->ptr != B->b.buffer) + lua_insert(B->L2, -2); /* userdata buffer must be at stack top */ + luaL_addlstring(B, s, len); + lua_remove(B->L2, B->ptr != B->b.buffer ? -2 : -1); +} + +inline void luaL_pushresult(luaL_Buffer_52 *B) { + lua_pushlstring(B->L2, B->ptr, B->nelems); + if (B->ptr != B->b.buffer) + lua_replace(B->L2, -2); /* remove userdata buffer */ +} + +#endif /* SOL_LUA_VERSION == 501 */ + +#endif // SOL_5_X_X_INL +// end of sol/compatibility/5.x.x.inl + +#if defined(__cplusplus) && !defined(SOL_USING_CXX_LUA) +} +#endif + +#endif // SOL_NO_COMPAT + +// end of sol/compatibility.hpp + +// beginning of sol/in_place.hpp + +namespace sol { + + namespace detail { + struct in_place_of {}; + template + struct in_place_of_i {}; + template + struct in_place_of_t {}; + } // detail + + struct in_place_tag { struct init {}; constexpr in_place_tag(init) {} in_place_tag() = delete; }; + constexpr inline in_place_tag in_place(detail::in_place_of) { return in_place_tag(in_place_tag::init()); } + template + constexpr inline in_place_tag in_place(detail::in_place_of_t) { return in_place_tag(in_place_tag::init()); } + template + constexpr inline in_place_tag in_place(detail::in_place_of_i) { return in_place_tag(in_place_tag::init()); } + + using in_place_t = in_place_tag(&)(detail::in_place_of); + template + using in_place_type_t = in_place_tag(&)(detail::in_place_of_t); + template + using in_place_index_t = in_place_tag(&)(detail::in_place_of_i); + +} // sol + +// end of sol/in_place.hpp + +#if defined(SOL_USE_BOOST) +#include +#else +// beginning of sol/optional_implementation.hpp + +# ifndef SOL_OPTIONAL_IMPLEMENTATION_HPP +# define SOL_OPTIONAL_IMPLEMENTATION_HPP + +# include +# include +# include +# include +# include +# include +# include +#ifdef SOL_NO_EXCEPTIONS +#include +#endif // Exceptions + +# define TR2_OPTIONAL_REQUIRES(...) typename ::std::enable_if<__VA_ARGS__::value, bool>::type = false + +# if defined __GNUC__ // NOTE: GNUC is also defined for Clang +# if (__GNUC__ >= 5) +# define TR2_OPTIONAL_GCC_5_0_AND_HIGHER___ +# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ +# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8) +# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ +# elif (__GNUC__ > 4) +# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ +# endif +# +# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7) +# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ +# elif (__GNUC__ > 4) +# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ +# endif +# +# if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ >= 1) +# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9) +# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# elif (__GNUC__ > 4) +# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# endif +# endif +# +# if defined __clang_major__ +# if (__clang_major__ == 3 && __clang_minor__ >= 5) +# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ +# elif (__clang_major__ > 3) +# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ +# endif +# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ +# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ +# elif (__clang_major__ == 3 && __clang_minor__ == 4 && __clang_patchlevel__ >= 2) +# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ +# endif +# endif +# +# if defined _MSC_VER +# if (_MSC_VER >= 1900) +# define TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ +# endif +# endif + +# if defined __clang__ +# if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9) +# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 +# else +# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 +# endif +# elif defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 +# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ +# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 +# else +# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 +# endif + +# if defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ +# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1 +# define OPTIONAL_CONSTEXPR_INIT_LIST constexpr +# else +# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0 +# define OPTIONAL_CONSTEXPR_INIT_LIST +# endif + +# if defined(TR2_OPTIONAL_MSVC_2015_AND_HIGHER___) || (defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ && (defined __cplusplus) && (__cplusplus != 201103L)) +# define OPTIONAL_HAS_MOVE_ACCESSORS 1 +# else +# define OPTIONAL_HAS_MOVE_ACCESSORS 0 +# endif + +# // In C++11 constexpr implies const, so we need to make non-const members also non-constexpr +# if defined(TR2_OPTIONAL_MSVC_2015_AND_HIGHER___) || ((defined __cplusplus) && (__cplusplus == 201103L)) +# define OPTIONAL_MUTABLE_CONSTEXPR +# else +# define OPTIONAL_MUTABLE_CONSTEXPR constexpr +# endif + +# if defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ +#pragma warning( push ) +#pragma warning( disable : 4814 ) +#endif + +namespace sol { + + // BEGIN workaround for missing is_trivially_destructible +# if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ + // leave it: it is already there +# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ + // leave it: it is already there +# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ + // leave it: it is already there +# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS + // leave it: the user doesn't want it +# else + template + using is_trivially_destructible = ::std::has_trivial_destructor; +# endif + // END workaround for missing is_trivially_destructible + +# if (defined TR2_OPTIONAL_GCC_4_7_AND_HIGHER___) + // leave it; our metafunctions are already defined. +# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ + // leave it; our metafunctions are already defined. +# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ + // leave it: it is already there +# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS + // leave it: the user doesn't want it +# else + + template + struct is_nothrow_move_constructible + { + constexpr static bool value = ::std::is_nothrow_constructible::value; + }; + + template + struct is_assignable + { + template + constexpr static bool has_assign(...) { return false; } + + template () = ::std::declval(), true)) > + // the comma operator is necessary for the cases where operator= returns void + constexpr static bool has_assign(bool) { return true; } + + constexpr static bool value = has_assign(true); + }; + + template + struct is_nothrow_move_assignable + { + template + struct has_nothrow_move_assign { + constexpr static bool value = false; + }; + + template + struct has_nothrow_move_assign { + constexpr static bool value = noexcept(::std::declval() = ::std::declval()); + }; + + constexpr static bool value = has_nothrow_move_assign::value>::value; + }; + // end workaround + +# endif + + template class optional; + + // 20.5.5, optional for lvalue reference types + template class optional; + + // workaround: std utility functions aren't constexpr yet + template inline constexpr T&& constexpr_forward(typename ::std::remove_reference::type& t) noexcept + { + return static_cast(t); + } + + template inline constexpr T&& constexpr_forward(typename ::std::remove_reference::type&& t) noexcept + { + static_assert(!::std::is_lvalue_reference::value, "!!"); + return static_cast(t); + } + + template inline constexpr typename ::std::remove_reference::type&& constexpr_move(T&& t) noexcept + { + return static_cast::type&&>(t); + } + +#if defined NDEBUG +# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR) +#else +# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{assert(!#CHECK);}(), (EXPR))) +#endif + + namespace detail_ + { + + // static_addressof: a constexpr version of addressof + template + struct has_overloaded_addressof + { + template + constexpr static bool has_overload(...) { return false; } + + template ().operator&()) > + constexpr static bool has_overload(bool) { return true; } + + constexpr static bool value = has_overload(true); + }; + + template )> + constexpr T* static_addressof(T& ref) + { + return &ref; + } + + template )> + T* static_addressof(T& ref) + { + return ::std::addressof(ref); + } + + // the call to convert(b) has return type A and converts b to type A iff b decltype(b) is implicitly convertible to A + template + constexpr U convert(U v) { return v; } + + } // namespace detail_ + + constexpr struct trivial_init_t {} trivial_init{}; + + // 20.5.7, Disengaged state indicator + struct nullopt_t + { + struct init {}; + constexpr explicit nullopt_t(init) {} + }; + constexpr nullopt_t nullopt{ nullopt_t::init() }; + + // 20.5.8, class bad_optional_access + class bad_optional_access : public ::std::logic_error { + public: + explicit bad_optional_access(const ::std::string& what_arg) : ::std::logic_error{ what_arg } {} + explicit bad_optional_access(const char* what_arg) : ::std::logic_error{ what_arg } {} + }; + + template + struct alignas(T) optional_base { + char storage_[sizeof(T)]; + bool init_; + + constexpr optional_base() noexcept : storage_(), init_(false) {}; + + explicit optional_base(const T& v) : storage_(), init_(true) { + new (&storage())T(v); + } + + explicit optional_base(T&& v) : storage_(), init_(true) { + new (&storage())T(constexpr_move(v)); + } + + template explicit optional_base(in_place_t, Args&&... args) + : init_(true), storage_() { + new (&storage())T(constexpr_forward(args)...); + } + + template >)> + explicit optional_base(in_place_t, ::std::initializer_list il, Args&&... args) + : init_(true), storage_() { + new (&storage())T(il, constexpr_forward(args)...); + } +#if defined __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif + T& storage() { + return *reinterpret_cast(&storage_[0]); + } + + constexpr const T& storage() const { + return *reinterpret_cast(&storage_[0]); + } +#if defined __GNUC__ +#pragma GCC diagnostic pop +#endif + + ~optional_base() { if (init_) { storage().T::~T(); } } + }; + +#if defined __GNUC__ && !defined TR2_OPTIONAL_GCC_5_0_AND_HIGHER___ + // Sorry, GCC 4.x; you're just a piece of shit + template + using constexpr_optional_base = optional_base; +#else + template + struct alignas(T) constexpr_optional_base { + char storage_[sizeof(T)]; + bool init_; + constexpr constexpr_optional_base() noexcept : storage_(), init_(false) {} + + explicit constexpr constexpr_optional_base(const T& v) : storage_(), init_(true) { + new (&storage())T(v); + } + + explicit constexpr constexpr_optional_base(T&& v) : storage_(), init_(true) { + new (&storage())T(constexpr_move(v)); + } + + template explicit constexpr constexpr_optional_base(in_place_t, Args&&... args) + : init_(true), storage_() { + new (&storage())T(constexpr_forward(args)...); + } + + template >)> + OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, ::std::initializer_list il, Args&&... args) + : init_(true), storage_() { + new (&storage())T(il, constexpr_forward(args)...); + } + +#if defined __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif + T& storage() { + return (*reinterpret_cast(&storage_[0])); + } + + constexpr const T& storage() const { + return (*reinterpret_cast(&storage_[0])); + } +#if defined __GNUC__ +#pragma GCC diagnostic pop +#endif + + ~constexpr_optional_base() = default; + }; +#endif + + template + using OptionalBase = typename ::std::conditional< + ::std::is_trivially_destructible::value, + constexpr_optional_base::type>, + optional_base::type> + >::type; + + template + class optional : private OptionalBase + { + static_assert(!::std::is_same::type, nullopt_t>::value, "bad T"); + static_assert(!::std::is_same::type, in_place_t>::value, "bad T"); + + constexpr bool initialized() const noexcept { return OptionalBase::init_; } + typename ::std::remove_const::type* dataptr() { return ::std::addressof(OptionalBase::storage()); } + constexpr const T* dataptr() const { return detail_::static_addressof(OptionalBase::storage()); } + +# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 + constexpr const T& contained_val() const& { return OptionalBase::storage(); } +# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 + OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && { return ::std::move(OptionalBase::storage()); } + OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & { return OptionalBase::storage(); } +# else + T& contained_val() & { return OptionalBase::storage(); } + T&& contained_val() && { return ::std::move(OptionalBase::storage()); } +# endif +# else + constexpr const T& contained_val() const { return OptionalBase::storage(); } + T& contained_val() { return OptionalBase::storage(); } +# endif + + void clear() noexcept { + if (initialized()) dataptr()->T::~T(); + OptionalBase::init_ = false; + } + + template + void initialize(Args&&... args) noexcept(noexcept(T(::std::forward(args)...))) + { + assert(!OptionalBase::init_); + ::new (static_cast(dataptr())) T(::std::forward(args)...); + OptionalBase::init_ = true; + } + + template + void initialize(::std::initializer_list il, Args&&... args) noexcept(noexcept(T(il, ::std::forward(args)...))) + { + assert(!OptionalBase::init_); + ::new (static_cast(dataptr())) T(il, ::std::forward(args)...); + OptionalBase::init_ = true; + } + + public: + typedef T value_type; + + // 20.5.5.1, constructors + constexpr optional() noexcept : OptionalBase() {}; + constexpr optional(nullopt_t) noexcept : OptionalBase() {}; + + optional(const optional& rhs) + : OptionalBase() + { + if (rhs.initialized()) { + ::new (static_cast(dataptr())) T(*rhs); + OptionalBase::init_ = true; + } + } + + optional(const optional& rhs) : optional() + { + if (rhs) { + ::new (static_cast(dataptr())) T(*rhs); + OptionalBase::init_ = true; + } + } + + optional(optional&& rhs) noexcept(::std::is_nothrow_move_constructible::value) + : OptionalBase() + { + if (rhs.initialized()) { + ::new (static_cast(dataptr())) T(::std::move(*rhs)); + OptionalBase::init_ = true; + } + } + + constexpr optional(const T& v) : OptionalBase(v) {} + + constexpr optional(T&& v) : OptionalBase(constexpr_move(v)) {} + + template + explicit constexpr optional(in_place_t, Args&&... args) + : OptionalBase(in_place, constexpr_forward(args)...) {} + + template >)> + OPTIONAL_CONSTEXPR_INIT_LIST explicit optional(in_place_t, ::std::initializer_list il, Args&&... args) + : OptionalBase(in_place, il, constexpr_forward(args)...) {} + + // 20.5.4.2, Destructor + ~optional() = default; + + // 20.5.4.3, assignment + optional& operator=(nullopt_t) noexcept + { + clear(); + return *this; + } + + optional& operator=(const optional& rhs) + { + if (initialized() == true && rhs.initialized() == false) clear(); + else if (initialized() == false && rhs.initialized() == true) initialize(*rhs); + else if (initialized() == true && rhs.initialized() == true) contained_val() = *rhs; + return *this; + } + + optional& operator=(optional&& rhs) + noexcept(::std::is_nothrow_move_assignable::value && ::std::is_nothrow_move_constructible::value) + { + if (initialized() == true && rhs.initialized() == false) clear(); + else if (initialized() == false && rhs.initialized() == true) initialize(::std::move(*rhs)); + else if (initialized() == true && rhs.initialized() == true) contained_val() = ::std::move(*rhs); + return *this; + } + + template + auto operator=(U&& v) + -> typename ::std::enable_if + < + ::std::is_same::type, T>::value, + optional& + >::type + { + if (initialized()) { contained_val() = ::std::forward(v); } + else { initialize(::std::forward(v)); } + return *this; + } + + template + void emplace(Args&&... args) + { + clear(); + initialize(::std::forward(args)...); + } + + template + void emplace(::std::initializer_list il, Args&&... args) + { + clear(); + initialize(il, ::std::forward(args)...); + } + + // 20.5.4.4, Swap + void swap(optional& rhs) noexcept(::std::is_nothrow_move_constructible::value && noexcept(swap(::std::declval(), ::std::declval()))) + { + if (initialized() == true && rhs.initialized() == false) { rhs.initialize(::std::move(**this)); clear(); } + else if (initialized() == false && rhs.initialized() == true) { initialize(::std::move(*rhs)); rhs.clear(); } + else if (initialized() == true && rhs.initialized() == true) { using ::std::swap; swap(**this, *rhs); } + } + + // 20.5.4.5, Observers + + explicit constexpr operator bool() const noexcept { return initialized(); } + + constexpr T const* operator ->() const { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr()); + } + +# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 + + OPTIONAL_MUTABLE_CONSTEXPR T* operator ->() { + assert(initialized()); + return dataptr(); + } + + constexpr T const& operator *() const& { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); + } + + OPTIONAL_MUTABLE_CONSTEXPR T& operator *() & { + assert(initialized()); + return contained_val(); + } + + OPTIONAL_MUTABLE_CONSTEXPR T&& operator *() && { + assert(initialized()); + return constexpr_move(contained_val()); + } + + constexpr T const& value() const& { + return initialized() ? + contained_val() +#ifdef SOL_NO_EXCEPTIONS + // we can't abort here + // because there's no constexpr abort + : *(T*)nullptr; +#else + : (throw bad_optional_access("bad optional access"), contained_val()); +#endif + } + + OPTIONAL_MUTABLE_CONSTEXPR T& value() & { + return initialized() ? + contained_val() +#ifdef SOL_NO_EXCEPTIONS + : *(T*)nullptr; +#else + : (throw bad_optional_access("bad optional access"), contained_val()); +#endif + } + + OPTIONAL_MUTABLE_CONSTEXPR T&& value() && { + return initialized() ? + contained_val() +#ifdef SOL_NO_EXCEPTIONS + // we can't abort here + // because there's no constexpr abort + : std::move(*(T*)nullptr); +#else + : (throw bad_optional_access("bad optional access"), contained_val()); +#endif + } + +# else + + T* operator ->() { + assert(initialized()); + return dataptr(); + } + + constexpr T const& operator *() const { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); + } + + T& operator *() { + assert(initialized()); + return contained_val(); + } + + constexpr T const& value() const { + return initialized() ? + contained_val() +#ifdef SOL_NO_EXCEPTIONS + // we can't abort here + // because there's no constexpr abort + : *(T*)nullptr; +#else + : (throw bad_optional_access("bad optional access"), contained_val()); +#endif + } + + T& value() { + return initialized() ? + contained_val() +#ifdef SOL_NO_EXCEPTIONS + // we can abort here + // but the others are constexpr, so we can't... + : (std::abort(), *(T*)nullptr); +#else + : (throw bad_optional_access("bad optional access"), contained_val()); +#endif + } + +# endif + +# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 + + template + constexpr T value_or(V&& v) const& + { + return *this ? **this : detail_::convert(constexpr_forward(v)); + } + +# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 + + template + OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) && + { + return *this ? constexpr_move(const_cast&>(*this).contained_val()) : detail_::convert(constexpr_forward(v)); + } + +# else + + template + T value_or(V&& v) && + { + return *this ? constexpr_move(const_cast&>(*this).contained_val()) : detail_::convert(constexpr_forward(v)); + } + +# endif + +# else + + template + constexpr T value_or(V&& v) const + { + return *this ? **this : detail_::convert(constexpr_forward(v)); + } + +# endif + + }; + + template + class optional + { + static_assert(!::std::is_same::value, "bad T"); + static_assert(!::std::is_same::value, "bad T"); + T* ref; + + public: + + // 20.5.5.1, construction/destruction + constexpr optional() noexcept : ref(nullptr) {} + + constexpr optional(nullopt_t) noexcept : ref(nullptr) {} + + constexpr optional(T& v) noexcept : ref(detail_::static_addressof(v)) {} + + optional(T&&) = delete; + + constexpr optional(const optional& rhs) noexcept : ref(rhs.ref) {} + + explicit constexpr optional(in_place_t, T& v) noexcept : ref(detail_::static_addressof(v)) {} + + explicit optional(in_place_t, T&&) = delete; + + ~optional() = default; + + // 20.5.5.2, mutation + optional& operator=(nullopt_t) noexcept { + ref = nullptr; + return *this; + } + + // optional& operator=(const optional& rhs) noexcept { + // ref = rhs.ref; + // return *this; + // } + + // optional& operator=(optional&& rhs) noexcept { + // ref = rhs.ref; + // return *this; + // } + + template + auto operator=(U&& rhs) noexcept + -> typename ::std::enable_if + < + ::std::is_same::type, optional>::value, + optional& + >::type + { + ref = rhs.ref; + return *this; + } + + template + auto operator=(U&& rhs) noexcept + -> typename ::std::enable_if + < + !::std::is_same::type, optional>::value, + optional& + >::type + = delete; + + void emplace(T& v) noexcept { + ref = detail_::static_addressof(v); + } + + void emplace(T&&) = delete; + + void swap(optional& rhs) noexcept + { + ::std::swap(ref, rhs.ref); + } + + // 20.5.5.3, observers + constexpr T* operator->() const { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref); + } + + constexpr T& operator*() const { + return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref); + } + + constexpr T& value() const { +#ifdef SOL_NO_EXCEPTIONS + return *ref; +#else + return ref ? *ref + : (throw bad_optional_access("bad optional access"), *ref); +#endif // Exceptions + } + + explicit constexpr operator bool() const noexcept { + return ref != nullptr; + } + + template + constexpr T& value_or(V&& v) const + { + return *this ? **this : detail_::convert(constexpr_forward(v)); + } + }; + + template + class optional + { + static_assert(sizeof(T) == 0, "optional rvalue references disallowed"); + }; + + // 20.5.8, Relational operators + template constexpr bool operator==(const optional& x, const optional& y) + { + return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y; + } + + template constexpr bool operator!=(const optional& x, const optional& y) + { + return !(x == y); + } + + template constexpr bool operator<(const optional& x, const optional& y) + { + return (!y) ? false : (!x) ? true : *x < *y; + } + + template constexpr bool operator>(const optional& x, const optional& y) + { + return (y < x); + } + + template constexpr bool operator<=(const optional& x, const optional& y) + { + return !(y < x); + } + + template constexpr bool operator>=(const optional& x, const optional& y) + { + return !(x < y); + } + + // 20.5.9, Comparison with nullopt + template constexpr bool operator==(const optional& x, nullopt_t) noexcept + { + return (!x); + } + + template constexpr bool operator==(nullopt_t, const optional& x) noexcept + { + return (!x); + } + + template constexpr bool operator!=(const optional& x, nullopt_t) noexcept + { + return bool(x); + } + + template constexpr bool operator!=(nullopt_t, const optional& x) noexcept + { + return bool(x); + } + + template constexpr bool operator<(const optional&, nullopt_t) noexcept + { + return false; + } + + template constexpr bool operator<(nullopt_t, const optional& x) noexcept + { + return bool(x); + } + + template constexpr bool operator<=(const optional& x, nullopt_t) noexcept + { + return (!x); + } + + template constexpr bool operator<=(nullopt_t, const optional&) noexcept + { + return true; + } + + template constexpr bool operator>(const optional& x, nullopt_t) noexcept + { + return bool(x); + } + + template constexpr bool operator>(nullopt_t, const optional&) noexcept + { + return false; + } + + template constexpr bool operator>=(const optional&, nullopt_t) noexcept + { + return true; + } + + template constexpr bool operator>=(nullopt_t, const optional& x) noexcept + { + return (!x); + } + + // 20.5.10, Comparison with T + template constexpr bool operator==(const optional& x, const T& v) + { + return bool(x) ? *x == v : false; + } + + template constexpr bool operator==(const T& v, const optional& x) + { + return bool(x) ? v == *x : false; + } + + template constexpr bool operator!=(const optional& x, const T& v) + { + return bool(x) ? *x != v : true; + } + + template constexpr bool operator!=(const T& v, const optional& x) + { + return bool(x) ? v != *x : true; + } + + template constexpr bool operator<(const optional& x, const T& v) + { + return bool(x) ? *x < v : true; + } + + template constexpr bool operator>(const T& v, const optional& x) + { + return bool(x) ? v > *x : true; + } + + template constexpr bool operator>(const optional& x, const T& v) + { + return bool(x) ? *x > v : false; + } + + template constexpr bool operator<(const T& v, const optional& x) + { + return bool(x) ? v < *x : false; + } + + template constexpr bool operator>=(const optional& x, const T& v) + { + return bool(x) ? *x >= v : false; + } + + template constexpr bool operator<=(const T& v, const optional& x) + { + return bool(x) ? v <= *x : false; + } + + template constexpr bool operator<=(const optional& x, const T& v) + { + return bool(x) ? *x <= v : true; + } + + template constexpr bool operator>=(const T& v, const optional& x) + { + return bool(x) ? v >= *x : true; + } + + // Comparison of optional with T + template constexpr bool operator==(const optional& x, const T& v) + { + return bool(x) ? *x == v : false; + } + + template constexpr bool operator==(const T& v, const optional& x) + { + return bool(x) ? v == *x : false; + } + + template constexpr bool operator!=(const optional& x, const T& v) + { + return bool(x) ? *x != v : true; + } + + template constexpr bool operator!=(const T& v, const optional& x) + { + return bool(x) ? v != *x : true; + } + + template constexpr bool operator<(const optional& x, const T& v) + { + return bool(x) ? *x < v : true; + } + + template constexpr bool operator>(const T& v, const optional& x) + { + return bool(x) ? v > *x : true; + } + + template constexpr bool operator>(const optional& x, const T& v) + { + return bool(x) ? *x > v : false; + } + + template constexpr bool operator<(const T& v, const optional& x) + { + return bool(x) ? v < *x : false; + } + + template constexpr bool operator>=(const optional& x, const T& v) + { + return bool(x) ? *x >= v : false; + } + + template constexpr bool operator<=(const T& v, const optional& x) + { + return bool(x) ? v <= *x : false; + } + + template constexpr bool operator<=(const optional& x, const T& v) + { + return bool(x) ? *x <= v : true; + } + + template constexpr bool operator>=(const T& v, const optional& x) + { + return bool(x) ? v >= *x : true; + } + + // Comparison of optional with T + template constexpr bool operator==(const optional& x, const T& v) + { + return bool(x) ? *x == v : false; + } + + template constexpr bool operator==(const T& v, const optional& x) + { + return bool(x) ? v == *x : false; + } + + template constexpr bool operator!=(const optional& x, const T& v) + { + return bool(x) ? *x != v : true; + } + + template constexpr bool operator!=(const T& v, const optional& x) + { + return bool(x) ? v != *x : true; + } + + template constexpr bool operator<(const optional& x, const T& v) + { + return bool(x) ? *x < v : true; + } + + template constexpr bool operator>(const T& v, const optional& x) + { + return bool(x) ? v > *x : true; + } + + template constexpr bool operator>(const optional& x, const T& v) + { + return bool(x) ? *x > v : false; + } + + template constexpr bool operator<(const T& v, const optional& x) + { + return bool(x) ? v < *x : false; + } + + template constexpr bool operator>=(const optional& x, const T& v) + { + return bool(x) ? *x >= v : false; + } + + template constexpr bool operator<=(const T& v, const optional& x) + { + return bool(x) ? v <= *x : false; + } + + template constexpr bool operator<=(const optional& x, const T& v) + { + return bool(x) ? *x <= v : true; + } + + template constexpr bool operator>=(const T& v, const optional& x) + { + return bool(x) ? v >= *x : true; + } + + // 20.5.12, Specialized algorithms + template + void swap(optional& x, optional& y) noexcept(noexcept(x.swap(y))) { + x.swap(y); + } + + template + constexpr optional::type> make_optional(T&& v) { + return optional::type>(constexpr_forward(v)); + } + + template + constexpr optional make_optional(::std::reference_wrapper v) { + return optional(v.get()); + } + +} // namespace + +namespace std +{ + template + struct hash> { + typedef typename hash::result_type result_type; + typedef sol::optional argument_type; + + constexpr result_type operator()(argument_type const& arg) const { + return arg ? ::std::hash{}(*arg) : result_type{}; + } + }; + + template + struct hash> { + typedef typename hash::result_type result_type; + typedef sol::optional argument_type; + + constexpr result_type operator()(argument_type const& arg) const { + return arg ? ::std::hash{}(*arg) : result_type{}; + } + }; +} + +# if defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ +#pragma warning( pop ) +#endif + +# undef TR2_OPTIONAL_REQUIRES +# undef TR2_OPTIONAL_ASSERTED_EXPRESSION + +# endif // SOL_OPTIONAL_IMPLEMENTATION_HPP +// end of sol/optional_implementation.hpp + +#endif // Boost vs. Better optional + +namespace sol { + +#if defined(SOL_USE_BOOST) + template + using optional = boost::optional; + using nullopt_t = boost::none_t; + const nullopt_t nullopt = boost::none; +#endif // Boost vs. Better optional + +} // sol + +// end of sol/optional.hpp + +// beginning of sol/string_shim.hpp + +namespace sol { + namespace string_detail { + struct string_shim { + std::size_t s; + const char* p; + + string_shim(const std::string& r) : string_shim(r.data(), r.size()) {} + string_shim(const char* ptr) : string_shim(ptr, std::char_traits::length(ptr)) {} + string_shim(const char* ptr, std::size_t sz) : s(sz), p(ptr) {} + + static int compare(const char* lhs_p, std::size_t lhs_sz, const char* rhs_p, std::size_t rhs_sz) { + int result = std::char_traits::compare(lhs_p, rhs_p, lhs_sz < rhs_sz ? lhs_sz : rhs_sz); + if (result != 0) + return result; + if (lhs_sz < rhs_sz) + return -1; + if (lhs_sz > rhs_sz) + return 1; + return 0; + } + + const char* c_str() const { + return p; + } + + const char* data() const { + return p; + } + + std::size_t size() const { + return s; + } + + bool operator==(const string_shim& r) const { + return compare(p, s, r.data(), r.size()) == 0; + } + + bool operator==(const char* r) const { + return compare(r, std::char_traits::length(r), p, s) == 0; + } + + bool operator==(const std::string& r) const { + return compare(r.data(), r.size(), p, s) == 0; + } + + bool operator!=(const string_shim& r) const { + return !(*this == r); + } + + bool operator!=(const char* r) const { + return !(*this == r); + } + + bool operator!=(const std::string& r) const { + return !(*this == r); + } + }; + } +} + +// end of sol/string_shim.hpp + +#include + +namespace sol { + namespace detail { +#ifdef SOL_NO_EXCEPTIONS + template + int static_trampoline(lua_State* L) { + return f(L); + } + + template + int trampoline(lua_State* L, Fx&& f, Args&&... args) { + return f(L, std::forward(args)...); + } + + inline int c_trampoline(lua_State* L, lua_CFunction f) { + return trampoline(L, f); + } +#else + template + int static_trampoline(lua_State* L) { + try { + return f(L); + } + catch (const char *s) { + lua_pushstring(L, s); + } + catch (const std::exception& e) { + lua_pushstring(L, e.what()); + } +#if !defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) + catch (...) { + std::exception_ptr eptr = std::current_exception(); + lua_pushstring(L, "caught (...) exception"); + } +#endif + return lua_error(L); + } + + template + int trampoline(lua_State* L, Fx&& f, Args&&... args) { + try { + return f(L, std::forward(args)...); + } + catch (const char *s) { + lua_pushstring(L, s); + } + catch (const std::exception& e) { + lua_pushstring(L, e.what()); + } +#if !defined(SOL_EXCEPTIONS_SAFE_PROPAGATION) + catch (...) { + lua_pushstring(L, "caught (...) exception"); + } +#endif + return lua_error(L); + } + + inline int c_trampoline(lua_State* L, lua_CFunction f) { + return trampoline(L, f); + } +#endif // Exceptions vs. No Exceptions + + template + struct unique_usertype {}; + + template + struct implicit_wrapper { + T& item; + implicit_wrapper(T* item) : item(*item) {} + implicit_wrapper(T& item) : item(item) {} + operator T& () { + return item; + } + operator T* () { + return std::addressof(item); + } + }; + + struct unchecked_t {}; + const unchecked_t unchecked = unchecked_t{}; + } // detail + + struct lua_nil_t {}; + const lua_nil_t lua_nil{}; + inline bool operator==(lua_nil_t, lua_nil_t) { return true; } + inline bool operator!=(lua_nil_t, lua_nil_t) { return false; } +#ifndef __OBJC__ + typedef lua_nil_t nil_t; + const nil_t nil{}; +#endif + + struct metatable_t {}; + const metatable_t metatable_key = {}; + + struct env_t {}; + const env_t env_key = {}; + + struct no_metatable_t {}; + const no_metatable_t no_metatable = {}; + + typedef std::remove_pointer_t lua_r_CFunction; + + template + struct unique_usertype_traits { + typedef T type; + typedef T actual_type; + static const bool value = false; + + template + static bool is_null(U&&) { + return false; + } + + template + static auto get(U&& value) { + return std::addressof(detail::deref(value)); + } + }; + + template + struct unique_usertype_traits> { + typedef T type; + typedef std::shared_ptr actual_type; + static const bool value = true; + + static bool is_null(const actual_type& p) { + return p == nullptr; + } + + static type* get(const actual_type& p) { + return p.get(); + } + }; + + template + struct unique_usertype_traits> { + typedef T type; + typedef std::unique_ptr actual_type; + static const bool value = true; + + static bool is_null(const actual_type& p) { + return p == nullptr; + } + + static type* get(const actual_type& p) { + return p.get(); + } + }; + + template + struct non_null {}; + + template + struct function_sig {}; + + struct upvalue_index { + int index; + upvalue_index(int idx) : index(lua_upvalueindex(idx)) {} + operator int() const { return index; } + }; + + struct raw_index { + int index; + raw_index(int i) : index(i) {} + operator int() const { return index; } + }; + + struct absolute_index { + int index; + absolute_index(lua_State* L, int idx) : index(lua_absindex(L, idx)) {} + operator int() const { return index; } + }; + + struct ref_index { + int index; + ref_index(int idx) : index(idx) {} + operator int() const { return index; } + }; + + struct lightuserdata_value { + void* value; + lightuserdata_value(void* data) : value(data) {} + operator void*() const { return value; } + }; + + struct userdata_value { + void* value; + userdata_value(void* data) : value(data) {} + operator void*() const { return value; } + }; + + template + struct light { + L* value; + + light(L& x) : value(std::addressof(x)) {} + light(L* x) : value(x) {} + light(void* x) : value(static_cast(x)) {} + operator L* () const { return value; } + operator L& () const { return *value; } + }; + + template + auto make_light(T& l) { + typedef meta::unwrapped_t>> L; + return light(l); + } + + template + struct user { + U value; + + user(U x) : value(std::move(x)) {} + operator U* () { return std::addressof(value); } + operator U& () { return value; } + operator const U& () const { return value; } + }; + + template + auto make_user(T&& u) { + typedef meta::unwrapped_t> U; + return user(std::forward(u)); + } + + template + struct metatable_registry_key { + T key; + + metatable_registry_key(T key) : key(std::forward(key)) {} + }; + + template + auto meta_registry_key(T&& key) { + typedef meta::unqualified_t K; + return metatable_registry_key(std::forward(key)); + } + + template + struct closure { + lua_CFunction c_function; + std::tuple upvalues; + closure(lua_CFunction f, Upvalues... targetupvalues) : c_function(f), upvalues(std::forward(targetupvalues)...) {} + }; + + template <> + struct closure<> { + lua_CFunction c_function; + int upvalues; + closure(lua_CFunction f, int upvalue_count = 0) : c_function(f), upvalues(upvalue_count) {} + }; + + typedef closure<> c_closure; + + template + closure make_closure(lua_CFunction f, Args&&... args) { + return closure(f, std::forward(args)...); + } + + template + struct function_arguments { + std::tuple arguments; + template , function_arguments>> = meta::enabler> + function_arguments(Arg&& arg, Args&&... args) : arguments(std::forward(arg), std::forward(args)...) {} + }; + + template , typename... Args> + auto as_function(Args&&... args) { + return function_arguments...>(std::forward(args)...); + } + + template , typename... Args> + auto as_function_reference(Args&&... args) { + return function_arguments(std::forward(args)...); + } + + template + struct as_table_t { + T source; + template + as_table_t(Args&&... args) : source(std::forward(args)...) {} + + operator std::add_lvalue_reference_t () { + return source; + } + }; + + template + struct nested { + T source; + + template + nested(Args&&... args) : source(std::forward(args)...) {} + + operator std::add_lvalue_reference_t() { + return source; + } + }; + + template + as_table_t as_table(T&& container) { + return as_table_t(std::forward(container)); + } + + struct this_state { + lua_State* L; + operator lua_State* () const { + return L; + } + lua_State* operator-> () const { + return L; + } + }; + + struct new_table { + int sequence_hint = 0; + int map_hint = 0; + + new_table() = default; + new_table(const new_table&) = default; + new_table(new_table&&) = default; + new_table& operator=(const new_table&) = default; + new_table& operator=(new_table&&) = default; + + new_table(int sequence_hint, int map_hint = 0) : sequence_hint(sequence_hint), map_hint(map_hint) {} + }; + + enum class call_syntax { + dot = 0, + colon = 1 + }; + + enum class call_status : int { + ok = LUA_OK, + yielded = LUA_YIELD, + runtime = LUA_ERRRUN, + memory = LUA_ERRMEM, + handler = LUA_ERRERR, + gc = LUA_ERRGCMM, + syntax = LUA_ERRSYNTAX, + file = LUA_ERRFILE, + }; + + enum class thread_status : int { + ok = LUA_OK, + yielded = LUA_YIELD, + runtime = LUA_ERRRUN, + memory = LUA_ERRMEM, + gc = LUA_ERRGCMM, + handler = LUA_ERRERR, + dead = -1, + }; + + enum class load_status : int { + ok = LUA_OK, + syntax = LUA_ERRSYNTAX, + memory = LUA_ERRMEM, + gc = LUA_ERRGCMM, + file = LUA_ERRFILE, + }; + + enum class type : int { + none = LUA_TNONE, + lua_nil = LUA_TNIL, +#ifndef __OBJC__ + nil = lua_nil, +#endif // Objective C++ Keyword + string = LUA_TSTRING, + number = LUA_TNUMBER, + thread = LUA_TTHREAD, + boolean = LUA_TBOOLEAN, + function = LUA_TFUNCTION, + userdata = LUA_TUSERDATA, + lightuserdata = LUA_TLIGHTUSERDATA, + table = LUA_TTABLE, + poly = none | lua_nil | string | number | thread | + table | boolean | function | userdata | lightuserdata + }; + + inline const std::string& to_string(call_status c) { + static const std::array names{{ + "ok", + "yielded", + "runtime", + "memory", + "handler", + "gc", + "syntax", + "file", + }}; + switch (c) { + case call_status::ok: + return names[0]; + case call_status::yielded: + return names[1]; + case call_status::runtime: + return names[2]; + case call_status::memory: + return names[3]; + case call_status::handler: + return names[4]; + case call_status::gc: + return names[5]; + case call_status::syntax: + return names[6]; + case call_status::file: + return names[7]; + } + return names[0]; + } + + inline const std::string& to_string(load_status c) { + static const std::array names{ { + "ok", + "memory", + "gc", + "syntax", + "file", + } }; + switch (c) { + case load_status::ok: + return names[0]; + case load_status::memory: + return names[1]; + case load_status::gc: + return names[2]; + case load_status::syntax: + return names[3]; + case load_status::file: + return names[4]; + } + return names[0]; + } + + enum class meta_function { + construct, + index, + new_index, + mode, + call, + call_function = call, + metatable, + to_string, + length, + unary_minus, + addition, + subtraction, + multiplication, + division, + modulus, + power_of, + involution = power_of, + concatenation, + equal_to, + less_than, + less_than_or_equal_to, + garbage_collect, + floor_division, + bitwise_left_shift, + bitwise_right_shift, + bitwise_not, + bitwise_and, + bitwise_or, + bitwise_xor, + pairs, + next + }; + + typedef meta_function meta_method; + + inline const std::array& meta_function_names() { + static const std::array names = { { + "new", + "__index", + "__newindex", + "__mode", + "__call", + "__mt", + "__tostring", + "__len", + "__unm", + "__add", + "__sub", + "__mul", + "__div", + "__mod", + "__pow", + "__concat", + "__eq", + "__lt", + "__le", + "__gc", + + "__idiv", + "__shl", + "__shr", + "__bnot", + "__band", + "__bor", + "__bxor", + + "__pairs", + "__next" + } }; + return names; + } + + inline const std::string& to_string(meta_function mf) { + return meta_function_names()[static_cast(mf)]; + } + + inline type type_of(lua_State* L, int index) { + return static_cast(lua_type(L, index)); + } + + inline int type_panic(lua_State* L, int index, type expected, type actual) { + return luaL_error(L, "stack index %d, expected %s, received %s", index, + expected == type::poly ? "anything" : lua_typename(L, static_cast(expected)), + expected == type::poly ? "anything" : lua_typename(L, static_cast(actual)) + ); + } + + // Specify this function as the handler for lua::check if you know there's nothing wrong + inline int no_panic(lua_State*, int, type, type) noexcept { + return 0; + } + + inline void type_error(lua_State* L, int expected, int actual) { + luaL_error(L, "expected %s, received %s", lua_typename(L, expected), lua_typename(L, actual)); + } + + inline void type_error(lua_State* L, type expected, type actual) { + type_error(L, static_cast(expected), static_cast(actual)); + } + + inline void type_assert(lua_State* L, int index, type expected, type actual) { + if (expected != type::poly && expected != actual) { + type_panic(L, index, expected, actual); + } + } + + inline void type_assert(lua_State* L, int index, type expected) { + type actual = type_of(L, index); + type_assert(L, index, expected, actual); + } + + inline std::string type_name(lua_State* L, type t) { + return lua_typename(L, static_cast(t)); + } + + class reference; + class stack_reference; + template + struct proxy; + template + class usertype; + template + class basic_table_core; + template + using table_core = basic_table_core; + template + using stack_table_core = basic_table_core; + template + using basic_table = basic_table_core; + typedef table_core table; + typedef table_core global_table; + typedef stack_table_core stack_table; + typedef stack_table_core stack_global_table; + template + struct basic_environment; + using environment = basic_environment; + using stack_environment = basic_environment; + template + class basic_function; + template + class basic_protected_function; + using protected_function = basic_protected_function; + using stack_protected_function = basic_protected_function; + using unsafe_function = basic_function; + using safe_function = basic_protected_function; + using stack_unsafe_function = basic_function; + using stack_safe_function = basic_protected_function; +#ifdef SOL_SAFE_FUNCTIONS + using function = protected_function; + using stack_function = stack_protected_function; +#else + using function = unsafe_function; + using stack_function = stack_unsafe_function; +#endif + template + class basic_object; + template + class basic_userdata; + template + class basic_lightuserdata; + struct variadic_args; + using object = basic_object; + using stack_object = basic_object; + using userdata = basic_userdata; + using stack_userdata = basic_userdata; + using lightuserdata = basic_lightuserdata; + using stack_lightuserdata = basic_lightuserdata; + class coroutine; + class thread; + struct variadic_args; + struct this_state; + + namespace detail { + template + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant { }; + + template <> + struct lua_type_of : std::integral_constant { }; + + template <> + struct lua_type_of : std::integral_constant { }; + + template <> + struct lua_type_of : std::integral_constant { }; + + template + struct lua_type_of> : std::integral_constant { }; + + template <> + struct lua_type_of : std::integral_constant { }; + + template + struct lua_type_of> : std::integral_constant { }; + + template <> + struct lua_type_of : std::integral_constant { }; + + template <> + struct lua_type_of : std::integral_constant { }; + + template + struct lua_type_of> : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of> : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template + struct lua_type_of> : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of : std::integral_constant {}; + + template + struct lua_type_of::value>> : std::integral_constant {}; + + template + struct lua_type_of::value>> : std::integral_constant {}; + + template + struct is_container : std::false_type {}; + + template <> + struct is_container : std::false_type {}; + + template <> + struct is_container : std::false_type {}; + + template <> + struct is_container : std::false_type {}; + + template <> + struct is_container : std::false_type {}; + + template + struct is_container>::value>> : std::true_type {}; + + template <> + struct lua_type_of : std::integral_constant {}; + + template class V, typename... Args> + struct accumulate : std::integral_constant {}; + + template class V, typename T, typename... Args> + struct accumulate : accumulate::value, V, Args...> {}; + } // detail + + template + struct is_unique_usertype : std::integral_constant::value> {}; + + template + struct lua_type_of : detail::lua_type_of { + typedef int SOL_INTERNAL_UNSPECIALIZED_MARKER_; + }; + + template + struct lua_size : std::integral_constant { + typedef int SOL_INTERNAL_UNSPECIALIZED_MARKER_; + }; + + template + struct lua_size> : std::integral_constant::value + lua_size::value> { }; + + template + struct lua_size> : std::integral_constant::value> { }; + + namespace detail { + template + struct void_ { typedef void type; }; + template + struct has_internal_marker_impl : std::false_type {}; + template + struct has_internal_marker_impl::type> : std::true_type {}; + + template + struct has_internal_marker : has_internal_marker_impl {}; + } + + template + struct is_lua_primitive : std::integral_constant>::value + || ((type::userdata == lua_type_of>::value) + && detail::has_internal_marker>>::value + && !detail::has_internal_marker>>::value) + || std::is_base_of>::value + || std::is_base_of>::value + || meta::is_specialization_of>::value + || meta::is_specialization_of>::value + > { }; + + template + struct is_lua_reference : std::integral_constant>::value + || std::is_base_of>::value + || meta::is_specialization_of>::value + > { }; + + template + struct is_lua_primitive : std::true_type {}; + template + struct is_lua_primitive> : std::true_type { }; + template + struct is_lua_primitive> : std::true_type { }; + template + struct is_lua_primitive> : is_lua_primitive { }; + template + struct is_lua_primitive> : std::true_type {}; + template <> + struct is_lua_primitive : std::true_type {}; + template <> + struct is_lua_primitive : std::true_type {}; + template + struct is_lua_primitive> : is_lua_primitive {}; + + template + struct is_proxy_primitive : is_lua_primitive { }; + + template + struct is_transparent_argument : std::false_type {}; + + template <> + struct is_transparent_argument : std::true_type {}; + + template <> + struct is_transparent_argument : std::true_type {}; + + template + struct is_variadic_arguments : std::is_same {}; + + template + struct lua_bind_traits : meta::bind_traits { + private: + typedef meta::bind_traits base_t; + public: + typedef std::integral_constant::value != 0> runtime_variadics_t; + static const std::size_t true_arity = base_t::arity; + static const std::size_t arity = base_t::arity - meta::count_for::value; + static const std::size_t true_free_arity = base_t::free_arity; + static const std::size_t free_arity = base_t::free_arity - meta::count_for::value; + }; + + template + struct is_table : std::false_type {}; + template + struct is_table> : std::true_type {}; + + template + struct is_function : std::false_type {}; + template + struct is_function> : std::true_type {}; + template + struct is_function> : std::true_type {}; + + template + struct is_lightuserdata : std::false_type {}; + template + struct is_lightuserdata> : std::true_type {}; + + template + struct is_userdata : std::false_type {}; + template + struct is_userdata> : std::true_type {}; + + template + struct is_environment : std::integral_constant::value || is_table::value> {}; + + template + struct is_container : detail::is_container{}; + + template + inline type type_of() { + return lua_type_of>::value; + } + + namespace detail { + template + struct lua_type_of, std::enable_if_t<::sol::is_container::value>> : std::integral_constant {}; + + template + struct lua_type_of, std::enable_if_t::value>> : lua_type_of {}; + } // detail +} // sol + +// end of sol/types.hpp + +// beginning of sol/stack_reference.hpp + +namespace sol { + class stack_reference { + private: + lua_State* L = nullptr; + int index = 0; + + protected: + int registry_index() const noexcept { + return LUA_NOREF; + } + + public: + stack_reference() noexcept = default; + stack_reference(lua_nil_t) noexcept : stack_reference() {}; + stack_reference(lua_State* L, int i) noexcept : L(L), index(lua_absindex(L, i)) {} + stack_reference(lua_State* L, absolute_index i) noexcept : L(L), index(i) {} + stack_reference(lua_State* L, raw_index i) noexcept : L(L), index(i) {} + stack_reference(lua_State* L, ref_index i) noexcept = delete; + stack_reference(stack_reference&& o) noexcept = default; + stack_reference& operator=(stack_reference&&) noexcept = default; + stack_reference(const stack_reference&) noexcept = default; + stack_reference& operator=(const stack_reference&) noexcept = default; + + int push() const noexcept { + return push(lua_state()); + } + + int push(lua_State* Ls) const noexcept { + lua_pushvalue(lua_state(), index); + if (Ls != lua_state()) { + lua_xmove(lua_state(), Ls, 1); + } + return 1; + } + + void pop() const noexcept { + pop(lua_state()); + } + + void pop(lua_State* Ls, int n = 1) const noexcept { + lua_pop(Ls, n); + } + + int stack_index() const noexcept { + return index; + } + + type get_type() const noexcept { + int result = lua_type(L, index); + return static_cast(result); + } + + lua_State* lua_state() const noexcept { + return L; + } + + bool valid() const noexcept { + type t = get_type(); + return t != type::lua_nil && t != type::none; + } + }; + + inline bool operator== (const stack_reference& l, const stack_reference& r) { + return lua_compare(l.lua_state(), l.stack_index(), r.stack_index(), LUA_OPEQ) == 0; + } + + inline bool operator!= (const stack_reference& l, const stack_reference& r) { + return !operator==(l, r); + } + + inline bool operator==(const stack_reference& lhs, const lua_nil_t&) { + return !lhs.valid(); + } + + inline bool operator==(const lua_nil_t&, const stack_reference& rhs) { + return !rhs.valid(); + } + + inline bool operator!=(const stack_reference& lhs, const lua_nil_t&) { + return lhs.valid(); + } + + inline bool operator!=(const lua_nil_t&, const stack_reference& rhs) { + return rhs.valid(); + } +} // sol + +// end of sol/stack_reference.hpp + +namespace sol { + namespace stack { + inline void remove(lua_State* L, int rawindex, int count) { + if (count < 1) + return; + int top = lua_gettop(L); + if (rawindex == -count || top == rawindex) { + // Slice them right off the top + lua_pop(L, static_cast(count)); + return; + } + + // Remove each item one at a time using stack operations + // Probably slower, maybe, haven't benchmarked, + // but necessary + int index = lua_absindex(L, rawindex); + if (index < 0) { + index = lua_gettop(L) + (index + 1); + } + int last = index + count; + for (int i = index; i < last; ++i) { + lua_remove(L, index); + } + } + + struct push_popper_at { + lua_State* L; + int index; + int count; + push_popper_at(lua_State* luastate, int index = -1, int count = 1) : L(luastate), index(index), count(count) { } + ~push_popper_at() { remove(L, index, count); } + }; + + template + struct push_popper_n { + lua_State* L; + int t; + push_popper_n(lua_State* luastate, int x) : L(luastate), t(x) { } + ~push_popper_n() { lua_pop(L, t); } + }; + template <> + struct push_popper_n { + push_popper_n(lua_State*, int) { } + }; + template + struct push_popper { + T t; + push_popper(T x) : t(x) { t.push(); } + ~push_popper() { t.pop(); } + }; + template + struct push_popper { + push_popper(T) {} + ~push_popper() {} + }; + template + push_popper push_pop(T&& x) { + return push_popper(std::forward(x)); + } + template + push_popper_at push_pop_at(T&& x) { + int c = x.push(); + lua_State* L = x.lua_state(); + return push_popper_at(L, lua_absindex(L, -c), c); + } + template + push_popper_n pop_n(lua_State* L, int x) { + return push_popper_n(L, x); + } + } // stack + + namespace detail { + struct global_tag { } const global_{}; + struct no_safety_tag {} const no_safety{}; + } // detail + + class reference { + private: + lua_State* luastate = nullptr; // non-owning + int ref = LUA_NOREF; + + int copy() const noexcept { + if (ref == LUA_NOREF) + return LUA_NOREF; + push(); + return luaL_ref(lua_state(), LUA_REGISTRYINDEX); + } + + protected: + reference(lua_State* L, detail::global_tag) noexcept : luastate(L) { + lua_pushglobaltable(lua_state()); + ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); + } + + int stack_index() const noexcept { + return -1; + } + + void deref() const noexcept { + luaL_unref(lua_state(), LUA_REGISTRYINDEX, ref); + } + + public: + reference() noexcept = default; + reference(lua_nil_t) noexcept : reference() {} + reference(const stack_reference& r) noexcept : reference(r.lua_state(), r.stack_index()) {} + reference(stack_reference&& r) noexcept : reference(r.lua_state(), r.stack_index()) {} + reference(lua_State* L, int index = -1) noexcept : luastate(L) { + lua_pushvalue(lua_state(), index); + ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); + } + reference(lua_State* L, ref_index index) noexcept : luastate(L) { + lua_rawgeti(L, LUA_REGISTRYINDEX, index.index); + ref = luaL_ref(lua_state(), LUA_REGISTRYINDEX); + } + + ~reference() noexcept { + deref(); + } + + reference(reference&& o) noexcept { + luastate = o.luastate; + ref = o.ref; + + o.luastate = nullptr; + o.ref = LUA_NOREF; + } + + reference& operator=(reference&& o) noexcept { + if (valid()) { + deref(); + } + luastate = o.luastate; + ref = o.ref; + + o.luastate = nullptr; + o.ref = LUA_NOREF; + + return *this; + } + + reference(const reference& o) noexcept { + luastate = o.luastate; + ref = o.copy(); + } + + reference& operator=(const reference& o) noexcept { + luastate = o.luastate; + deref(); + ref = o.copy(); + return *this; + } + + int push() const noexcept { + return push(lua_state()); + } + + int push(lua_State* Ls) const noexcept { + lua_rawgeti(Ls, LUA_REGISTRYINDEX, ref); + return 1; + } + + void pop() const noexcept { + pop(lua_state()); + } + + void pop(lua_State* Ls, int n = 1) const noexcept { + lua_pop(Ls, n); + } + + int registry_index() const noexcept { + return ref; + } + + bool valid() const noexcept { + return !(ref == LUA_NOREF || ref == LUA_REFNIL); + } + + explicit operator bool() const noexcept { + return valid(); + } + + type get_type() const noexcept { + auto pp = stack::push_pop(*this); + int result = lua_type(lua_state(), -1); + return static_cast(result); + } + + lua_State* lua_state() const noexcept { + return luastate; + } + }; + + inline bool operator== (const reference& l, const reference& r) { + auto ppl = stack::push_pop(l); + auto ppr = stack::push_pop(r); + return lua_compare(l.lua_state(), -1, -2, LUA_OPEQ) == 1; + } + + inline bool operator!= (const reference& l, const reference& r) { + return !operator==(l, r); + } + + inline bool operator==(const reference& lhs, const lua_nil_t&) { + return !lhs.valid(); + } + + inline bool operator==(const lua_nil_t&, const reference& rhs) { + return !rhs.valid(); + } + + inline bool operator!=(const reference& lhs, const lua_nil_t&) { + return lhs.valid(); + } + + inline bool operator!=(const lua_nil_t&, const reference& rhs) { + return rhs.valid(); + } +} // sol + +// end of sol/reference.hpp + +// beginning of sol/stack.hpp + +// beginning of sol/stack_core.hpp + +// beginning of sol/tie.hpp + +namespace sol { + + namespace detail { + template + struct is_speshul : std::false_type {}; + } + + template + struct tie_size : std::tuple_size {}; + + template + struct is_tieable : std::integral_constant::value > 0)> {}; + + template + struct tie_t : public std::tuple...> { + private: + typedef std::tuple...> base_t; + + template + void set(std::false_type, T&& target) { + std::get<0>(*this) = std::forward(target); + } + + template + void set(std::true_type, T&& target) { + typedef tie_size> value_size; + typedef tie_size> tie_size; + typedef std::conditional_t<(value_size::value < tie_size::value), value_size, tie_size> indices_size; + typedef std::make_index_sequence indices; + set_extra(detail::is_speshul>(), indices(), std::forward(target)); + } + + template + void set_extra(std::true_type, std::index_sequence, T&& target) { + using std::get; + (void)detail::swallow{ 0, + (get(static_cast(*this)) = get(types(), target), 0)... + , 0 }; + } + + template + void set_extra(std::false_type, std::index_sequence, T&& target) { + using std::get; + (void)detail::swallow{ 0, + (get(static_cast(*this)) = get(target), 0)... + , 0 }; + } + + public: + using base_t::base_t; + + template + tie_t& operator= (T&& value) { + typedef is_tieable> tieable; + set(tieable(), std::forward(value)); + return *this; + } + + }; + + template + struct tie_size< tie_t > : std::tuple_size< std::tuple > { }; + + namespace adl_barrier_detail { + template + inline tie_t...> tie(Tn&&... argn) { + return tie_t...>(std::forward(argn)...); + } + } + + using namespace adl_barrier_detail; + +} // sol + +// end of sol/tie.hpp + +// beginning of sol/stack_guard.hpp + +namespace sol { + namespace detail { + inline void stack_fail(int, int) { +#ifndef SOL_NO_EXCEPTIONS + throw error(detail::direct_error, "imbalanced stack after operation finish"); +#else + // Lol, what do you want, an error printout? :3c + // There's no sane default here. The right way would be C-style abort(), and that's not acceptable, so + // hopefully someone will register their own stack_fail thing for the `fx` parameter of stack_guard. +#endif // No Exceptions + } + } // detail + + struct stack_guard { + lua_State* L; + int top; + std::function on_mismatch; + + stack_guard(lua_State* L) : stack_guard(L, lua_gettop(L)) {} + stack_guard(lua_State* L, int top, std::function fx = detail::stack_fail) : L(L), top(top), on_mismatch(std::move(fx)) {} + bool check_stack(int modification = 0) const { + int bottom = lua_gettop(L) + modification; + if (top == bottom) { + return true; + } + on_mismatch(top, bottom); + return false; + } + ~stack_guard() { + check_stack(); + } + }; +} // sol + +// end of sol/stack_guard.hpp + +#include + +namespace sol { + namespace detail { + struct as_reference_tag {}; + template + struct as_pointer_tag {}; + template + struct as_value_tag {}; + + using special_destruct_func = void(*)(void*); + + template + inline void special_destruct(void* memory) { + T** pointerpointer = static_cast(memory); + special_destruct_func* dx = static_cast(static_cast(pointerpointer + 1)); + Real* target = static_cast(static_cast(dx + 1)); + target->~Real(); + } + + template + inline int unique_destruct(lua_State* L) { + void* memory = lua_touserdata(L, 1); + T** pointerpointer = static_cast(memory); + special_destruct_func& dx = *static_cast(static_cast(pointerpointer + 1)); + (dx)(memory); + return 0; + } + + template + inline int user_alloc_destroy(lua_State* L) { + void* rawdata = lua_touserdata(L, 1); + T* data = static_cast(rawdata); + std::allocator alloc; + alloc.destroy(data); + return 0; + } + + template + inline int usertype_alloc_destroy(lua_State* L) { + void* rawdata = lua_touserdata(L, 1); + T** pdata = static_cast(rawdata); + T* data = *pdata; + std::allocator alloc{}; + alloc.destroy(data); + return 0; + } + + template + void reserve(T&, std::size_t) {} + + template + void reserve(std::vector& arr, std::size_t hint) { + arr.reserve(hint); + } + + template + void reserve(std::basic_string& arr, std::size_t hint) { + arr.reserve(hint); + } + } // detail + + namespace stack { + + template + struct field_getter; + template + struct probe_field_getter; + template + struct field_setter; + template + struct getter; + template + struct popper; + template + struct pusher; + template::value, typename = void> + struct checker; + template + struct check_getter; + + struct probe { + bool success; + int levels; + + probe(bool s, int l) : success(s), levels(l) {} + + operator bool() const { return success; }; + }; + + struct record { + int last; + int used; + + record() : last(), used() {} + void use(int count) { + last = count; + used += count; + } + }; + + namespace stack_detail { + template + struct strip { + typedef T type; + }; + template + struct strip> { + typedef T& type; + }; + template + struct strip> { + typedef T& type; + }; + template + struct strip> { + typedef T type; + }; + template + using strip_t = typename strip::type; + const bool default_check_arguments = +#ifdef SOL_CHECK_ARGUMENTS + true; +#else + false; +#endif + template + inline decltype(auto) unchecked_get(lua_State* L, int index, record& tracking) { + return getter>{}.get(L, index, tracking); + } + } // stack_detail + + inline bool maybe_indexable(lua_State* L, int index = -1) { + type t = type_of(L, index); + return t == type::userdata || t == type::table; + } + + template + inline int push(lua_State* L, T&& t, Args&&... args) { + return pusher>{}.push(L, std::forward(t), std::forward(args)...); + } + + // overload allows to use a pusher of a specific type, but pass in any kind of args + template::value>> + inline int push(lua_State* L, Arg&& arg, Args&&... args) { + return pusher>{}.push(L, std::forward(arg), std::forward(args)...); + } + + template + inline int push_reference(lua_State* L, T&& t, Args&&... args) { + typedef meta::all< + std::is_lvalue_reference, + meta::neg>, + meta::neg>>, + meta::neg>> + > use_reference_tag; + return pusher>>{}.push(L, std::forward(t), std::forward(args)...); + } + + inline int multi_push(lua_State*) { + // do nothing + return 0; + } + + template + inline int multi_push(lua_State* L, T&& t, Args&&... args) { + int pushcount = push(L, std::forward(t)); + void(sol::detail::swallow{ (pushcount += sol::stack::push(L, std::forward(args)), 0)... }); + return pushcount; + } + + inline int multi_push_reference(lua_State*) { + // do nothing + return 0; + } + + template + inline int multi_push_reference(lua_State* L, T&& t, Args&&... args) { + int pushcount = push_reference(L, std::forward(t)); + void(sol::detail::swallow{ (pushcount += sol::stack::push_reference(L, std::forward(args)), 0)... }); + return pushcount; + } + + template + bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + typedef meta::unqualified_t Tu; + checker c; + // VC++ has a bad warning here: shut it up + (void)c; + return c.check(L, index, std::forward(handler), tracking); + } + + template + bool check(lua_State* L, int index, Handler&& handler) { + record tracking{}; + return check(L, index, std::forward(handler), tracking); + } + + template + bool check(lua_State* L, int index = -lua_size>::value) { + auto handler = no_panic; + return check(L, index, handler); + } + + template + inline decltype(auto) check_get(lua_State* L, int index, Handler&& handler, record& tracking) { + return check_getter>{}.get(L, index, std::forward(handler), tracking); + } + + template + inline decltype(auto) check_get(lua_State* L, int index, Handler&& handler) { + record tracking{}; + return check_get(L, index, handler, tracking); + } + + template + inline decltype(auto) check_get(lua_State* L, int index = -lua_size>::value) { + auto handler = no_panic; + return check_get(L, index, handler); + } + + namespace stack_detail { + +#ifdef SOL_CHECK_ARGUMENTS + template + inline auto tagged_get(types, lua_State* L, int index, record& tracking) -> decltype(stack_detail::unchecked_get(L, index, tracking)) { + auto op = check_get(L, index, type_panic, tracking); + return *std::move(op); + } +#else + template + inline decltype(auto) tagged_get(types, lua_State* L, int index, record& tracking) { + return stack_detail::unchecked_get(L, index, tracking); + } +#endif + + template + inline decltype(auto) tagged_get(types>, lua_State* L, int index, record& tracking) { + return stack_detail::unchecked_get>(L, index, tracking); + } + + template + struct check_types { + template + static bool check(types, lua_State* L, int firstargument, Handler&& handler, record& tracking) { + if (!stack::check(L, firstargument + tracking.used, handler, tracking)) + return false; + return check(types(), L, firstargument, std::forward(handler), tracking); + } + + template + static bool check(types<>, lua_State*, int, Handler&&, record&) { + return true; + } + }; + + template <> + struct check_types { + template + static bool check(types, lua_State*, int, Handler&&, record&) { + return true; + } + }; + + } // stack_detail + + template + bool multi_check(lua_State* L, int index, Handler&& handler, record& tracking) { + return stack_detail::check_types{}.check(types...>(), L, index, std::forward(handler), tracking); + } + + template + bool multi_check(lua_State* L, int index, Handler&& handler) { + record tracking{}; + return multi_check(L, index, std::forward(handler), tracking); + } + + template + bool multi_check(lua_State* L, int index) { + auto handler = no_panic; + return multi_check(L, index, handler); + } + + template + bool multi_check(lua_State* L, int index, Handler&& handler, record& tracking) { + return multi_check(L, index, std::forward(handler), tracking); + } + + template + bool multi_check(lua_State* L, int index, Handler&& handler) { + return multi_check(L, index, std::forward(handler)); + } + + template + bool multi_check(lua_State* L, int index) { + return multi_check(L, index); + } + + template + inline decltype(auto) get(lua_State* L, int index, record& tracking) { + return stack_detail::tagged_get(types(), L, index, tracking); + } + + template + inline decltype(auto) get(lua_State* L, int index = -lua_size>::value) { + record tracking{}; + return get(L, index, tracking); + } + + template + inline decltype(auto) pop(lua_State* L) { + return popper>{}.pop(L); + } + + template + void get_field(lua_State* L, Key&& key) { + field_getter, global, raw>{}.get(L, std::forward(key)); + } + + template + void get_field(lua_State* L, Key&& key, int tableindex) { + field_getter, global, raw>{}.get(L, std::forward(key), tableindex); + } + + template + void raw_get_field(lua_State* L, Key&& key) { + get_field(L, std::forward(key)); + } + + template + void raw_get_field(lua_State* L, Key&& key, int tableindex) { + get_field(L, std::forward(key), tableindex); + } + + template + probe probe_get_field(lua_State* L, Key&& key) { + return probe_field_getter, global, raw>{}.get(L, std::forward(key)); + } + + template + probe probe_get_field(lua_State* L, Key&& key, int tableindex) { + return probe_field_getter, global, raw>{}.get(L, std::forward(key), tableindex); + } + + template + probe probe_raw_get_field(lua_State* L, Key&& key) { + return probe_get_field(L, std::forward(key)); + } + + template + probe probe_raw_get_field(lua_State* L, Key&& key, int tableindex) { + return probe_get_field(L, std::forward(key), tableindex); + } + + template + void set_field(lua_State* L, Key&& key, Value&& value) { + field_setter, global, raw>{}.set(L, std::forward(key), std::forward(value)); + } + + template + void set_field(lua_State* L, Key&& key, Value&& value, int tableindex) { + field_setter, global, raw>{}.set(L, std::forward(key), std::forward(value), tableindex); + } + + template + void raw_set_field(lua_State* L, Key&& key, Value&& value) { + set_field(L, std::forward(key), std::forward(value)); + } + + template + void raw_set_field(lua_State* L, Key&& key, Value&& value, int tableindex) { + set_field(L, std::forward(key), std::forward(value), tableindex); + } + } // stack +} // sol + +// end of sol/stack_core.hpp + +// beginning of sol/stack_check.hpp + +// beginning of sol/usertype_traits.hpp + +// beginning of sol/demangle.hpp + +#include +#include + +namespace sol { + namespace detail { +#if defined(__GNUC__) || defined(__clang__) + template + inline std::string ctti_get_type_name() { + const static std::array removals = { { "{anonymous}", "(anonymous namespace)" } }; + std::string name = __PRETTY_FUNCTION__; + std::size_t start = name.find_first_of('['); + start = name.find_first_of('=', start); + std::size_t end = name.find_last_of(']'); + if (end == std::string::npos) + end = name.size(); + if (start == std::string::npos) + start = 0; + if (start < name.size() - 1) + start += 1; + name = name.substr(start, end - start); + start = name.rfind("seperator_mark"); + if (start != std::string::npos) { + name.erase(start - 2, name.length()); + } + while (!name.empty() && std::isblank(name.front())) name.erase(name.begin()); + while (!name.empty() && std::isblank(name.back())) name.pop_back(); + + for (std::size_t r = 0; r < removals.size(); ++r) { + auto found = name.find(removals[r]); + while (found != std::string::npos) { + name.erase(found, removals[r].size()); + found = name.find(removals[r]); + } + } + + return name; + } +#elif defined(_MSC_VER) + template + inline std::string ctti_get_type_name() { + const static std::array removals = { { "public:", "private:", "protected:", "struct ", "class ", "`anonymous-namespace'", "`anonymous namespace'" } }; + std::string name = __FUNCSIG__; + std::size_t start = name.find("get_type_name"); + if (start == std::string::npos) + start = 0; + else + start += 13; + if (start < name.size() - 1) + start += 1; + std::size_t end = name.find_last_of('>'); + if (end == std::string::npos) + end = name.size(); + name = name.substr(start, end - start); + if (name.find("struct", 0) == 0) + name.replace(0, 6, "", 0); + if (name.find("class", 0) == 0) + name.replace(0, 5, "", 0); + while (!name.empty() && std::isblank(name.front())) name.erase(name.begin()); + while (!name.empty() && std::isblank(name.back())) name.pop_back(); + + for (std::size_t r = 0; r < removals.size(); ++r) { + auto found = name.find(removals[r]); + while (found != std::string::npos) { + name.erase(found, removals[r].size()); + found = name.find(removals[r]); + } + } + + return name; + } +#else +#error Compiler not supported for demangling +#endif // compilers + + template + inline std::string demangle_once() { + std::string realname = ctti_get_type_name(); + return realname; + } + + template + inline std::string short_demangle_once() { + std::string realname = ctti_get_type_name(); + // This isn't the most complete but it'll do for now...? + static const std::array ops = { { "operator<", "operator<<", "operator<<=", "operator<=", "operator>", "operator>>", "operator>>=", "operator>=", "operator->", "operator->*" } }; + int level = 0; + std::ptrdiff_t idx = 0; + for (idx = static_cast(realname.empty() ? 0 : realname.size() - 1); idx > 0; --idx) { + if (level == 0 && realname[idx] == ':') { + break; + } + bool isleft = realname[idx] == '<'; + bool isright = realname[idx] == '>'; + if (!isleft && !isright) + continue; + bool earlybreak = false; + for (const auto& op : ops) { + std::size_t nisop = realname.rfind(op, idx); + if (nisop == std::string::npos) + continue; + std::size_t nisopidx = idx - op.size() + 1; + if (nisop == nisopidx) { + idx = static_cast(nisopidx); + earlybreak = true; + } + break; + } + if (earlybreak) { + continue; + } + level += isleft ? -1 : 1; + } + if (idx > 0) { + realname.erase(0, realname.length() < static_cast(idx) ? realname.length() : idx + 1); + } + return realname; + } + + template + inline const std::string& demangle() { + static const std::string d = demangle_once(); + return d; + } + + template + inline const std::string& short_demangle() { + static const std::string d = short_demangle_once(); + return d; + } + } // detail +} // sol + +// end of sol/demangle.hpp + +namespace sol { + + template + struct usertype_traits { + static const std::string& name() { + static const std::string& n = detail::short_demangle(); + return n; + } + static const std::string& qualified_name() { + static const std::string& q_n = detail::demangle(); + return q_n; + } + static const std::string& metatable() { + static const std::string m = std::string("sol.").append(detail::demangle()); + return m; + } + static const std::string& user_metatable() { + static const std::string u_m = std::string("sol.").append(detail::demangle()).append(".user"); + return u_m; + } + static const std::string& user_gc_metatable() { + static const std::string u_g_m = std::string("sol.").append(detail::demangle()).append(".user\xE2\x99\xBB"); + return u_g_m; + } + static const std::string& gc_table() { + static const std::string g_t = std::string("sol.").append(detail::demangle()).append(".\xE2\x99\xBB"); + return g_t; + } + }; + +} + +// end of sol/usertype_traits.hpp + +// beginning of sol/inheritance.hpp + +#include + +namespace sol { + template + struct base_list { }; + template + using bases = base_list; + + typedef bases<> base_classes_tag; + const auto base_classes = base_classes_tag(); + + namespace detail { + + template + struct has_derived { + static bool value; + }; + + template + bool has_derived::value = false; + + inline std::size_t unique_id() { + static std::atomic x(0); + return ++x; + } + + template + struct id_for { + static const std::size_t value; + }; + + template + const std::size_t id_for::value = unique_id(); + + inline decltype(auto) base_class_check_key() { + static const auto& key = "class_check"; + return key; + } + + inline decltype(auto) base_class_cast_key() { + static const auto& key = "class_cast"; + return key; + } + + inline decltype(auto) base_class_index_propogation_key() { + static const auto& key = u8"\xF0\x9F\x8C\xB2.index"; + return key; + } + + inline decltype(auto) base_class_new_index_propogation_key() { + static const auto& key = u8"\xF0\x9F\x8C\xB2.new_index"; + return key; + } + + template + struct inheritance { + static bool type_check_bases(types<>, std::size_t) { + return false; + } + + template + static bool type_check_bases(types, std::size_t ti) { + return ti == id_for::value || type_check_bases(types(), ti); + } + + static bool type_check(std::size_t ti) { + return ti == id_for::value || type_check_bases(types(), ti); + } + + static void* type_cast_bases(types<>, T*, std::size_t) { + return nullptr; + } + + template + static void* type_cast_bases(types, T* data, std::size_t ti) { + // Make sure to convert to T first, and then dynamic cast to the proper type + return ti != id_for::value ? type_cast_bases(types(), data, ti) : static_cast(static_cast(data)); + } + + static void* type_cast(void* voiddata, std::size_t ti) { + T* data = static_cast(voiddata); + return static_cast(ti != id_for::value ? type_cast_bases(types(), data, ti) : data); + } + }; + + using inheritance_check_function = decltype(&inheritance::type_check); + using inheritance_cast_function = decltype(&inheritance::type_cast); + + } // detail +} // sol + +// end of sol/inheritance.hpp + +#include + +namespace sol { + namespace stack { + namespace stack_detail { + template + inline bool check_metatable(lua_State* L, int index = -2) { + const auto& metakey = usertype_traits::metatable(); + luaL_getmetatable(L, &metakey[0]); + const type expectedmetatabletype = static_cast(lua_type(L, -1)); + if (expectedmetatabletype != type::lua_nil) { + if (lua_rawequal(L, -1, index) == 1) { + lua_pop(L, 1 + static_cast(poptable)); + return true; + } + } + lua_pop(L, 1); + return false; + } + + template + struct basic_check { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + bool success = check_func(L, index) == 1; + if (!success) { + // expected type, actual type + handler(L, index, expected, type_of(L, index)); + } + return success; + } + }; + } // stack_detail + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + const type indextype = type_of(L, index); + bool success = expected == indextype; + if (!success) { + // expected type, actual type + handler(L, index, expected, indextype); + } + return success; + } + }; + + template + struct checker::value>> { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + bool success = lua_isinteger(L, index) == 1; + if (!success) { + // expected type, actual type + handler(L, index, type::number, type_of(L, index)); + } + return success; + } + }; + + template + struct checker::value>> { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + bool success = lua_isnumber(L, index) == 1; + if (!success) { + // expected type, actual type + handler(L, index, type::number, type_of(L, index)); + } + return success; + } + }; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + bool success = lua_isnil(L, index); + if (success) { + tracking.use(1); + return success; + } + tracking.use(0); + success = lua_isnone(L, index); + if (!success) { + // expected type, actual type + handler(L, index, expected, type_of(L, index)); + } + return success; + } + }; + + template + struct checker : checker {}; + + template + struct checker { + template + static bool check(lua_State*, int, Handler&&, record& tracking) { + tracking.use(0); + return true; + } + }; + + template + struct checker { + template + static bool check(lua_State*, int, Handler&&, record& tracking) { + tracking.use(0); + return true; + } + }; + + template + struct checker { + template + static bool check(lua_State*, int, Handler&&, record& tracking) { + tracking.use(0); + return true; + } + }; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + bool success = !lua_isnone(L, index); + if (!success) { + // expected type, actual type + handler(L, index, type::none, type_of(L, index)); + } + return success; + } + }; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + type t = type_of(L, index); + bool success = t == type::userdata || t == type::lightuserdata; + if (!success) { + // expected type, actual type + handler(L, index, type::lightuserdata, t); + } + return success; + } + }; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + type t = type_of(L, index); + bool success = t == type::userdata; + if (!success) { + // expected type, actual type + handler(L, index, type::userdata, t); + } + return success; + } + }; + + template + struct checker, type::userdata, C> { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + return stack::check(L, index, std::forward(handler), tracking); + } + }; + + template + struct checker, type::userdata, C> : checker, type::lightuserdata, C> {}; + + template + struct checker, type::userdata, C> : checker::value, C> {}; + + template + struct checker : stack_detail::basic_check {}; + template + struct checker, type::function, C> : checker {}; + template + struct checker : checker {}; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + type t = type_of(L, index); + if (t == type::lua_nil || t == type::none || t == type::function) { + // allow for lua_nil to be returned + return true; + } + if (t != type::userdata && t != type::table) { + handler(L, index, type::function, t); + return false; + } + // Do advanced check for call-style userdata? + static const auto& callkey = to_string(meta_function::call); + if (lua_getmetatable(L, index) == 0) { + // No metatable, no __call key possible + handler(L, index, type::function, t); + return false; + } + if (lua_isnoneornil(L, -1)) { + lua_pop(L, 1); + handler(L, index, type::function, t); + return false; + } + lua_getfield(L, -1, &callkey[0]); + if (lua_isnoneornil(L, -1)) { + lua_pop(L, 2); + handler(L, index, type::function, t); + return false; + } + // has call, is definitely a function + lua_pop(L, 2); + return true; + } + }; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + type t = type_of(L, index); + if (t == type::table) { + return true; + } + if (t != type::userdata) { + handler(L, index, type::table, t); + return false; + } + return true; + } + }; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + if (lua_getmetatable(L, index) == 0) { + return true; + } + type t = type_of(L, -1); + if (t == type::table || t == type::none || t == type::nil) { + lua_pop(L, 1); + return true; + } + if (t != type::userdata) { + lua_pop(L, 1); + handler(L, index, expected, t); + return false; + } + return true; + } + }; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + if (lua_getmetatable(L, index) == 0) { + return true; + } + type t = type_of(L, -1); + if (t == type::table || t == type::none || t == type::nil) { + lua_pop(L, 1); + return true; + } + if (t != type::userdata) { + lua_pop(L, 1); + handler(L, index, type::table, t); + return false; + } + return true; + } + }; + + template + struct checker, type::poly, C> { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + tracking.use(1); + if (lua_getmetatable(L, index) == 0) { + return true; + } + type t = type_of(L, -1); + if (t == type::table || t == type::none || t == type::nil) { + lua_pop(L, 1); + return true; + } + if (t != type::userdata) { + lua_pop(L, 1); + handler(L, index, type::table, t); + return false; + } + return true; + } + }; + + template + struct checker, type::userdata, C> { + template + static bool check(types, lua_State* L, type indextype, int index, Handler&& handler, record& tracking) { + tracking.use(1); + if (indextype != type::userdata) { + handler(L, index, type::userdata, indextype); + return false; + } + if (meta::any, std::is_same, std::is_same, std::is_same>::value) + return true; + if (lua_getmetatable(L, index) == 0) { + return true; + } + int metatableindex = lua_gettop(L); + if (stack_detail::check_metatable(L, metatableindex)) + return true; + if (stack_detail::check_metatable(L, metatableindex)) + return true; + if (stack_detail::check_metatable>(L, metatableindex)) + return true; + bool success = false; + if (detail::has_derived::value) { + auto pn = stack::pop_n(L, 1); + lua_pushstring(L, &detail::base_class_check_key()[0]); + lua_rawget(L, metatableindex); + if (type_of(L, -1) != type::lua_nil) { + void* basecastdata = lua_touserdata(L, -1); + detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata; + success = ic(detail::id_for::value); + } + } + if (!success) { + lua_pop(L, 1); + handler(L, index, type::userdata, indextype); + return false; + } + lua_pop(L, 1); + return true; + } + }; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + const type indextype = type_of(L, index); + return checker, type::userdata, C>{}.check(types(), L, indextype, index, std::forward(handler), tracking); + } + }; + + template + struct checker { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + const type indextype = type_of(L, index); + // Allow lua_nil to be transformed to nullptr + if (indextype == type::lua_nil) { + tracking.use(1); + return true; + } + return checker, type::userdata, C>{}.check(L, index, std::forward(handler), tracking); + } + }; + + template + struct checker::value>> { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + return checker::type, type::userdata>{}.check(L, index, std::forward(handler), tracking); + } + }; + + template + struct checker, type::userdata, C> { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + return checker{}.check(L, index, std::forward(handler), tracking); + } + }; + + template + struct checker, type::poly, C> { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + return stack::multi_check(L, index, std::forward(handler), tracking); + } + }; + + template + struct checker, type::poly, C> { + template + static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { + return stack::multi_check(L, index, std::forward(handler), tracking); + } + }; + + template + struct checker, type::poly, C> { + template + static bool check(lua_State* L, int index, Handler&&, record& tracking) { + type t = type_of(L, index); + if (t == type::none) { + tracking.use(0); + return true; + } + if (t == type::lua_nil) { + tracking.use(1); + return true; + } + return stack::check(L, index, no_panic, tracking); + } + }; + } // stack +} // sol + +// end of sol/stack_check.hpp + +// beginning of sol/stack_get.hpp + +// beginning of sol/overload.hpp + +namespace sol { + template + struct overload_set { + std::tuple functions; + template >> = meta::enabler> + overload_set (Arg&& arg, Args&&... args) : functions(std::forward(arg), std::forward(args)...) {} + overload_set(const overload_set&) = default; + overload_set(overload_set&&) = default; + overload_set& operator=(const overload_set&) = default; + overload_set& operator=(overload_set&&) = default; + }; + + template + decltype(auto) overload(Args&&... args) { + return overload_set...>(std::forward(args)...); + } +} + +// end of sol/overload.hpp + +#ifdef SOL_CODECVT_SUPPORT +#include +#endif + +namespace sol { + namespace stack { + + template + struct getter { + static T& get(lua_State* L, int index, record& tracking) { + return getter>{}.get(L, index, tracking); + } + }; + + template + struct getter::value>> { + static T get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return static_cast(lua_tonumber(L, index)); + } + }; + + template + struct getter, std::is_signed>::value>> { + static T get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return static_cast(lua_tointeger(L, index)); + } + }; + + template + struct getter, std::is_unsigned>::value>> { + static T get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return static_cast(lua_tointeger(L, index)); + } + }; + + template + struct getter::value>> { + static T get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return static_cast(lua_tointegerx(L, index, nullptr)); + } + }; + + template + struct getter, std::enable_if_t>::value>> { + static T get(lua_State* L, int relindex, record& tracking) { + typedef typename T::value_type V; + return get(types(), L, relindex, tracking); + } + + template + static T get(types, lua_State* L, int relindex, record& tracking) { + tracking.use(1); + + int index = lua_absindex(L, relindex); + T arr; +#if SOL_LUA_VERSION >= 503 + // This method is HIGHLY performant over regular table iteration thanks to the Lua API changes in 5.3 + for (lua_Integer i = 0; ; i += lua_size::value, lua_pop(L, lua_size::value)) { + bool isnil = false; + for (int vi = 0; vi < lua_size::value; ++vi) { + type t = static_cast(lua_geti(L, index, i + vi)); + isnil = t == type::lua_nil; + if (isnil) { + if (i == 0) { + break; + } + lua_pop(L, (vi + 1)); + return arr; + } + } + if (isnil) + continue; + arr.push_back(stack::get(L, -lua_size::value)); + } +#else + // Zzzz slower but necessary thanks to the lower version API and missing functions qq + for (lua_Integer i = 0; ; i += lua_size::value, lua_pop(L, lua_size::value)) { + bool isnil = false; + for (int vi = 0; vi < lua_size::value; ++vi) { + lua_pushinteger(L, i); + lua_gettable(L, index); + type t = type_of(L, -1); + isnil = t == type::lua_nil; + if (isnil) { + if (i == 0) { + break; + } + lua_pop(L, (vi + 1)); + return arr; + } + } + if (isnil) + continue; + arr.push_back(stack::get(L, -1)); + } +#endif + return arr; + } + }; + + template + struct getter, std::enable_if_t>::value>> { + static T get(lua_State* L, int index, record& tracking) { + typedef typename T::value_type P; + typedef typename P::first_type K; + typedef typename P::second_type V; + return get(types(), L, index, tracking); + } + + template + static T get(types, lua_State* L, int relindex, record& tracking) { + tracking.use(1); + + T associative; + int index = lua_absindex(L, relindex); + lua_pushnil(L); + while (lua_next(L, index) != 0) { + decltype(auto) key = stack::check_get(L, -2); + if (!key) { + lua_pop(L, 1); + continue; + } + associative.emplace(std::forward(*key), stack::get(L, -1)); + lua_pop(L, 1); + } + return associative; + } + }; + + template + struct getter, std::enable_if_t::value>> { + static T get(lua_State* L, int index, record& tracking) { + getter g; + // VC++ has a bad warning here: shut it up + (void)g; + return g.get(L, index, tracking); + } + }; + + template + struct getter, std::enable_if_t, meta::neg>>>::value>> { + static T get(lua_State* L, int index, record& tracking) { + typedef typename T::value_type V; + getter> g; + // VC++ has a bad warning here: shut it up + (void)g; + return g.get(types>(), L, index, tracking); + } + }; + + template + struct getter, std::enable_if_t, meta::has_key_value_pair>>::value>> { + static T get(lua_State* L, int index, record& tracking) { + typedef typename T::value_type P; + typedef typename P::first_type K; + typedef typename P::second_type V; + getter> g; + // VC++ has a bad warning here: shut it up + (void)g; + return g.get(types>(), L, index, tracking); + } + }; + + template + struct getter::value || std::is_base_of::value>> { + static T get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return T(L, index); + } + }; + + template<> + struct getter { + static userdata_value get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return userdata_value(lua_touserdata(L, index)); + } + }; + + template<> + struct getter { + static lightuserdata_value get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return lightuserdata_value(lua_touserdata(L, index)); + } + }; + + template + struct getter> { + static light get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return light(static_cast(lua_touserdata(L, index))); + } + }; + + template + struct getter> { + static T& get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return *static_cast(lua_touserdata(L, index)); + } + }; + + template + struct getter> { + static T* get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return static_cast(lua_touserdata(L, index)); + } + }; + + template<> + struct getter { + static type get(lua_State *L, int index, record& tracking) { + tracking.use(1); + return static_cast(lua_type(L, index)); + } + }; + + template<> + struct getter { + static bool get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return lua_toboolean(L, index) != 0; + } + }; + + template<> + struct getter { + static std::string get(lua_State* L, int index, record& tracking) { + tracking.use(1); + std::size_t len; + auto str = lua_tolstring(L, index, &len); + return std::string( str, len ); + } + }; + + template <> + struct getter { + string_detail::string_shim get(lua_State* L, int index, record& tracking) { + tracking.use(1); + size_t len; + const char* p = lua_tolstring(L, index, &len); + return string_detail::string_shim(p, len); + } + }; + + template<> + struct getter { + static const char* get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return lua_tostring(L, index); + } + }; + + template<> + struct getter { + static char get(lua_State* L, int index, record& tracking) { + tracking.use(1); + size_t len; + auto str = lua_tolstring(L, index, &len); + return len > 0 ? str[0] : '\0'; + } + }; + +#ifdef SOL_CODECVT_SUPPORT + template<> + struct getter { + static std::wstring get(lua_State* L, int index, record& tracking) { + tracking.use(1); + size_t len; + auto str = lua_tolstring(L, index, &len); + if (len < 1) + return std::wstring(); + if (sizeof(wchar_t) == 2) { + static std::wstring_convert> convert; + std::wstring r = convert.from_bytes(str, str + len); +#ifdef __MINGW32__ + // Fuck you, MinGW, and fuck you libstdc++ for introducing this absolutely asinine bug + // https://sourceforge.net/p/mingw-w64/bugs/538/ + // http://chat.stackoverflow.com/transcript/message/32271369#32271369 + for (auto& c : r) { + uint8_t* b = reinterpret_cast(&c); + std::swap(b[0], b[1]); + } +#endif + return r; + } + static std::wstring_convert> convert; + std::wstring r = convert.from_bytes(str, str + len); + return r; + } + }; + + template<> + struct getter { + static std::u16string get(lua_State* L, int index, record& tracking) { + tracking.use(1); + size_t len; + auto str = lua_tolstring(L, index, &len); + if (len < 1) + return std::u16string(); +#ifdef _MSC_VER + static std::wstring_convert, int16_t> convert; + auto intd = convert.from_bytes(str, str + len); + std::u16string r(intd.size(), '\0'); + std::memcpy(&r[0], intd.data(), intd.size() * sizeof(char16_t)); +#else + static std::wstring_convert, char16_t> convert; + std::u16string r = convert.from_bytes(str, str + len); +#endif // VC++ is a shit + return r; + } + }; + + template<> + struct getter { + static std::u32string get(lua_State* L, int index, record& tracking) { + tracking.use(1); + size_t len; + auto str = lua_tolstring(L, index, &len); + if (len < 1) + return std::u32string(); +#ifdef _MSC_VER + static std::wstring_convert, int32_t> convert; + auto intd = convert.from_bytes(str, str + len); + std::u32string r(intd.size(), '\0'); + std::memcpy(&r[0], intd.data(), r.size() * sizeof(char32_t)); +#else + static std::wstring_convert, char32_t> convert; + std::u32string r = convert.from_bytes(str, str + len); +#endif // VC++ is a shit + return r; + } + }; + + template<> + struct getter { + static wchar_t get(lua_State* L, int index, record& tracking) { + auto str = getter{}.get(L, index, tracking); + return str.size() > 0 ? str[0] : wchar_t(0); + } + }; + + template<> + struct getter { + static char16_t get(lua_State* L, int index, record& tracking) { + auto str = getter{}.get(L, index, tracking); + return str.size() > 0 ? str[0] : char16_t(0); + } + }; + + template<> + struct getter { + static char32_t get(lua_State* L, int index, record& tracking) { + auto str = getter{}.get(L, index, tracking); + return str.size() > 0 ? str[0] : char32_t(0); + } + }; +#endif // codecvt header support + + template<> + struct getter { + static meta_function get(lua_State *L, int index, record& tracking) { + tracking.use(1); + const char* name = getter{}.get(L, index, tracking); + const auto& mfnames = meta_function_names(); + for (std::size_t i = 0; i < mfnames.size(); ++i) + if (mfnames[i] == name) + return static_cast(i); + return meta_function::construct; + } + }; + + template<> + struct getter { + static lua_nil_t get(lua_State*, int, record& tracking) { + tracking.use(1); + return lua_nil; + } + }; + + template<> + struct getter { + static std::nullptr_t get(lua_State*, int, record& tracking) { + tracking.use(1); + return nullptr; + } + }; + + template<> + struct getter { + static nullopt_t get(lua_State*, int, record& tracking) { + tracking.use(1); + return nullopt; + } + }; + + template<> + struct getter { + static this_state get(lua_State* L, int, record& tracking) { + tracking.use(0); + return this_state{ L }; + } + }; + + template<> + struct getter { + static lua_CFunction get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return lua_tocfunction(L, index); + } + }; + + template<> + struct getter { + static c_closure get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return c_closure(lua_tocfunction(L, index), -1); + } + }; + + template<> + struct getter { + static error get(lua_State* L, int index, record& tracking) { + tracking.use(1); + size_t sz = 0; + const char* err = lua_tolstring(L, index, &sz); + if (err == nullptr) { + return error(detail::direct_error, ""); + } + return error(detail::direct_error, std::string(err, sz)); + } + }; + + template<> + struct getter { + static void* get(lua_State* L, int index, record& tracking) { + tracking.use(1); + return lua_touserdata(L, index); + } + }; + + template + struct getter> { + static T* get_no_lua_nil(lua_State* L, int index, record& tracking) { + tracking.use(1); + void** pudata = static_cast(lua_touserdata(L, index)); + void* udata = *pudata; + return get_no_lua_nil_from(L, udata, index, tracking); + } + + static T* get_no_lua_nil_from(lua_State* L, void* udata, int index, record&) { + if (detail::has_derived::value && luaL_getmetafield(L, index, &detail::base_class_cast_key()[0]) != 0) { + void* basecastdata = lua_touserdata(L, -1); + detail::inheritance_cast_function ic = (detail::inheritance_cast_function)basecastdata; + // use the casting function to properly adjust the pointer for the desired T + udata = ic(udata, detail::id_for::value); + lua_pop(L, 1); + } + T* obj = static_cast(udata); + return obj; + } + + static T& get(lua_State* L, int index, record& tracking) { + return *get_no_lua_nil(L, index, tracking); + } + }; + + template + struct getter> { + static T* get(lua_State* L, int index, record& tracking) { + type t = type_of(L, index); + if (t == type::lua_nil) { + tracking.use(1); + return nullptr; + } + getter> g; + // Avoid VC++ warning + (void)g; + return g.get_no_lua_nil(L, index, tracking); + } + }; + + template + struct getter> { + static T* get(lua_State* L, int index, record& tracking) { + getter> g; + // Avoid VC++ warning + (void)g; + return g.get_no_lua_nil(L, index, tracking); + } + }; + + template + struct getter { + static T& get(lua_State* L, int index, record& tracking) { + getter> g; + // Avoid VC++ warning + (void)g; + return g.get(L, index, tracking); + } + }; + + template + struct getter> { + static T& get(lua_State* L, int index, record& tracking) { + getter g; + // Avoid VC++ warning + (void)g; + return g.get(L, index, tracking); + } + }; + + template + struct getter { + static T* get(lua_State* L, int index, record& tracking) { + getter> g; + // Avoid VC++ warning + (void)g; + return g.get(L, index, tracking); + } + }; + + template + struct getter::value>> { + typedef typename unique_usertype_traits::type P; + typedef typename unique_usertype_traits::actual_type Real; + + static Real& get(lua_State* L, int index, record& tracking) { + tracking.use(1); + P** pref = static_cast(lua_touserdata(L, index)); + detail::special_destruct_func* fx = static_cast(static_cast(pref + 1)); + Real* mem = static_cast(static_cast(fx + 1)); + return *mem; + } + }; + + template + struct getter> { + typedef std::tuple(nullptr, 0))...> R; + + template + static R apply(std::index_sequence<>, lua_State*, int, record&, TArgs&&... args) { + // Fuck you too, VC++ + return R{std::forward(args)...}; + } + + template + static R apply(std::index_sequence, lua_State* L, int index, record& tracking, TArgs&&... args) { + // Fuck you too, VC++ + typedef std::tuple_element_t> T; + return apply(std::index_sequence(), L, index, tracking, std::forward(args)..., stack::get(L, index + tracking.used, tracking)); + } + + static R get(lua_State* L, int index, record& tracking) { + return apply(std::make_index_sequence(), L, index, tracking); + } + }; + + template + struct getter> { + static decltype(auto) get(lua_State* L, int index, record& tracking) { + return std::pair(L, index)), decltype(stack::get(L, index))>{stack::get(L, index, tracking), stack::get(L, index + tracking.used, tracking)}; + } + }; + } // stack +} // sol + +// end of sol/stack_get.hpp + +// beginning of sol/stack_check_get.hpp + +namespace sol { + namespace stack { + template + struct check_getter { + typedef decltype(stack_detail::unchecked_get(nullptr, 0, std::declval())) R; + + template + static optional get(lua_State* L, int index, Handler&& handler, record& tracking) { + if (!check(L, index, std::forward(handler))) { + tracking.use(static_cast(!lua_isnone(L, index))); + return nullopt; + } + return stack_detail::unchecked_get(L, index, tracking); + } + }; + + template + struct check_getter> { + template + static decltype(auto) get(lua_State* L, int index, Handler&&, record& tracking) { + return check_get(L, index, no_panic, tracking); + } + }; + + template + struct check_getter::value && lua_type_of::value == type::number>> { + template + static optional get(lua_State* L, int index, Handler&& handler, record& tracking) { + int isnum = 0; + lua_Integer value = lua_tointegerx(L, index, &isnum); + if (isnum == 0) { + type t = type_of(L, index); + tracking.use(static_cast(t != type::none)); + handler(L, index, type::number, t); + return nullopt; + } + tracking.use(1); + return static_cast(value); + } + }; + + template + struct check_getter::value && !meta::any_same::value>> { + template + static optional get(lua_State* L, int index, Handler&& handler, record& tracking) { + int isnum = 0; + lua_Integer value = lua_tointegerx(L, index, &isnum); + if (isnum == 0) { + type t = type_of(L, index); + tracking.use(static_cast(t != type::none)); + handler(L, index, type::number, t); + return nullopt; + } + tracking.use(1); + return static_cast(value); + } + }; + + template + struct check_getter::value>> { + template + static optional get(lua_State* L, int index, Handler&& handler, record& tracking) { + int isnum = 0; + lua_Number value = lua_tonumberx(L, index, &isnum); + if (isnum == 0) { + type t = type_of(L, index); + tracking.use(static_cast(t != type::none)); + handler(L, index, type::number, t); + return nullopt; + } + tracking.use(1); + return static_cast(value); + } + }; + + template + struct getter> { + static decltype(auto) get(lua_State* L, int index, record& tracking) { + return check_get(L, index, no_panic, tracking); + } + }; + } // stack +} // sol + +// end of sol/stack_check_get.hpp + +// beginning of sol/stack_push.hpp + +// beginning of sol/raii.hpp + +namespace sol { + namespace detail { + struct default_construct { + template + static void construct(T&& obj, Args&&... args) { + std::allocator> alloc{}; + alloc.construct(obj, std::forward(args)...); + } + + template + void operator()(T&& obj, Args&&... args) const { + construct(std::forward(obj), std::forward(args)...); + } + }; + + struct default_destruct { + template + static void destroy(T&& obj) { + std::allocator> alloc{}; + alloc.destroy(obj); + } + + template + void operator()(T&& obj) const { + destroy(std::forward(obj)); + } + }; + + struct deleter { + template + void operator()(T* p) const { + delete p; + } + }; + + template + inline std::unique_ptr make_unique_deleter(Args&&... args) { + return std::unique_ptr(new T(std::forward(args)...)); + } + + template + struct tagged { + T value; + template , tagged>> = meta::enabler> + tagged(Arg&& arg, Args&&... args) : value(std::forward(arg), std::forward(args)...) {} + }; + } // detail + + template + struct constructor_list {}; + + template + using constructors = constructor_list; + + const auto default_constructor = constructors>{}; + + struct no_construction {}; + const auto no_constructor = no_construction{}; + + struct call_construction {}; + const auto call_constructor = call_construction{}; + + template + struct constructor_wrapper { + std::tuple functions; + template , constructor_wrapper>> = meta::enabler> + constructor_wrapper(Arg&& arg, Args&&... args) : functions(std::forward(arg), std::forward(args)...) {} + }; + + template + inline auto initializers(Functions&&... functions) { + return constructor_wrapper...>(std::forward(functions)...); + } + + template + struct factory_wrapper { + std::tuple functions; + template , factory_wrapper>> = meta::enabler> + factory_wrapper(Arg&& arg, Args&&... args) : functions(std::forward(arg), std::forward(args)...) {} + }; + + template + inline auto factories(Functions&&... functions) { + return factory_wrapper...>(std::forward(functions)...); + } + + template + struct destructor_wrapper { + Function fx; + destructor_wrapper(Function f) : fx(std::move(f)) {} + }; + + template <> + struct destructor_wrapper {}; + + const destructor_wrapper default_destructor{}; + + template + inline auto destructor(Fx&& fx) { + return destructor_wrapper>(std::forward(fx)); + } + +} // sol + +// end of sol/raii.hpp + +#ifdef SOL_CODECVT_SUPPORT +#endif + +namespace sol { + namespace stack { + inline int push_environment_of(lua_State* L, int index = -1) { +#if SOL_LUA_VERSION < 502 + // Use lua_setfenv + lua_getfenv(L, index); + return 1; +#else + // Use upvalues as explained in Lua 5.2 and beyond's manual + if (lua_getupvalue(L, index, 1) == nullptr) { + push(L, lua_nil); + return 1; + } +#endif + return 1; + } + + template + int push_environment_of(const T& target) { + target.push(); + return push_environment_of(target.lua_state(), -1) + 1; + } + + template + struct pusher> { + template + static int push_fx(lua_State* L, F&& f, Args&&... args) { + // Basically, we store all user-data like this: + // If it's a movable/copyable value (no std::ref(x)), then we store the pointer to the new + // data in the first sizeof(T*) bytes, and then however many bytes it takes to + // do the actual object. Things that are std::ref or plain T* are stored as + // just the sizeof(T*), and nothing else. + T** pointerpointer = static_cast(lua_newuserdata(L, sizeof(T*) + sizeof(T))); + T*& referencereference = *pointerpointer; + T* allocationtarget = reinterpret_cast(pointerpointer + 1); + referencereference = allocationtarget; + std::allocator alloc{}; + alloc.construct(allocationtarget, std::forward(args)...); + f(); + return 1; + } + + template + static int push_keyed(lua_State* L, K&& k, Args&&... args) { + return push_fx(L, [&L, &k]() { + luaL_newmetatable(L, &k[0]); + lua_setmetatable(L, -2); + }, std::forward(args)...); + } + + template + static int push(lua_State* L, Args&&... args) { + return push_keyed(L, usertype_traits::metatable(), std::forward(args)...); + } + }; + + template + struct pusher> { + template + static int push_fx(lua_State* L, F&& f, T* obj) { + if (obj == nullptr) + return stack::push(L, lua_nil); + T** pref = static_cast(lua_newuserdata(L, sizeof(T*))); + *pref = obj; + f(); + return 1; + } + + template + static int push_keyed(lua_State* L, K&& k, T* obj) { + return push_fx(L, [&L, &k]() { + luaL_newmetatable(L, &k[0]); + lua_setmetatable(L, -2); + }, obj); + } + + static int push(lua_State* L, T* obj) { + return push_keyed(L, usertype_traits*>::metatable(), obj); + } + }; + + template <> + struct pusher { + template + static int push(lua_State* L, T&& obj) { + return stack::push(L, detail::ptr(obj)); + } + }; + + template + struct pusher { + template + static int push(lua_State* L, Args&&... args) { + return pusher>{}.push(L, std::forward(args)...); + } + }; + + template + struct pusher>, meta::neg>, std::is_base_of>>>>::value>> { + template + static int push(lua_State* L, Args&&... args) { + return pusher>{}.push(L, std::forward(args)...); + } + }; + + template + struct pusher::value>> { + typedef typename unique_usertype_traits::type P; + typedef typename unique_usertype_traits::actual_type Real; + + template >> = meta::enabler> + static int push(lua_State* L, Arg&& arg) { + if (unique_usertype_traits::is_null(arg)) + return stack::push(L, lua_nil); + return push_deep(L, std::forward(arg)); + } + + template + static int push(lua_State* L, Arg0&& arg0, Arg0&& arg1, Args&&... args) { + return push_deep(L, std::forward(arg0), std::forward(arg1), std::forward(args)...); + } + + template + static int push_deep(lua_State* L, Args&&... args) { + P** pref = static_cast(lua_newuserdata(L, sizeof(P*) + sizeof(detail::special_destruct_func) + sizeof(Real))); + detail::special_destruct_func* fx = static_cast(static_cast(pref + 1)); + Real* mem = static_cast(static_cast(fx + 1)); + *fx = detail::special_destruct; + detail::default_construct::construct(mem, std::forward(args)...); + *pref = unique_usertype_traits::get(*mem); + if (luaL_newmetatable(L, &usertype_traits>::metatable()[0]) == 1) { + set_field(L, "__gc", detail::unique_destruct

); + } + lua_setmetatable(L, -2); + return 1; + } + }; + + template + struct pusher> { + static int push(lua_State* L, const std::reference_wrapper& t) { + return stack::push(L, std::addressof(detail::deref(t.get()))); + } + }; + + template + struct pusher::value>> { + static int push(lua_State* L, const T& value) { + lua_pushnumber(L, value); + return 1; + } + }; + + template + struct pusher, std::is_signed>::value>> { + static int push(lua_State* L, const T& value) { + lua_pushinteger(L, static_cast(value)); + return 1; + } + }; + + template + struct pusher::value>> { + static int push(lua_State* L, const T& value) { + if (std::is_same::value) { + return stack::push(L, static_cast(value)); + } + return stack::push(L, static_cast>(value)); + } + }; + + template + struct pusher, std::is_unsigned>::value>> { + static int push(lua_State* L, const T& value) { + lua_pushinteger(L, static_cast(value)); + return 1; + } + }; + + template + struct pusher, std::enable_if_t>>::value>> { + static int push(lua_State* L, const as_table_t& tablecont) { + auto& cont = detail::deref(detail::unwrap(tablecont.source)); + lua_createtable(L, static_cast(cont.size()), 0); + int tableindex = lua_gettop(L); + std::size_t index = 1; + for (const auto& i : cont) { +#if SOL_LUA_VERSION >= 503 + int p = stack::push(L, i); + for (int pi = 0; pi < p; ++pi) { + lua_seti(L, tableindex, static_cast(index++)); + } +#else + lua_pushinteger(L, static_cast(index)); + int p = stack::push(L, i); + if (p == 1) { + ++index; + lua_settable(L, tableindex); + } + else { + int firstindex = tableindex + 1 + 1; + for (int pi = 0; pi < p; ++pi) { + stack::push(L, index); + lua_pushvalue(L, firstindex); + lua_settable(L, tableindex); + ++index; + ++firstindex; + } + lua_pop(L, 1 + p); + } +#endif + } + // TODO: figure out a better way to do this...? + //set_field(L, -1, cont.size()); + return 1; + } + }; + + template + struct pusher, std::enable_if_t>>::value>> { + static int push(lua_State* L, const as_table_t& tablecont) { + auto& cont = detail::deref(detail::unwrap(tablecont.source)); + lua_createtable(L, static_cast(cont.size()), 0); + int tableindex = lua_gettop(L); + for (const auto& pair : cont) { + set_field(L, pair.first, pair.second, tableindex); + } + return 1; + } + }; + + template + struct pusher::value || std::is_base_of::value>> { + static int push(lua_State* L, const T& ref) { + return ref.push(L); + } + + static int push(lua_State* L, T&& ref) { + return ref.push(L); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, bool b) { + lua_pushboolean(L, b); + return 1; + } + }; + + template<> + struct pusher { + static int push(lua_State* L, lua_nil_t) { + lua_pushnil(L); + return 1; + } + }; + + template<> + struct pusher { + static int push(lua_State* L, metatable_t) { + lua_pushlstring(L, "__mt", 4); + return 1; + } + }; + + template<> + struct pusher> { + static int push(lua_State* L, lua_CFunction func, int n = 0) { + lua_pushcclosure(L, func, n); + return 1; + } + }; + + template<> + struct pusher { + static int push(lua_State* L, lua_CFunction func, int n = 0) { + lua_pushcclosure(L, func, n); + return 1; + } + }; + + template<> + struct pusher { + static int push(lua_State* L, c_closure cc) { + lua_pushcclosure(L, cc.c_function, cc.upvalues); + return 1; + } + }; + + template + struct pusher> { + template + static int push(std::index_sequence, lua_State* L, T&& c) { + int pushcount = multi_push(L, detail::forward_get(c.upvalues)...); + return stack::push(L, c_closure(c.c_function, pushcount)); + } + + template + static int push(lua_State* L, T&& c) { + return push(std::make_index_sequence<1 + sizeof...(Args)>(), L, std::forward(c)); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, void* userdata) { + lua_pushlightuserdata(L, userdata); + return 1; + } + }; + + template<> + struct pusher { + static int push(lua_State* L, lightuserdata_value userdata) { + lua_pushlightuserdata(L, userdata); + return 1; + } + }; + + template + struct pusher> { + static int push(lua_State* L, light l) { + lua_pushlightuserdata(L, static_cast(l.value)); + return 1; + } + }; + + template + struct pusher> { + template + static int push_with(lua_State* L, Key&& name, Args&&... args) { + // A dumb pusher + void* rawdata = lua_newuserdata(L, sizeof(T)); + T* data = static_cast(rawdata); + std::allocator alloc; + alloc.construct(data, std::forward(args)...); + if (with_meta) { + lua_CFunction cdel = detail::user_alloc_destroy; + // Make sure we have a plain GC set for this data + if (luaL_newmetatable(L, name) != 0) { + lua_pushcclosure(L, cdel, 0); + lua_setfield(L, -2, "__gc"); + } + lua_setmetatable(L, -2); + } + return 1; + } + + template , no_metatable_t, metatable_t>> = meta::enabler> + static int push(lua_State* L, Arg&& arg, Args&&... args) { + const auto name = &usertype_traits>::user_gc_metatable()[0]; + return push_with(L, name, std::forward(arg), std::forward(args)...); + } + + template + static int push(lua_State* L, no_metatable_t, Args&&... args) { + const auto name = &usertype_traits>::user_gc_metatable()[0]; + return push_with(L, name, std::forward(args)...); + } + + template + static int push(lua_State* L, metatable_t, Key&& key, Args&&... args) { + const auto name = &key[0]; + return push_with(L, name, std::forward(args)...); + } + + static int push(lua_State* L, const user& u) { + const auto name = &usertype_traits>::user_gc_metatable()[0]; + return push_with(L, name, u.value); + } + + static int push(lua_State* L, user&& u) { + const auto name = &usertype_traits>::user_gc_metatable()[0]; + return push_with(L, name, std::move(u.value)); + } + + static int push(lua_State* L, no_metatable_t, const user& u) { + const auto name = &usertype_traits>::user_gc_metatable()[0]; + return push_with(L, name, u.value); + } + + static int push(lua_State* L, no_metatable_t, user&& u) { + const auto name = &usertype_traits>::user_gc_metatable()[0]; + return push_with(L, name, std::move(u.value)); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, userdata_value data) { + void** ud = static_cast(lua_newuserdata(L, sizeof(void*))); + *ud = data.value; + return 1; + } + }; + + template<> + struct pusher { + static int push_sized(lua_State* L, const char* str, std::size_t len) { + lua_pushlstring(L, str, len); + return 1; + } + + static int push(lua_State* L, const char* str) { + if (str == nullptr) + return stack::push(L, lua_nil); + return push_sized(L, str, std::char_traits::length(str)); + } + + static int push(lua_State* L, const char* strb, const char* stre) { + return push_sized(L, strb, stre - strb); + } + + static int push(lua_State* L, const char* str, std::size_t len) { + return push_sized(L, str, len); + } + }; + + template + struct pusher { + static int push(lua_State* L, const char(&str)[N]) { + lua_pushlstring(L, str, N - 1); + return 1; + } + + static int push(lua_State* L, const char(&str)[N], std::size_t sz) { + lua_pushlstring(L, str, sz); + return 1; + } + }; + + template <> + struct pusher { + static int push(lua_State* L, char c) { + const char str[2] = { c, '\0' }; + return stack::push(L, str, 1); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, const std::string& str) { + lua_pushlstring(L, str.c_str(), str.size()); + return 1; + } + + static int push(lua_State* L, const std::string& str, std::size_t sz) { + lua_pushlstring(L, str.c_str(), sz); + return 1; + } + }; + + template<> + struct pusher { + static int push(lua_State* L, meta_function m) { + const std::string& str = to_string(m); + lua_pushlstring(L, str.c_str(), str.size()); + return 1; + } + }; + +#ifdef SOL_CODECVT_SUPPORT + template<> + struct pusher { + static int push(lua_State* L, const wchar_t* wstr) { + return push(L, wstr, std::char_traits::length(wstr)); + } + + static int push(lua_State* L, const wchar_t* wstr, std::size_t sz) { + return push(L, wstr, wstr + sz); + } + + static int push(lua_State* L, const wchar_t* strb, const wchar_t* stre) { + if (sizeof(wchar_t) == 2) { + static std::wstring_convert> convert; + std::string u8str = convert.to_bytes(strb, stre); + return stack::push(L, u8str); + } + static std::wstring_convert> convert; + std::string u8str = convert.to_bytes(strb, stre); + return stack::push(L, u8str); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, const char16_t* u16str) { + return push(L, u16str, std::char_traits::length(u16str)); + } + + static int push(lua_State* L, const char16_t* u16str, std::size_t sz) { + return push(L, u16str, u16str + sz); + } + + static int push(lua_State* L, const char16_t* strb, const char16_t* stre) { +#ifdef _MSC_VER + static std::wstring_convert, int16_t> convert; + std::string u8str = convert.to_bytes(reinterpret_cast(strb), reinterpret_cast(stre)); +#else + static std::wstring_convert, char16_t> convert; + std::string u8str = convert.to_bytes(strb, stre); +#endif // VC++ is a shit + return stack::push(L, u8str); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, const char32_t* u32str) { + return push(L, u32str, u32str + std::char_traits::length(u32str)); + } + + static int push(lua_State* L, const char32_t* u32str, std::size_t sz) { + return push(L, u32str, u32str + sz); + } + + static int push(lua_State* L, const char32_t* strb, const char32_t* stre) { +#ifdef _MSC_VER + static std::wstring_convert, int32_t> convert; + std::string u8str = convert.to_bytes(reinterpret_cast(strb), reinterpret_cast(stre)); +#else + static std::wstring_convert, char32_t> convert; + std::string u8str = convert.to_bytes(strb, stre); +#endif // VC++ is a shit + return stack::push(L, u8str); + } + }; + + template + struct pusher { + static int push(lua_State* L, const wchar_t(&str)[N]) { + return push(L, str, N - 1); + } + + static int push(lua_State* L, const wchar_t(&str)[N], std::size_t sz) { + return stack::push(L, str, str + sz); + } + }; + + template + struct pusher { + static int push(lua_State* L, const char16_t(&str)[N]) { + return push(L, str, N - 1); + } + + static int push(lua_State* L, const char16_t(&str)[N], std::size_t sz) { + return stack::push(L, str, str + sz); + } + }; + + template + struct pusher { + static int push(lua_State* L, const char32_t(&str)[N]) { + return push(L, str, N - 1); + } + + static int push(lua_State* L, const char32_t(&str)[N], std::size_t sz) { + return stack::push(L, str, str + sz); + } + }; + + template <> + struct pusher { + static int push(lua_State* L, wchar_t c) { + const wchar_t str[2] = { c, '\0' }; + return stack::push(L, str, 1); + } + }; + + template <> + struct pusher { + static int push(lua_State* L, char16_t c) { + const char16_t str[2] = { c, '\0' }; + return stack::push(L, str, 1); + } + }; + + template <> + struct pusher { + static int push(lua_State* L, char32_t c) { + const char32_t str[2] = { c, '\0' }; + return stack::push(L, str, 1); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, const std::wstring& wstr) { + return push(L, wstr.data(), wstr.size()); + } + + static int push(lua_State* L, const std::wstring& wstr, std::size_t sz) { + return stack::push(L, wstr.data(), wstr.data() + sz); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, const std::u16string& u16str) { + return push(L, u16str, u16str.size()); + } + + static int push(lua_State* L, const std::u16string& u16str, std::size_t sz) { + return stack::push(L, u16str.data(), u16str.data() + sz); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, const std::u32string& u32str) { + return push(L, u32str, u32str.size()); + } + + static int push(lua_State* L, const std::u32string& u32str, std::size_t sz) { + return stack::push(L, u32str.data(), u32str.data() + sz); + } + }; +#endif // codecvt Header Support + + template + struct pusher> { + template + static int push(std::index_sequence, lua_State* L, T&& t) { + int pushcount = 0; + (void)detail::swallow{ 0, (pushcount += stack::push(L, + detail::forward_get(t) + ), 0)... }; + return pushcount; + } + + template + static int push(lua_State* L, T&& t) { + return push(std::index_sequence_for(), L, std::forward(t)); + } + }; + + template + struct pusher> { + template + static int push(lua_State* L, T&& t) { + int pushcount = stack::push(L, detail::forward_get<0>(t)); + pushcount += stack::push(L, detail::forward_get<1>(t)); + return pushcount; + } + }; + + template + struct pusher> { + template + static int push(lua_State* L, T&& t) { + if (t == nullopt) { + return stack::push(L, nullopt); + } + return stack::push(L, t.value()); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, nullopt_t) { + return stack::push(L, lua_nil); + } + }; + + template<> + struct pusher { + static int push(lua_State* L, std::nullptr_t) { + return stack::push(L, lua_nil); + } + }; + + template<> + struct pusher { + static int push(lua_State*, const this_state&) { + return 0; + } + }; + + template<> + struct pusher { + static int push(lua_State* L, const new_table& nt) { + lua_createtable(L, nt.sequence_hint, nt.map_hint); + return 1; + } + }; + } // stack +} // sol + +// end of sol/stack_push.hpp + +// beginning of sol/stack_pop.hpp + +namespace sol { + namespace stack { + template + struct popper { + inline static decltype(auto) pop(lua_State* L) { + record tracking{}; + decltype(auto) r = get(L, -lua_size::value, tracking); + lua_pop(L, tracking.used); + return r; + } + }; + + template + struct popper>::value>> { + static_assert(meta::neg>>::value, "You cannot pop something that derives from stack_reference: it will not remain on the stack and thusly will go out of scope!"); + }; + } // stack +} // sol + +// end of sol/stack_pop.hpp + +// beginning of sol/stack_field.hpp + +namespace sol { + namespace stack { + template + struct field_getter { + template + void get(lua_State* L, Key&& key, int tableindex = -2) { + push(L, std::forward(key)); + lua_gettable(L, tableindex); + } + }; + + template + struct field_getter { + template + void get(lua_State* L, Key&& key, int tableindex = -2) { + push(L, std::forward(key)); + lua_rawget(L, tableindex); + } + }; + + template + struct field_getter { + void get(lua_State* L, metatable_t, int tableindex = -1) { + if (lua_getmetatable(L, tableindex) == 0) + push(L, lua_nil); + } + }; + + template + struct field_getter { + void get(lua_State* L, env_t, int tableindex = -1) { +#if SOL_LUA_VERSION < 502 + // Use lua_setfenv + lua_getfenv(L, tableindex); +#else + // Use upvalues as explained in Lua 5.2 and beyond's manual + if (lua_getupvalue(L, tableindex, 1) == nullptr) { + push(L, lua_nil); + } +#endif + } + }; + + template + struct field_getter::value>> { + template + void get(lua_State* L, Key&& key, int = -1) { + lua_getglobal(L, &key[0]); + } + }; + + template + struct field_getter::value>> { + template + void get(lua_State* L, Key&& key, int tableindex = -1) { + lua_getfield(L, tableindex, &key[0]); + } + }; + +#if SOL_LUA_VERSION >= 503 + template + struct field_getter::value>> { + template + void get(lua_State* L, Key&& key, int tableindex = -1) { + lua_geti(L, tableindex, static_cast(key)); + } + }; +#endif // Lua 5.3.x + +#if SOL_LUA_VERSION >= 502 + template + struct field_getter { + void get(lua_State* L, void* key, int tableindex = -1) { + lua_rawgetp(L, tableindex, key); + } + }; +#endif // Lua 5.3.x + + template + struct field_getter::value>> { + template + void get(lua_State* L, Key&& key, int tableindex = -1) { + lua_rawgeti(L, tableindex, static_cast(key)); + } + }; + + template + struct field_getter, b, raw, C> { + template + void apply(std::index_sequence<0, I...>, lua_State* L, Keys&& keys, int tableindex) { + get_field(L, detail::forward_get<0>(keys), tableindex); + void(detail::swallow{ (get_field(L, detail::forward_get(keys)), 0)... }); + reference saved(L, -1); + lua_pop(L, static_cast(sizeof...(I))); + saved.push(); + } + + template + void get(lua_State* L, Keys&& keys) { + apply(std::make_index_sequence(), L, std::forward(keys), lua_absindex(L, -1)); + } + + template + void get(lua_State* L, Keys&& keys, int tableindex) { + apply(std::make_index_sequence(), L, std::forward(keys), tableindex); + } + }; + + template + struct field_getter, b, raw, C> { + template + void get(lua_State* L, Keys&& keys, int tableindex) { + get_field(L, detail::forward_get<0>(keys), tableindex); + get_field(L, detail::forward_get<1>(keys)); + reference saved(L, -1); + lua_pop(L, static_cast(2)); + saved.push(); + } + + template + void get(lua_State* L, Keys&& keys) { + get_field(L, detail::forward_get<0>(keys)); + get_field(L, detail::forward_get<1>(keys)); + reference saved(L, -1); + lua_pop(L, static_cast(2)); + saved.push(); + } + }; + + template + struct field_setter { + template + void set(lua_State* L, Key&& key, Value&& value, int tableindex = -3) { + push(L, std::forward(key)); + push(L, std::forward(value)); + lua_settable(L, tableindex); + } + }; + + template + struct field_setter { + template + void set(lua_State* L, Key&& key, Value&& value, int tableindex = -3) { + push(L, std::forward(key)); + push(L, std::forward(value)); + lua_rawset(L, tableindex); + } + }; + + template + struct field_setter { + template + void set(lua_State* L, metatable_t, Value&& value, int tableindex = -2) { + push(L, std::forward(value)); + lua_setmetatable(L, tableindex); + } + }; + + template + struct field_setter::value>> { + template + void set(lua_State* L, Key&& key, Value&& value, int = -2) { + push(L, std::forward(value)); + lua_setglobal(L, &key[0]); + } + }; + + template + struct field_setter::value>> { + template + void set(lua_State* L, Key&& key, Value&& value, int tableindex = -2) { + push(L, std::forward(value)); + lua_setfield(L, tableindex, &key[0]); + } + }; + +#if SOL_LUA_VERSION >= 503 + template + struct field_setter::value>> { + template + void set(lua_State* L, Key&& key, Value&& value, int tableindex = -2) { + push(L, std::forward(value)); + lua_seti(L, tableindex, static_cast(key)); + } + }; +#endif // Lua 5.3.x + + template + struct field_setter::value>> { + template + void set(lua_State* L, Key&& key, Value&& value, int tableindex = -2) { + push(L, std::forward(value)); + lua_rawseti(L, tableindex, static_cast(key)); + } + }; + +#if SOL_LUA_VERSION >= 502 + template + struct field_setter { + template + void set(lua_State* L, void* key, Value&& value, int tableindex = -2) { + push(L, std::forward(value)); + lua_rawsetp(L, tableindex, key); + } + }; +#endif // Lua 5.2.x + + template + struct field_setter, b, raw, C> { + template + void apply(std::index_sequence, lua_State* L, Key&& keys, Value&& value, int tableindex) { + I < 1 ? + set_field(L, detail::forward_get(keys), std::forward(value), tableindex) : + set_field(L, detail::forward_get(keys), std::forward(value)); + } + + template + void apply(std::index_sequence, lua_State* L, Keys&& keys, Value&& value, int tableindex) { + I0 < 1 ? get_field(L, detail::forward_get(keys), tableindex) : get_field(L, detail::forward_get(keys), -1); + apply(std::index_sequence(), L, std::forward(keys), std::forward(value), -1); + } + + template + void top_apply(std::index_sequence, lua_State* L, Keys&& keys, Value&& value, int tableindex) { + apply(std::index_sequence(), L, std::forward(keys), std::forward(value), tableindex); + lua_pop(L, static_cast(sizeof...(I))); + } + + template + void set(lua_State* L, Keys&& keys, Value&& value, int tableindex = -3) { + top_apply(std::make_index_sequence(), L, std::forward(keys), std::forward(value), tableindex); + } + }; + + template + struct field_setter, b, raw, C> { + template + void set(lua_State* L, Keys&& keys, Value&& value, int tableindex = -1) { + get_field(L, detail::forward_get<0>(keys), tableindex); + set_field(L, detail::forward_get<1>(keys), std::forward(value)); + lua_pop(L, 1); + } + }; + } // stack +} // sol + +// end of sol/stack_field.hpp + +// beginning of sol/stack_probe.hpp + +namespace sol { + namespace stack { + template + struct probe_field_getter { + template + probe get(lua_State* L, Key&& key, int tableindex = -2) { + if (!b && !maybe_indexable(L, tableindex)) { + return probe(false, 0); + } + get_field(L, std::forward(key), tableindex); + return probe(!check(L), 1); + } + }; + + template + struct probe_field_getter, b, raw, C> { + template + probe get(lua_State* L, Keys&& keys, int tableindex = -2) { + if (!b && !maybe_indexable(L, tableindex)) { + return probe(false, 0); + } + get_field(L, std::get<0>(keys), tableindex); + if (!maybe_indexable(L)) { + return probe(false, 1); + } + get_field(L, std::get<1>(keys), tableindex); + return probe(!check(L), 2); + } + }; + + template + struct probe_field_getter, b, raw, C> { + template + probe apply(std::index_sequence, int sofar, lua_State* L, Keys&& keys, int tableindex) { + get_field < I < 1 && b, raw>(L, std::get(keys), tableindex); + return probe(!check(L), sofar); + } + + template + probe apply(std::index_sequence, int sofar, lua_State* L, Keys&& keys, int tableindex) { + get_field < I < 1 && b, raw>(L, std::get(keys), tableindex); + if (!maybe_indexable(L)) { + return probe(false, sofar); + } + return apply(std::index_sequence(), sofar + 1, L, std::forward(keys), -1); + } + + template + probe get(lua_State* L, Keys&& keys, int tableindex = -2) { + if (!b && !maybe_indexable(L, tableindex)) { + return probe(false, 0); + } + return apply(std::index_sequence_for(), 1, L, std::forward(keys), tableindex); + } + }; + } // stack +} // sol + +// end of sol/stack_probe.hpp + +#include + +namespace sol { + namespace stack { + namespace stack_detail { + template + inline int push_as_upvalues(lua_State* L, T& item) { + typedef std::decay_t TValue; + const static std::size_t itemsize = sizeof(TValue); + const static std::size_t voidsize = sizeof(void*); + const static std::size_t voidsizem1 = voidsize - 1; + const static std::size_t data_t_count = (sizeof(TValue) + voidsizem1) / voidsize; + typedef std::array data_t; + + data_t data{ {} }; + std::memcpy(&data[0], std::addressof(item), itemsize); + int pushcount = 0; + for (auto&& v : data) { + pushcount += push(L, lightuserdata_value(v)); + } + return pushcount; + } + + template + inline std::pair get_as_upvalues(lua_State* L, int index = 1) { + const static std::size_t data_t_count = (sizeof(T) + (sizeof(void*) - 1)) / sizeof(void*); + typedef std::array data_t; + data_t voiddata{ {} }; + for (std::size_t i = 0, d = 0; d < sizeof(T); ++i, d += sizeof(void*)) { + voiddata[i] = get(L, upvalue_index(index++)); + } + return std::pair(*reinterpret_cast(static_cast(voiddata.data())), index); + } + + struct evaluator { + template + static decltype(auto) eval(types<>, std::index_sequence<>, lua_State*, int, record&, Fx&& fx, Args&&... args) { + return std::forward(fx)(std::forward(args)...); + } + + template + static decltype(auto) eval(types, std::index_sequence, lua_State* L, int start, record& tracking, Fx&& fx, FxArgs&&... fxargs) { + return eval(types(), std::index_sequence(), L, start, tracking, std::forward(fx), std::forward(fxargs)..., stack_detail::unchecked_get(L, start + tracking.used, tracking)); + } + }; + + template ::value>> + inline decltype(auto) call(types, types ta, std::index_sequence tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { +#ifndef _MSC_VER + static_assert(meta::all...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention."); +#endif // This compiler make me so fucking sad + multi_check(L, start, type_panic); + record tracking{}; + return evaluator{}.eval(ta, tai, L, start, tracking, std::forward(fx), std::forward(args)...); + } + + template + inline void call(types, types ta, std::index_sequence tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { +#ifndef _MSC_VER + static_assert(meta::all...>::value, "One of the arguments being bound is a move-only type, and it is not being taken by reference: this will break your code. Please take a reference and std::move it manually if this was your intention."); +#endif // This compiler make me so fucking sad + multi_check(L, start, type_panic); + record tracking{}; + evaluator{}.eval(ta, tai, L, start, tracking, std::forward(fx), std::forward(args)...); + } + } // stack_detail + + template + int set_ref(lua_State* L, T&& arg, int tableindex = -2) { + push(L, std::forward(arg)); + return luaL_ref(L, tableindex); + } + + template ::value>> + inline decltype(auto) call(types tr, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { + typedef std::make_index_sequence args_indices; + return stack_detail::call(tr, ta, args_indices(), L, start, std::forward(fx), std::forward(args)...); + } + + template ::value>> + inline decltype(auto) call(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { + return call(tr, ta, L, 1, std::forward(fx), std::forward(args)...); + } + + template + inline void call(types tr, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... args) { + typedef std::make_index_sequence args_indices; + stack_detail::call(tr, ta, args_indices(), L, start, std::forward(fx), std::forward(args)...); + } + + template + inline void call(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { + call(tr, ta, L, 1, std::forward(fx), std::forward(args)...); + } + + template ::value>> + inline decltype(auto) call_from_top(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { + return call(tr, ta, L, static_cast(lua_gettop(L) - sizeof...(Args)), std::forward(fx), std::forward(args)...); + } + + template + inline void call_from_top(types tr, types ta, lua_State* L, Fx&& fx, FxArgs&&... args) { + call(tr, ta, L, static_cast(lua_gettop(L) - sizeof...(Args)), std::forward(fx), std::forward(args)...); + } + + template + inline int call_into_lua(types tr, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { + call(tr, ta, L, start, std::forward(fx), std::forward(fxargs)...); + lua_settop(L, 0); + return 0; + } + + template>::value>> + inline int call_into_lua(types, types ta, lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { + decltype(auto) r = call(types>(), ta, L, start, std::forward(fx), std::forward(fxargs)...); + lua_settop(L, 0); + return push_reference(L, std::forward(r)); + } + + template + inline int call_lua(lua_State* L, int start, Fx&& fx, FxArgs&&... fxargs) { + typedef lua_bind_traits> traits_type; + typedef typename traits_type::args_list args_list; + typedef typename traits_type::returns_list returns_list; + return call_into_lua(returns_list(), args_list(), L, start, std::forward(fx), std::forward(fxargs)...); + } + + inline call_syntax get_call_syntax(lua_State* L, const std::string& key, int index) { + if (lua_gettop(L) == 0) { + return call_syntax::dot; + } + luaL_getmetatable(L, key.c_str()); + auto pn = pop_n(L, 1); + if (lua_compare(L, -1, index, LUA_OPEQ) != 1) { + return call_syntax::dot; + } + return call_syntax::colon; + } + + inline void script(lua_State* L, const std::string& code) { + if (luaL_dostring(L, code.c_str())) { + lua_error(L); + } + } + + inline void script_file(lua_State* L, const std::string& filename) { + if (luaL_dofile(L, filename.c_str())) { + lua_error(L); + } + } + + inline void luajit_exception_handler(lua_State* L, int(*handler)(lua_State*, lua_CFunction) = detail::c_trampoline) { +#ifdef SOL_LUAJIT + lua_pushlightuserdata(L, (void*)handler); + auto pn = pop_n(L, 1); + luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON); +#else + (void)L; + (void)handler; +#endif + } + + inline void luajit_exception_off(lua_State* L) { +#ifdef SOL_LUAJIT + luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_OFF); +#else + (void)L; +#endif + } + } // stack +} // sol + +// end of sol/stack.hpp + +// beginning of sol/object_base.hpp + +namespace sol { + + template + class basic_object_base : public base_t { + private: + template + decltype(auto) as_stack(std::true_type) const { + return stack::get(base_t::lua_state(), base_t::stack_index()); + } + + template + decltype(auto) as_stack(std::false_type) const { + base_t::push(); + return stack::pop(base_t::lua_state()); + } + + template + bool is_stack(std::true_type) const { + return stack::check(base_t::lua_state(), base_t::stack_index(), no_panic); + } + + template + bool is_stack(std::false_type) const { + int r = base_t::registry_index(); + if (r == LUA_REFNIL) + return meta::any_same, lua_nil_t, nullopt_t, std::nullptr_t>::value ? true : false; + if (r == LUA_NOREF) + return false; + auto pp = stack::push_pop(*this); + return stack::check(base_t::lua_state(), -1, no_panic); + } + + public: + basic_object_base() noexcept = default; + basic_object_base(const basic_object_base&) = default; + basic_object_base(basic_object_base&&) = default; + basic_object_base& operator=(const basic_object_base&) = default; + basic_object_base& operator=(basic_object_base&&) = default; + template , basic_object_base>>> = meta::enabler> + basic_object_base(T&& arg, Args&&... args) : base_t(std::forward(arg), std::forward(args)...) { } + + template + decltype(auto) as() const { + return as_stack(std::is_same()); + } + + template + bool is() const { + return is_stack(std::is_same()); + } + }; +} // sol + +// end of sol/object_base.hpp + +// beginning of sol/userdata.hpp + +namespace sol { + template + class basic_userdata : public basic_table { + typedef basic_table base_t; + public: + basic_userdata() noexcept = default; + template , basic_userdata>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_userdata(T&& r) noexcept : base_t(std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_userdata>::value) { + auto pp = stack::push_pop(*this); + type_assert(base_t::lua_state(), -1, type::userdata); + } +#endif // Safety + } + basic_userdata(const basic_userdata&) = default; + basic_userdata(basic_userdata&&) = default; + basic_userdata& operator=(const basic_userdata&) = default; + basic_userdata& operator=(basic_userdata&&) = default; + basic_userdata(const stack_reference& r) : basic_userdata(r.lua_state(), r.stack_index()) {} + basic_userdata(stack_reference&& r) : basic_userdata(r.lua_state(), r.stack_index()) {} + template >>, meta::neg, ref_index>>> = meta::enabler> + basic_userdata(lua_State* L, T&& r) : basic_userdata(L, sol::ref_index(r.registry_index())) {} + basic_userdata(lua_State* L, int index = -1) : base_t(detail::no_safety, L, index) { +#ifdef SOL_CHECK_ARGUMENTS + stack::check(L, index, type_panic); +#endif // Safety + } + basic_userdata(lua_State* L, ref_index index) : base_t(detail::no_safety, L, index) { +#ifdef SOL_CHECK_ARGUMENTS + auto pp = stack::push_pop(*this); + stack::check(L, index, type_panic); +#endif // Safety + } + }; + + template + class basic_lightuserdata : public basic_object_base { + typedef basic_object_base base_t; + public: + basic_lightuserdata() noexcept = default; + template , basic_lightuserdata>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_lightuserdata(T&& r) noexcept : base_t(std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_lightuserdata>::value) { + auto pp = stack::push_pop(*this); + type_assert(base_t::lua_state(), -1, type::lightuserdata); + } +#endif // Safety + } + basic_lightuserdata(const basic_lightuserdata&) = default; + basic_lightuserdata(basic_lightuserdata&&) = default; + basic_lightuserdata& operator=(const basic_lightuserdata&) = default; + basic_lightuserdata& operator=(basic_lightuserdata&&) = default; + basic_lightuserdata(const stack_reference& r) : basic_lightuserdata(r.lua_state(), r.stack_index()) {} + basic_lightuserdata(stack_reference&& r) : basic_lightuserdata(r.lua_state(), r.stack_index()) {} + template >>, meta::neg, ref_index>>> = meta::enabler> + basic_lightuserdata(lua_State* L, T&& r) : basic_lightuserdata(L, sol::ref_index(r.registry_index())) {} + basic_lightuserdata(lua_State* L, int index = -1) : base_t(L, index) { +#ifdef SOL_CHECK_ARGUMENTS + stack::check(L, index, type_panic); +#endif // Safety + } + basic_lightuserdata(lua_State* L, ref_index index) : base_t(L, index) { +#ifdef SOL_CHECK_ARGUMENTS + auto pp = stack::push_pop(*this); + stack::check(L, index, type_panic); +#endif // Safety + } + }; + +} // sol + +// end of sol/userdata.hpp + +// beginning of sol/as_args.hpp + +namespace sol { + template + struct to_args_t { + T src; + }; + + template + auto as_args(Source&& source) { + return to_args_t{ std::forward(source) }; + } + + namespace stack { + template + struct pusher> { + int push(lua_State* L, const to_args_t& e) { + int p = 0; + for (const auto& i : e.src) { + p += stack::push(L, i); + } + return p; + } + }; + } +} // sol + +// end of sol/as_args.hpp + +// beginning of sol/variadic_args.hpp + +// beginning of sol/stack_proxy.hpp + +// beginning of sol/function.hpp + +// beginning of sol/function_result.hpp + +// beginning of sol/proxy_base.hpp + +namespace sol { + struct proxy_base_tag {}; + + template + struct proxy_base : proxy_base_tag { + operator std::string() const { + const Super& super = *static_cast(static_cast(this)); + return super.template get(); + } + + template>, is_proxy_primitive>> = meta::enabler> + operator T () const { + const Super& super = *static_cast(static_cast(this)); + return super.template get(); + } + + template>, meta::neg>>> = meta::enabler> + operator T& () const { + const Super& super = *static_cast(static_cast(this)); + return super.template get(); + } + }; +} // sol + +// end of sol/proxy_base.hpp + +#include + +namespace sol { + struct function_result : public proxy_base { + private: + lua_State* L; + int index; + int returncount; + + public: + function_result() = default; + function_result(lua_State* Ls, int idx = -1, int retnum = 0) : L(Ls), index(idx), returncount(retnum) { + + } + function_result(const function_result&) = default; + function_result& operator=(const function_result&) = default; + function_result(function_result&& o) : L(o.L), index(o.index), returncount(o.returncount) { + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but will be thorough + o.L = nullptr; + o.index = 0; + o.returncount = 0; + } + function_result& operator=(function_result&& o) { + L = o.L; + index = o.index; + returncount = o.returncount; + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but will be thorough + o.L = nullptr; + o.index = 0; + o.returncount = 0; + return *this; + } + + template + decltype(auto) get() const { + return stack::get(L, index); + } + + call_status status() const noexcept { + return call_status::ok; + } + + bool valid() const noexcept { + return status() == call_status::ok || status() == call_status::yielded; + } + + lua_State* lua_state() const { return L; }; + int stack_index() const { return index; }; + + ~function_result() { + lua_pop(L, returncount); + } + }; +} // sol + +// end of sol/function_result.hpp + +// beginning of sol/function_types.hpp + +// beginning of sol/function_types_core.hpp + +// beginning of sol/wrapper.hpp + +namespace sol { + + template + struct wrapper { + typedef lua_bind_traits traits_type; + typedef typename traits_type::args_list args_list; + typedef typename traits_type::args_list free_args_list; + typedef typename traits_type::returns_list returns_list; + + template + static decltype(auto) call(F& f, Args&&... args) { + return f(std::forward(args)...); + } + + struct caller { + template + decltype(auto) operator()(F& fx, Args&&... args) const { + return call(fx, std::forward(args)...); + } + }; + }; + + template + struct wrapper>>::value>> { + typedef lua_bind_traits traits_type; + typedef typename traits_type::args_list args_list; + typedef typename traits_type::args_list free_args_list; + typedef typename traits_type::returns_list returns_list; + + template + static decltype(auto) invoke(Args&&... args) { + return fx(std::forward(args)...); + } + + template + static decltype(auto) call(F& fx, Args&&... args) { + return fx(std::forward(args)...); + } + + struct caller { + template + decltype(auto) operator()(F& fx, Args&&... args) const { + return call(fx, std::forward(args)...); + } + }; + + template + struct invoker { + template + decltype(auto) operator()(Args&&... args) const { + return invoke(std::forward(args)...); + } + }; + }; + + template + struct wrapper>::value>> { + typedef lua_bind_traits traits_type; + typedef typename traits_type::object_type object_type; + typedef typename traits_type::return_type return_type; + typedef typename traits_type::args_list args_list; + typedef types free_args_list; + typedef typename traits_type::returns_list returns_list; + + template + static decltype(auto) invoke(object_type& mem, Args&&... args) { + return (mem.*fx)(std::forward(args)...); + } + + template + static decltype(auto) call(Fx&& fx, object_type& mem) { + return (mem.*fx); + } + + template + static void call(Fx&& fx, object_type& mem, Arg&& arg, Args&&...) { + (mem.*fx) = std::forward(arg); + } + + struct caller { + template + decltype(auto) operator()(Fx&& fx, object_type& mem, Args&&... args) const { + return call(std::forward(fx), mem, std::forward(args)...); + } + }; + + template + struct invoker { + template + decltype(auto) operator()(Args&&... args) const { + return invoke(std::forward(args)...); + } + }; + }; + + template + struct member_function_wrapper { + typedef O object_type; + typedef lua_bind_traits traits_type; + typedef typename traits_type::args_list args_list; + typedef types free_args_list; + typedef meta::tuple_types returns_list; + + template + static R invoke(O& mem, Args&&... args) { + return (mem.*fx)(std::forward(args)...); + } + + template + static R call(Fx&& fx, O& mem, Args&&... args) { + return (mem.*fx)(std::forward(args)...); + } + + struct caller { + template + decltype(auto) operator()(Fx&& fx, O& mem, Args&&... args) const { + return call(std::forward(fx), mem, std::forward(args)...); + } + }; + + template + struct invoker { + template + decltype(auto) operator()(O& mem, Args&&... args) const { + return invoke(mem, std::forward(args)...); + } + }; + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + + template + struct wrapper : public member_function_wrapper { + + }; + +} // sol + +// end of sol/wrapper.hpp + +namespace sol { + namespace function_detail { + template + inline int call(lua_State* L) { + Fx& fx = stack::get>(L, upvalue_index(1)); + return fx(L); + } + } // function_detail +} // sol + +// end of sol/function_types_core.hpp + +// beginning of sol/function_types_templated.hpp + +// beginning of sol/call.hpp + +// beginning of sol/protect.hpp + +namespace sol { + + template + struct protect_t { + T value; + + template >> = meta::enabler> + protect_t(Arg&& arg, Args&&... args) : value(std::forward(arg), std::forward(args)...) {} + + protect_t(const protect_t&) = default; + protect_t(protect_t&&) = default; + protect_t& operator=(const protect_t&) = default; + protect_t& operator=(protect_t&&) = default; + + }; + + template + auto protect(T&& value) { + return protect_t>(std::forward(value)); + } + +} // sol + +// end of sol/protect.hpp + +// beginning of sol/property.hpp + +namespace sol { + + struct no_prop { }; + + template + struct property_wrapper { + typedef std::integral_constant::value> can_read; + typedef std::integral_constant::value> can_write; + typedef std::conditional_t Read; + typedef std::conditional_t Write; + Read read; + Write write; + + template + property_wrapper(Rx&& r, Wx&& w) : read(std::forward(r)), write(std::forward(w)) {} + }; + + namespace property_detail { + template + inline decltype(auto) property(std::true_type, R&& read, W&& write) { + return property_wrapper, std::decay_t>(std::forward(read), std::forward(write)); + } + template + inline decltype(auto) property(std::false_type, W&& write, R&& read) { + return property_wrapper, std::decay_t>(std::forward(read), std::forward(write)); + } + template + inline decltype(auto) property(std::true_type, R&& read) { + return property_wrapper, void>(std::forward(read), no_prop()); + } + template + inline decltype(auto) property(std::false_type, W&& write) { + return property_wrapper>(no_prop(), std::forward(write)); + } + } // property_detail + + template + inline decltype(auto) property(F&& f, G&& g) { + typedef lua_bind_traits> left_traits; + typedef lua_bind_traits> right_traits; + return property_detail::property(meta::boolean<(left_traits::free_arity < right_traits::free_arity)>(), std::forward(f), std::forward(g)); + } + + template + inline decltype(auto) property(F&& f) { + typedef lua_bind_traits> left_traits; + return property_detail::property(meta::boolean<(left_traits::free_arity < 2)>(), std::forward(f)); + } + + template + inline decltype(auto) readonly_property(F&& f) { + return property_detail::property(std::true_type(), std::forward(f)); + } + + template + inline decltype(auto) writeonly_property(F&& f) { + return property_detail::property(std::false_type(), std::forward(f)); + } + + // Allow someone to make a member variable readonly (const) + template + inline auto readonly(R T::* v) { + typedef const R C; + return static_cast(v); + } + + template + struct var_wrapper { + T value; + template + var_wrapper(Args&&... args) : value(std::forward(args)...) {} + var_wrapper(const var_wrapper&) = default; + var_wrapper(var_wrapper&&) = default; + var_wrapper& operator=(const var_wrapper&) = default; + var_wrapper& operator=(var_wrapper&&) = default; + }; + + template + inline auto var(V&& v) { + typedef meta::unqualified_t T; + return var_wrapper(std::forward(v)); + } + +} // sol + +// end of sol/property.hpp + +namespace sol { + namespace function_detail { + inline int no_construction_error(lua_State* L) { + return luaL_error(L, "sol: cannot call this constructor (tagged as non-constructible)"); + } + } + + namespace call_detail { + + template + inline auto& pick(std::true_type, property_wrapper& f) { + return f.read; + } + + template + inline auto& pick(std::false_type, property_wrapper& f) { + return f.write; + } + + template + struct void_call : void_call> {}; + + template + struct void_call> { + static void call(Args...) {} + }; + + template + struct constructor_match { + T* obj; + + constructor_match(T* o) : obj(o) {} + + template + int operator()(types, index_value, types r, types a, lua_State* L, int, int start) const { + detail::default_construct func{}; + return stack::call_into_lua(r, a, L, start, func, obj); + } + }; + + namespace overload_detail { + template + inline int overload_match_arity(types<>, std::index_sequence<>, std::index_sequence, Match&&, lua_State* L, int, int, Args&&...) { + return luaL_error(L, "sol: no matching function call takes this number of arguments and the specified types"); + } + + template + inline int overload_match_arity(types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + typedef lua_bind_traits> traits; + typedef meta::tuple_types return_types; + typedef typename traits::free_args_list args_list; + // compile-time eliminate any functions that we know ahead of time are of improper arity + if (meta::find_in_pack_v, index_value...>::value) { + return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + if (!traits::runtime_variadics_t::value && traits::free_arity != fxarity) { + return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + stack::record tracking{}; + if (!stack::stack_detail::check_types{}.check(args_list(), L, start, no_panic, tracking)) { + return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + return matchfx(types(), index_value(), return_types(), args_list(), L, fxarity, start, std::forward(args)...); + } + + template + inline int overload_match_arity_single(types<>, std::index_sequence<>, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + + template + inline int overload_match_arity_single(types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + typedef lua_bind_traits> traits; + typedef meta::tuple_types return_types; + typedef typename traits::free_args_list args_list; + // compile-time eliminate any functions that we know ahead of time are of improper arity + if (meta::find_in_pack_v, index_value...>::value) { + return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + if (!traits::runtime_variadics_t::value && traits::free_arity != fxarity) { + return overload_match_arity(types<>(), std::index_sequence<>(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + return matchfx(types(), index_value(), return_types(), args_list(), L, fxarity, start, std::forward(args)...); + } + + template + inline int overload_match_arity_single(types, std::index_sequence, std::index_sequence, Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + typedef lua_bind_traits> traits; + typedef meta::tuple_types return_types; + typedef typename traits::free_args_list args_list; + // compile-time eliminate any functions that we know ahead of time are of improper arity + if (meta::find_in_pack_v, index_value...>::value) { + return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + if (!traits::runtime_variadics_t::value && traits::free_arity != fxarity) { + return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + stack::record tracking{}; + if (!stack::stack_detail::check_types{}.check(args_list(), L, start, no_panic, tracking)) { + return overload_match_arity(types(), std::index_sequence(), std::index_sequence(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + return matchfx(types(), index_value(), return_types(), args_list(), L, fxarity, start, std::forward(args)...); + } + } // overload_detail + + template + inline int overload_match_arity(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + return overload_detail::overload_match_arity_single(types(), std::make_index_sequence(), std::index_sequence<>(), std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + + template + inline int overload_match(Match&& matchfx, lua_State* L, int start, Args&&... args) { + int fxarity = lua_gettop(L) - (start - 1); + return overload_match_arity(std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + + template + inline int construct_match(Match&& matchfx, lua_State* L, int fxarity, int start, Args&&... args) { + // use same overload resolution matching as all other parts of the framework + return overload_match_arity::call)...>(std::forward(matchfx), L, fxarity, start, std::forward(args)...); + } + + template + inline int construct(lua_State* L) { + static const auto& meta = usertype_traits::metatable(); + int argcount = lua_gettop(L); + call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits::user_metatable()[0], 1) : call_syntax::dot; + argcount -= static_cast(syntax); + + T** pointerpointer = reinterpret_cast(lua_newuserdata(L, sizeof(T*) + sizeof(T))); + T*& referencepointer = *pointerpointer; + T* obj = reinterpret_cast(pointerpointer + 1); + referencepointer = obj; + reference userdataref(L, -1); + userdataref.pop(); + + construct_match(constructor_match(obj), L, argcount, 1 + static_cast(syntax)); + + userdataref.push(); + luaL_getmetatable(L, &meta[0]); + if (type_of(L, -1) == type::lua_nil) { + lua_pop(L, 1); + return luaL_error(L, "sol: unable to get usertype metatable"); + } + + lua_setmetatable(L, -2); + return 1; + } + + template + struct agnostic_lua_call_wrapper { + template + static int call(lua_State* L, Fx&& f, Args&&... args) { + typedef wrapper> wrap; + typedef typename wrap::returns_list returns_list; + typedef typename wrap::free_args_list args_list; + typedef typename wrap::caller caller; + return stack::call_into_lua(returns_list(), args_list(), L, boost + 1, caller(), std::forward(f), std::forward(args)...); + } + }; + + template + struct agnostic_lua_call_wrapper, true, is_variable, checked, boost, C> { + template + static int call(lua_State* L, F&& f) { + return stack::push_reference(L, detail::unwrap(f.value)); + } + }; + + template + struct agnostic_lua_call_wrapper, false, is_variable, checked, boost, C> { + template + static int call_assign(std::true_type, lua_State* L, V&& f) { + detail::unwrap(f.value) = stack::get>(L, boost + (is_variable ? 3 : 1)); + return 0; + } + + template + static int call_assign(std::false_type, lua_State* L, Args&&...) { + return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); + } + + template + static int call_const(std::false_type, lua_State* L, Args&&... args) { + typedef meta::unwrapped_t R; + return call_assign(std::is_assignable>, R>(), L, std::forward(args)...); + } + + template + static int call_const(std::true_type, lua_State* L, Args&&...) { + return luaL_error(L, "sol: cannot write to a readonly (const) variable"); + } + + template + static int call(lua_State* L, V&& f) { + return call_const(std::is_const>(), L, f); + } + }; + + template + struct agnostic_lua_call_wrapper { + static int call(lua_State* L, lua_r_CFunction f) { + return f(L); + } + }; + + template + struct agnostic_lua_call_wrapper { + static int call(lua_State* L, lua_CFunction f) { + return f(L); + } + }; + + template + struct agnostic_lua_call_wrapper { + static int call(lua_State* L, const no_prop&) { + return luaL_error(L, is_index ? "sol: cannot read from a writeonly property" : "sol: cannot write to a readonly property"); + } + }; + + template + struct agnostic_lua_call_wrapper { + static int call(lua_State* L, const no_construction&) { + return function_detail::no_construction_error(L); + } + }; + + template + struct agnostic_lua_call_wrapper, is_index, is_variable, checked, boost, C> { + static int call(lua_State*, const bases&) { + // Uh. How did you even call this, lul + return 0; + } + }; + + template + struct lua_call_wrapper : agnostic_lua_call_wrapper {}; + + template + struct lua_call_wrapper::value>> { + typedef wrapper> wrap; + typedef typename wrap::object_type object_type; + + template + static int call(lua_State* L, Fx&& f, object_type& o) { + typedef typename wrap::returns_list returns_list; + typedef typename wrap::args_list args_list; + typedef typename wrap::caller caller; + return stack::call_into_lua(returns_list(), args_list(), L, boost + ( is_variable ? 3 : 2 ), caller(), std::forward(f), o); + } + + template + static int call(lua_State* L, Fx&& f) { + typedef std::conditional_t::value, object_type, T> Ta; +#ifdef SOL_SAFE_USERTYPE + auto maybeo = stack::check_get(L, 1); + if (!maybeo || maybeo.value() == nullptr) { + return luaL_error(L, "sol: received nil for 'self' argument (use ':' for accessing member functions, make sure member variables are preceeded by the actual object with '.' syntax)"); + } + object_type* o = static_cast(maybeo.value()); + return call(L, std::forward(f), *o); +#else + object_type& o = static_cast(*stack::get>(L, 1)); + return call(L, std::forward(f), o); +#endif // Safety + } + }; + + template + struct lua_call_wrapper::value>> { + typedef lua_bind_traits traits_type; + typedef wrapper> wrap; + typedef typename wrap::object_type object_type; + + template + static int call_assign(std::true_type, lua_State* L, V&& f, object_type& o) { + typedef typename wrap::args_list args_list; + typedef typename wrap::caller caller; + return stack::call_into_lua(types(), args_list(), L, boost + ( is_variable ? 3 : 2 ), caller(), f, o); + } + + template + static int call_assign(std::true_type, lua_State* L, V&& f) { + typedef std::conditional_t::value, object_type, T> Ta; +#ifdef SOL_SAFE_USERTYPE + auto maybeo = stack::check_get(L, 1); + if (!maybeo || maybeo.value() == nullptr) { + if (is_variable) { + return luaL_error(L, "sol: received nil for 'self' argument (bad '.' access?)"); + } + return luaL_error(L, "sol: received nil for 'self' argument (pass 'self' as first argument)"); + } + object_type* o = static_cast(maybeo.value()); + return call_assign(std::true_type(), L, f, *o); +#else + object_type& o = static_cast(*stack::get>(L, 1)); + return call_assign(std::true_type(), L, f, o); +#endif // Safety + } + + template + static int call_assign(std::false_type, lua_State* L, Args&&...) { + return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); + } + + template + static int call_const(std::false_type, lua_State* L, Args&&... args) { + typedef typename traits_type::return_type R; + return call_assign(std::is_assignable>, R>(), L, std::forward(args)...); + } + + template + static int call_const(std::true_type, lua_State* L, Args&&...) { + return luaL_error(L, "sol: cannot write to a readonly (const) variable"); + } + + template + static int call(lua_State* L, V&& f) { + return call_const(std::is_const(), L, std::forward(f)); + } + + template + static int call(lua_State* L, V&& f, object_type& o) { + return call_const(std::is_const(), L, std::forward(f), o); + } + }; + + template + struct lua_call_wrapper::value>> { + typedef lua_bind_traits traits_type; + typedef wrapper> wrap; + typedef typename wrap::object_type object_type; + + template + static int call(lua_State* L, V&& f, object_type& o) { + typedef typename wrap::returns_list returns_list; + typedef typename wrap::caller caller; + return stack::call_into_lua(returns_list(), types<>(), L, boost + ( is_variable ? 3 : 2 ), caller(), std::forward(f), o); + } + + template + static int call(lua_State* L, V&& f) { + typedef std::conditional_t::value, object_type, T> Ta; +#ifdef SOL_SAFE_USERTYPE + auto maybeo = stack::check_get(L, 1); + if (!maybeo || maybeo.value() == nullptr) { + if (is_variable) { + return luaL_error(L, "sol: 'self' argument is lua_nil (bad '.' access?)"); + } + return luaL_error(L, "sol: 'self' argument is lua_nil (pass 'self' as first argument)"); + } + object_type* o = static_cast(maybeo.value()); + return call(L, f, *o); +#else + object_type& o = static_cast(*stack::get>(L, 1)); + return call(L, f, o); +#endif // Safety + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, C> { + typedef constructor_list F; + + static int call(lua_State* L, F&) { + const auto& metakey = usertype_traits::metatable(); + int argcount = lua_gettop(L); + call_syntax syntax = argcount > 0 ? stack::get_call_syntax(L, &usertype_traits::user_metatable()[0], 1) : call_syntax::dot; + argcount -= static_cast(syntax); + + T** pointerpointer = reinterpret_cast(lua_newuserdata(L, sizeof(T*) + sizeof(T))); + reference userdataref(L, -1); + T*& referencepointer = *pointerpointer; + T* obj = reinterpret_cast(pointerpointer + 1); + referencepointer = obj; + + construct_match(constructor_match(obj), L, argcount, boost + 1 + static_cast(syntax)); + + userdataref.push(); + luaL_getmetatable(L, &metakey[0]); + if (type_of(L, -1) == type::lua_nil) { + lua_pop(L, 1); + return luaL_error(L, "sol: unable to get usertype metatable"); + } + + lua_setmetatable(L, -2); + return 1; + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, C> { + typedef constructor_wrapper F; + + struct onmatch { + template + int operator()(types, index_value, types r, types a, lua_State* L, int, int start, F& f) { + const auto& metakey = usertype_traits::metatable(); + T** pointerpointer = reinterpret_cast(lua_newuserdata(L, sizeof(T*) + sizeof(T))); + reference userdataref(L, -1); + T*& referencepointer = *pointerpointer; + T* obj = reinterpret_cast(pointerpointer + 1); + referencepointer = obj; + + auto& func = std::get(f.functions); + stack::call_into_lua(r, a, L, boost + start, func, detail::implicit_wrapper(obj)); + + userdataref.push(); + luaL_getmetatable(L, &metakey[0]); + if (type_of(L, -1) == type::lua_nil) { + lua_pop(L, 1); + std::string err = "sol: unable to get usertype metatable for "; + err += usertype_traits::name(); + return luaL_error(L, err.c_str()); + } + lua_setmetatable(L, -2); + + return 1; + } + }; + + static int call(lua_State* L, F& f) { + call_syntax syntax = stack::get_call_syntax(L, &usertype_traits::user_metatable()[0], 1); + int syntaxval = static_cast(syntax); + int argcount = lua_gettop(L) - syntaxval; + return construct_match>...>(onmatch(), L, argcount, 1 + syntaxval, f); + } + + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, std::enable_if_t::value>> { + typedef destructor_wrapper F; + + static int call(lua_State* L, const F&) { + return detail::usertype_alloc_destroy(L); + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, std::enable_if_t::value>> { + typedef destructor_wrapper F; + + static int call(lua_State* L, const F& f) { + T& obj = stack::get(L); + f.fx(detail::implicit_wrapper(obj)); + return 0; + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, C> { + typedef overload_set F; + + struct on_match { + template + int operator()(types, index_value, types, types, lua_State* L, int, int, F& fx) { + auto& f = std::get(fx.functions); + return lua_call_wrapper{}.call(L, f); + } + }; + + static int call(lua_State* L, F& fx) { + return overload_match_arity(on_match(), L, lua_gettop(L), 1, fx); + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, C> { + typedef factory_wrapper F; + + struct on_match { + template + int operator()(types, index_value, types, types, lua_State* L, int, int, F& fx) { + auto& f = std::get(fx.functions); + return lua_call_wrapper{}.call(L, f); + } + }; + + static int call(lua_State* L, F& fx) { + return overload_match_arity(on_match(), L, lua_gettop(L) - boost, 1 + boost, fx); + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, C> { + typedef std::conditional_t P; + typedef meta::unqualified_t

U; + typedef wrapper wrap; + typedef lua_bind_traits traits_type; + typedef meta::unqualified_t> object_type; + + template + static int self_call(std::true_type, lua_State* L, F&& f) { + // The type being void means we don't have any arguments, so it might be a free functions? + typedef typename traits_type::free_args_list args_list; + typedef typename wrap::returns_list returns_list; + typedef typename wrap::caller caller; + return stack::call_into_lua(returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), f); + } + + template + static int self_call(std::false_type, lua_State* L, F&& f) { + typedef meta::pop_front_type_t args_list; + typedef T Ta; +#ifdef SOL_SAFE_USERTYPE + auto maybeo = stack::check_get(L, 1); + if (!maybeo || maybeo.value() == nullptr) { + if (is_variable) { + return luaL_error(L, "sol: 'self' argument is lua_nil (bad '.' access?)"); + } + return luaL_error(L, "sol: 'self' argument is lua_nil (pass 'self' as first argument)"); + } + object_type* o = static_cast(maybeo.value()); +#else + object_type* o = static_cast(stack::get>(L, 1)); +#endif // Safety + typedef typename wrap::returns_list returns_list; + typedef typename wrap::caller caller; + return stack::call_into_lua(returns_list(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), f, *o); + } + + template + static int defer_call(std::false_type, lua_State* L, F&& f, Args&&... args) { + return self_call(meta::any, meta::boolean>::value != type::userdata>>(), L, pick(meta::boolean(), f), std::forward(args)...); + } + + template + static int defer_call(std::true_type, lua_State* L, F&& f, Args&&... args) { + auto& p = pick(meta::boolean(), std::forward(f)); + return lua_call_wrapper, is_index, is_variable, checked, boost>{}.call(L, p, std::forward(args)...); + } + + template + static int call(lua_State* L, F&& f, Args&&... args) { + typedef meta::any< + std::is_void, + std::is_same, + meta::is_specialization_of, + meta::is_specialization_of, + meta::is_specialization_of, + std::is_member_pointer + > is_specialized; + return defer_call(is_specialized(), L, std::forward(f), std::forward(args)...); + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, C> { + typedef protect_t F; + + template + static int call(lua_State* L, F& fx, Args&&... args) { + return lua_call_wrapper{}.call(L, fx.value, std::forward(args)...); + } + }; + + template + struct lua_call_wrapper, is_index, is_variable, checked, boost, C> { + template + static int call(lua_State* L, F&& f) { + return lua_call_wrapper, is_index, is_variable, stack::stack_detail::default_check_arguments, boost>{}.call(L, std::get<0>(f.arguments)); + } + }; + + template + inline int call_wrapped(lua_State* L, Fx&& fx, Args&&... args) { + return lua_call_wrapper, is_index, is_variable, stack::stack_detail::default_check_arguments, boost>{}.call(L, std::forward(fx), std::forward(args)...); + } + + template + inline int call_user(lua_State* L) { + auto& fx = stack::get>(L, upvalue_index(1)); + return call_wrapped(L, fx); + } + + template + struct is_var_bind : std::false_type {}; + + template + struct is_var_bind::value>> : std::true_type {}; + + template <> + struct is_var_bind : std::true_type {}; + + template + struct is_var_bind> : std::true_type {}; + + template + struct is_var_bind> : std::true_type {}; + } // call_detail + + template + struct is_variable_binding : call_detail::is_var_bind> {}; + + template + struct is_function_binding : meta::neg> {}; + +} // sol + +// end of sol/call.hpp + +namespace sol { + namespace function_detail { + template + inline int call_wrapper_variable(std::false_type, lua_State* L) { + typedef meta::bind_traits> traits_type; + typedef typename traits_type::args_list args_list; + typedef meta::tuple_types return_type; + return stack::call_into_lua(return_type(), args_list(), L, 1, fx); + } + + template + inline int call_set_assignable(std::false_type, T&&, lua_State* L) { + return luaL_error(L, "cannot write to this type: copy assignment/constructor not available"); + } + + template + inline int call_set_assignable(std::true_type, lua_State* L, T&& mem) { + (mem.*variable) = stack::get(L, 2); + return 0; + } + + template + inline int call_set_variable(std::false_type, lua_State* L, T&&) { + return luaL_error(L, "cannot write to a const variable"); + } + + template + inline int call_set_variable(std::true_type, lua_State* L, T&& mem) { + return call_set_assignable(std::is_assignable, R>(), L, std::forward(mem)); + } + + template + inline int call_wrapper_variable(std::true_type, lua_State* L) { + typedef meta::bind_traits> traits_type; + typedef typename traits_type::object_type T; + typedef typename traits_type::return_type R; + auto& mem = stack::get(L, 1); + switch (lua_gettop(L)) { + case 1: { + decltype(auto) r = (mem.*variable); + stack::push_reference(L, std::forward(r)); + return 1; } + case 2: + return call_set_variable(meta::neg>(), L, mem); + default: + return luaL_error(L, "incorrect number of arguments to member variable function call"); + } + } + + template + inline int call_wrapper_function(std::false_type, lua_State* L) { + return call_wrapper_variable(std::is_member_object_pointer(), L); + } + + template + inline int call_wrapper_function(std::true_type, lua_State* L) { + return call_detail::call_wrapped(L, fx); + } + + template + int call_wrapper_entry(lua_State* L) { + return call_wrapper_function(std::is_member_function_pointer>(), L); + } + + template + struct c_call_matcher { + template + int operator()(types, index_value, types, types, lua_State* L, int, int) const { + typedef meta::at_in_pack_t target; + return target::call(L); + } + }; + + } // function_detail + + template + inline int c_call(lua_State* L) { +#ifdef __clang__ + return detail::trampoline(L, function_detail::call_wrapper_entry); +#else + return detail::static_trampoline<(&function_detail::call_wrapper_entry)>(L); +#endif // fuck you clang :c + } + + template + struct wrap { + typedef F type; + + static int call(lua_State* L) { + return c_call(L); + } + }; + + template + inline int c_call(lua_State* L) { + if (sizeof...(Fxs) < 2) { + return meta::at_in_pack_t<0, Fxs...>::call(L); + } + else { + return call_detail::overload_match_arity(function_detail::c_call_matcher(), L, lua_gettop(L), 1); + } + } + +} // sol + +// end of sol/function_types_templated.hpp + +// beginning of sol/function_types_stateless.hpp + +namespace sol { + namespace function_detail { + template + struct upvalue_free_function { + typedef std::remove_pointer_t> function_type; + typedef lua_bind_traits traits_type; + + static int real_call(lua_State* L) { + auto udata = stack::stack_detail::get_as_upvalues(L); + function_type* fx = udata.first; + return call_detail::call_wrapped(L, fx); + } + + static int call(lua_State* L) { + return detail::static_trampoline<(&real_call)>(L); + } + + int operator()(lua_State* L) { + return call(L); + } + }; + + template + struct upvalue_member_function { + typedef std::remove_pointer_t> function_type; + typedef lua_bind_traits traits_type; + + static int real_call(lua_State* L) { + // Layout: + // idx 1...n: verbatim data of member function pointer + // idx n + 1: is the object's void pointer + // We don't need to store the size, because the other side is templated + // with the same member function pointer type + auto memberdata = stack::stack_detail::get_as_upvalues(L, 1); + auto objdata = stack::stack_detail::get_as_upvalues(L, memberdata.second); + function_type& memfx = memberdata.first; + auto& item = *objdata.first; + return call_detail::call_wrapped(L, memfx, item); + } + + static int call(lua_State* L) { + return detail::static_trampoline<(&real_call)>(L); + } + + int operator()(lua_State* L) { + return call(L); + } + }; + + template + struct upvalue_member_variable { + typedef std::remove_pointer_t> function_type; + typedef lua_bind_traits traits_type; + + static int real_call(lua_State* L) { + // Layout: + // idx 1...n: verbatim data of member variable pointer + // idx n + 1: is the object's void pointer + // We don't need to store the size, because the other side is templated + // with the same member function pointer type + auto memberdata = stack::stack_detail::get_as_upvalues(L, 1); + auto objdata = stack::stack_detail::get_as_upvalues(L, memberdata.second); + auto& mem = *objdata.first; + function_type& var = memberdata.first; + switch (lua_gettop(L)) { + case 0: + return call_detail::call_wrapped(L, var, mem); + case 1: + return call_detail::call_wrapped(L, var, mem); + default: + return luaL_error(L, "sol: incorrect number of arguments to member variable function"); + } + } + + static int call(lua_State* L) { + return detail::static_trampoline<(&real_call)>(L); + } + + int operator()(lua_State* L) { + return call(L); + } + }; + + template + struct upvalue_this_member_function { + typedef std::remove_pointer_t> function_type; + typedef lua_bind_traits traits_type; + + static int real_call(lua_State* L) { + // Layout: + // idx 1...n: verbatim data of member variable pointer + auto memberdata = stack::stack_detail::get_as_upvalues(L, 1); + function_type& memfx = memberdata.first; + return call_detail::call_wrapped(L, memfx); + } + + static int call(lua_State* L) { + return detail::static_trampoline<(&real_call)>(L); + } + + int operator()(lua_State* L) { + return call(L); + } + }; + + template + struct upvalue_this_member_variable { + typedef std::remove_pointer_t> function_type; + typedef lua_bind_traits traits_type; + + static int real_call(lua_State* L) { + // Layout: + // idx 1...n: verbatim data of member variable pointer + auto memberdata = stack::stack_detail::get_as_upvalues(L, 1); + function_type& var = memberdata.first; + switch (lua_gettop(L)) { + case 1: + return call_detail::call_wrapped(L, var); + case 2: + return call_detail::call_wrapped(L, var); + default: + return luaL_error(L, "sol: incorrect number of arguments to member variable function"); + } + } + + static int call(lua_State* L) { + return detail::static_trampoline<(&real_call)>(L); + } + + int operator()(lua_State* L) { + return call(L); + } + }; + } // function_detail +} // sol + +// end of sol/function_types_stateless.hpp + +// beginning of sol/function_types_stateful.hpp + +namespace sol { + namespace function_detail { + template + struct functor_function { + typedef meta::unwrapped_t> Function; + Function fx; + + template + functor_function(Function f, Args&&... args) : fx(std::move(f), std::forward(args)...) {} + + int call(lua_State* L) { + return call_detail::call_wrapped(L, fx); + } + + int operator()(lua_State* L) { + auto f = [&](lua_State*) -> int { return this->call(L); }; + return detail::trampoline(L, f); + } + }; + + template + struct member_function { + typedef std::remove_pointer_t> function_type; + typedef meta::function_return_t return_type; + typedef meta::function_args_t args_lists; + function_type invocation; + T member; + + template + member_function(function_type f, Args&&... args) : invocation(std::move(f)), member(std::forward(args)...) {} + + int call(lua_State* L) { + return call_detail::call_wrapped(L, invocation, detail::unwrap(detail::deref(member))); + } + + int operator()(lua_State* L) { + auto f = [&](lua_State*) -> int { return this->call(L); }; + return detail::trampoline(L, f); + } + }; + + template + struct member_variable { + typedef std::remove_pointer_t> function_type; + typedef typename meta::bind_traits::return_type return_type; + typedef typename meta::bind_traits::args_list args_lists; + function_type var; + T member; + typedef std::add_lvalue_reference_t>> M; + + template + member_variable(function_type v, Args&&... args) : var(std::move(v)), member(std::forward(args)...) {} + + int call(lua_State* L) { + M mem = detail::unwrap(detail::deref(member)); + switch (lua_gettop(L)) { + case 0: + return call_detail::call_wrapped(L, var, mem); + case 1: + return call_detail::call_wrapped(L, var, mem); + default: + return luaL_error(L, "sol: incorrect number of arguments to member variable function"); + } + } + + int operator()(lua_State* L) { + auto f = [&](lua_State*) -> int { return this->call(L); }; + return detail::trampoline(L, f); + } + }; + } // function_detail +} // sol + +// end of sol/function_types_stateful.hpp + +// beginning of sol/function_types_overloaded.hpp + +namespace sol { + namespace function_detail { + template + struct overloaded_function { + typedef std::tuple overload_list; + typedef std::make_index_sequence indices; + overload_list overloads; + + overloaded_function(overload_list set) + : overloads(std::move(set)) {} + + overloaded_function(Functions... fxs) + : overloads(fxs...) { + + } + + template + int call(types, index_value, types, types, lua_State* L, int, int) { + auto& func = std::get(overloads); + return call_detail::call_wrapped(L, func); + } + + int operator()(lua_State* L) { + auto mfx = [&](auto&&... args) { return this->call(std::forward(args)...); }; + return call_detail::overload_match(mfx, L, 1 + start_skew); + } + }; + } // function_detail +} // sol + +// end of sol/function_types_overloaded.hpp + +// beginning of sol/resolve.hpp + +namespace sol { + +#ifndef __clang__ + // constexpr is fine for not-clang + + namespace detail { + template(Args...)>> + inline constexpr auto resolve_i(types, F&&)->R(meta::unqualified_t::*)(Args...) { + using Sig = R(Args...); + typedef meta::unqualified_t Fu; + return static_cast(&Fu::operator()); + } + + template> + inline constexpr auto resolve_f(std::true_type, F&& f) + -> decltype(resolve_i(types>(), std::forward(f))) { + return resolve_i(types>(), std::forward(f)); + } + + template + inline constexpr void resolve_f(std::false_type, F&&) { + static_assert(meta::has_deducible_signature::value, + "Cannot use no-template-parameter call with an overloaded functor: specify the signature"); + } + + template> + inline constexpr auto resolve_i(types<>, F&& f) -> decltype(resolve_f(meta::has_deducible_signature(), std::forward(f))) { + return resolve_f(meta::has_deducible_signature {}, std::forward(f)); + } + + template> + inline constexpr auto resolve_i(types, F&& f) -> decltype(resolve_i(types(), std::forward(f))) { + return resolve_i(types(), std::forward(f)); + } + + template + inline constexpr Sig C::* resolve_v(std::false_type, Sig C::* mem_func_ptr) { + return mem_func_ptr; + } + + template + inline constexpr Sig C::* resolve_v(std::true_type, Sig C::* mem_variable_ptr) { + return mem_variable_ptr; + } + } // detail + + template + inline constexpr auto resolve(R fun_ptr(Args...))->R(*)(Args...) { + return fun_ptr; + } + + template + inline constexpr Sig* resolve(Sig* fun_ptr) { + return fun_ptr; + } + + template + inline constexpr auto resolve(R(C::*mem_ptr)(Args...))->R(C::*)(Args...) { + return mem_ptr; + } + + template + inline constexpr Sig C::* resolve(Sig C::* mem_ptr) { + return detail::resolve_v(std::is_member_object_pointer(), mem_ptr); + } + + template>> = meta::enabler> + inline constexpr auto resolve(F&& f) -> decltype(detail::resolve_i(types(), std::forward(f))) { + return detail::resolve_i(types(), std::forward(f)); + } +#else + + // Clang has distinct problems with constexpr arguments, + // so don't use the constexpr versions inside of clang. + + namespace detail { + template(Args...)>> + inline auto resolve_i(types, F&&)->R(meta::unqualified_t::*)(Args...) { + using Sig = R(Args...); + typedef meta::unqualified_t Fu; + return static_cast(&Fu::operator()); + } + + template> + inline auto resolve_f(std::true_type, F&& f) + -> decltype(resolve_i(types>(), std::forward(f))) { + return resolve_i(types>(), std::forward(f)); + } + + template + inline void resolve_f(std::false_type, F&&) { + static_assert(meta::has_deducible_signature::value, + "Cannot use no-template-parameter call with an overloaded functor: specify the signature"); + } + + template> + inline auto resolve_i(types<>, F&& f) -> decltype(resolve_f(meta::has_deducible_signature(), std::forward(f))) { + return resolve_f(meta::has_deducible_signature {}, std::forward(f)); + } + + template> + inline auto resolve_i(types, F&& f) -> decltype(resolve_i(types(), std::forward(f))) { + return resolve_i(types(), std::forward(f)); + } + + template + inline Sig C::* resolve_v(std::false_type, Sig C::* mem_func_ptr) { + return mem_func_ptr; + } + + template + inline Sig C::* resolve_v(std::true_type, Sig C::* mem_variable_ptr) { + return mem_variable_ptr; + } + } // detail + + template + inline auto resolve(R fun_ptr(Args...))->R(*)(Args...) { + return fun_ptr; + } + + template + inline Sig* resolve(Sig* fun_ptr) { + return fun_ptr; + } + + template + inline auto resolve(R(C::*mem_ptr)(Args...))->R(C::*)(Args...) { + return mem_ptr; + } + + template + inline Sig C::* resolve(Sig C::* mem_ptr) { + return detail::resolve_v(std::is_member_object_pointer(), mem_ptr); + } + + template + inline auto resolve(F&& f) -> decltype(detail::resolve_i(types(), std::forward(f))) { + return detail::resolve_i(types(), std::forward(f)); + } + +#endif + +} // sol + +// end of sol/resolve.hpp + +namespace sol { + namespace function_detail { + template + struct class_indicator {}; + + struct call_indicator {}; + } + namespace stack { + template + struct pusher> { + template + static void select_convertible(std::false_type, types, lua_State* L, Fx&& fx, Args&&... args) { + typedef std::remove_pointer_t> clean_fx; + typedef function_detail::functor_function F; + set_fx(L, std::forward(fx), std::forward(args)...); + } + + template + static void select_convertible(std::true_type, types, lua_State* L, Fx&& fx, Args&&... args) { + using fx_ptr_t = R(*)(A...); + fx_ptr_t fxptr = detail::unwrap(std::forward(fx)); + select_function(std::true_type(), L, fxptr, std::forward(args)...); + } + + template + static void select_convertible(types t, lua_State* L, Fx&& fx, Args&&... args) { + typedef std::decay_t> raw_fx_t; + typedef R(*fx_ptr_t)(A...); + typedef std::is_convertible is_convertible; + select_convertible(is_convertible(), t, L, std::forward(fx), std::forward(args)...); + } + + template + static void select_convertible(types<>, lua_State* L, Fx&& fx, Args&&... args) { + typedef meta::function_signature_t> Sig; + select_convertible(types(), L, std::forward(fx), std::forward(args)...); + } + + template + static void select_reference_member_variable(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef std::remove_pointer_t> clean_fx; + typedef function_detail::member_variable, clean_fx> F; + set_fx(L, std::forward(fx), std::forward(obj), std::forward(args)...); + } + + template + static void select_reference_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef std::decay_t dFx; + dFx memfxptr(std::forward(fx)); + auto userptr = detail::ptr(std::forward(obj), std::forward(args)...); + lua_CFunction freefunc = &function_detail::upvalue_member_variable, meta::unqualified_t>::call; + + int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr); + upvalues += stack::push(L, lightuserdata_value(static_cast(userptr))); + stack::push(L, c_closure(freefunc, upvalues)); + } + + template + static void select_member_variable(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { + select_convertible(types(), L, std::forward(fx), std::forward(args)...); + } + + template >> = meta::enabler> + static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef meta::boolean>::value || std::is_pointer::value> is_reference; + select_reference_member_variable(is_reference(), L, std::forward(fx), std::forward(obj), std::forward(args)...); + } + + template + static void select_member_variable(std::true_type, lua_State* L, Fx&& fx, function_detail::class_indicator) { + lua_CFunction freefunc = &function_detail::upvalue_this_member_variable::call; + int upvalues = stack::stack_detail::push_as_upvalues(L, fx); + stack::push(L, c_closure(freefunc, upvalues)); + } + + template + static void select_member_variable(std::true_type, lua_State* L, Fx&& fx) { + typedef typename meta::bind_traits>::object_type C; + lua_CFunction freefunc = &function_detail::upvalue_this_member_variable::call; + int upvalues = stack::stack_detail::push_as_upvalues(L, fx); + stack::push(L, c_closure(freefunc, upvalues)); + } + + template + static void select_reference_member_function(std::false_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef std::decay_t clean_fx; + typedef function_detail::member_function, clean_fx> F; + set_fx(L, std::forward(fx), std::forward(obj), std::forward(args)...); + } + + template + static void select_reference_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef std::decay_t dFx; + dFx memfxptr(std::forward(fx)); + auto userptr = detail::ptr(std::forward(obj), std::forward(args)...); + lua_CFunction freefunc = &function_detail::upvalue_member_function, meta::unqualified_t>::call; + + int upvalues = stack::stack_detail::push_as_upvalues(L, memfxptr); + upvalues += stack::push(L, lightuserdata_value(static_cast(userptr))); + stack::push(L, c_closure(freefunc, upvalues)); + } + + template + static void select_member_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { + select_member_variable(std::is_member_object_pointer>(), L, std::forward(fx), std::forward(args)...); + } + + template >> = meta::enabler> + static void select_member_function(std::true_type, lua_State* L, Fx&& fx, T&& obj, Args&&... args) { + typedef meta::boolean>::value || std::is_pointer::value> is_reference; + select_reference_member_function(is_reference(), L, std::forward(fx), std::forward(obj), std::forward(args)...); + } + + template + static void select_member_function(std::true_type, lua_State* L, Fx&& fx, function_detail::class_indicator) { + lua_CFunction freefunc = &function_detail::upvalue_this_member_function::call; + int upvalues = stack::stack_detail::push_as_upvalues(L, fx); + stack::push(L, c_closure(freefunc, upvalues)); + } + + template + static void select_member_function(std::true_type, lua_State* L, Fx&& fx) { + typedef typename meta::bind_traits>::object_type C; + lua_CFunction freefunc = &function_detail::upvalue_this_member_function::call; + int upvalues = stack::stack_detail::push_as_upvalues(L, fx); + stack::push(L, c_closure(freefunc, upvalues)); + } + + template + static void select_function(std::false_type, lua_State* L, Fx&& fx, Args&&... args) { + select_member_function(std::is_member_function_pointer>(), L, std::forward(fx), std::forward(args)...); + } + + template + static void select_function(std::true_type, lua_State* L, Fx&& fx, Args&&... args) { + std::decay_t target(std::forward(fx), std::forward(args)...); + lua_CFunction freefunc = &function_detail::upvalue_free_function::call; + + int upvalues = stack::stack_detail::push_as_upvalues(L, target); + stack::push(L, c_closure(freefunc, upvalues)); + } + + static void select_function(std::true_type, lua_State* L, lua_CFunction f) { + stack::push(L, f); + } + + template + static void select(lua_State* L, Fx&& fx, Args&&... args) { + select_function(std::is_function>(), L, std::forward(fx), std::forward(args)...); + } + + template + static void set_fx(lua_State* L, Args&&... args) { + lua_CFunction freefunc = function_detail::call>; + + stack::push>(L, std::forward(args)...); + stack::push(L, c_closure(freefunc, 1)); + } + + template + static int push(lua_State* L, Args&&... args) { + // Set will always place one thing (function) on the stack + select(L, std::forward(args)...); + return 1; + } + }; + + template + struct pusher> { + template + static int push_func(std::index_sequence, lua_State* L, FP&& fp) { + return stack::push(L, detail::forward_get(fp.arguments)...); + } + + static int push(lua_State* L, const function_arguments& fp) { + return push_func(std::make_index_sequence(), L, fp); + } + + static int push(lua_State* L, function_arguments&& fp) { + return push_func(std::make_index_sequence(), L, std::move(fp)); + } + }; + + template + struct pusher> { + static int push(lua_State* L, std::function fx) { + return pusher>{}.push(L, std::move(fx)); + } + }; + + template + struct pusher::value>> { + template + static int push(lua_State* L, F&& f, Args&&... args) { + return pusher>{}.push(L, std::forward(f), std::forward(args)...); + } + }; + + template + struct pusher, meta::neg>, meta::neg>>>::value>> { + template + static int push(lua_State* L, F&& f) { + return pusher>{}.push(L, std::forward(f)); + } + }; + + template + struct pusher> { + static int push(lua_State* L, overload_set&& set) { + typedef function_detail::overloaded_function<0, Functions...> F; + pusher>{}.set_fx(L, std::move(set.functions)); + return 1; + } + + static int push(lua_State* L, const overload_set& set) { + typedef function_detail::overloaded_function<0, Functions...> F; + pusher>{}.set_fx(L, set.functions); + return 1; + } + }; + + template + struct pusher> { + static int push(lua_State* L, protect_t&& pw) { + lua_CFunction cf = call_detail::call_user>; + int closures = stack::push>>(L, std::move(pw.value)); + return stack::push(L, c_closure(cf, closures)); + } + + static int push(lua_State* L, const protect_t& pw) { + lua_CFunction cf = call_detail::call_user>; + int closures = stack::push>>(L, pw.value); + return stack::push(L, c_closure(cf, closures)); + } + }; + + template + struct pusher, std::enable_if_t::value && !std::is_void::value>> { + static int push(lua_State* L, property_wrapper&& pw) { + return stack::push(L, sol::overload(std::move(pw.read), std::move(pw.write))); + } + static int push(lua_State* L, const property_wrapper& pw) { + return stack::push(L, sol::overload(pw.read, pw.write)); + } + }; + + template + struct pusher> { + static int push(lua_State* L, property_wrapper&& pw) { + return stack::push(L, std::move(pw.read)); + } + static int push(lua_State* L, const property_wrapper& pw) { + return stack::push(L, pw.read); + } + }; + + template + struct pusher> { + static int push(lua_State* L, property_wrapper&& pw) { + return stack::push(L, std::move(pw.write)); + } + static int push(lua_State* L, const property_wrapper& pw) { + return stack::push(L, pw.write); + } + }; + + template + struct pusher> { + static int push(lua_State* L, var_wrapper&& vw) { + return stack::push(L, std::move(vw.value)); + } + static int push(lua_State* L, const var_wrapper& vw) { + return stack::push(L, vw.value); + } + }; + + template + struct pusher> { + static int push(lua_State* L, const factory_wrapper& fw) { + typedef function_detail::overloaded_function<0, Functions...> F; + pusher>{}.set_fx(L, fw.functions); + return 1; + } + + static int push(lua_State* L, factory_wrapper&& fw) { + typedef function_detail::overloaded_function<0, Functions...> F; + pusher>{}.set_fx(L, std::move(fw.functions)); + return 1; + } + + static int push(lua_State* L, const factory_wrapper& set, function_detail::call_indicator) { + typedef function_detail::overloaded_function<1, Functions...> F; + pusher>{}.set_fx(L, set.functions); + return 1; + } + + static int push(lua_State* L, factory_wrapper&& set, function_detail::call_indicator) { + typedef function_detail::overloaded_function<1, Functions...> F; + pusher>{}.set_fx(L, std::move(set.functions)); + return 1; + } + }; + + template <> + struct pusher { + static int push(lua_State* L, no_construction) { + lua_CFunction cf = &function_detail::no_construction_error; + return stack::push(L, cf); + } + + static int push(lua_State* L, no_construction c, function_detail::call_indicator) { + return push(L, c); + } + }; + + template + struct pusher>> { + static int push(lua_State* L, detail::tagged>) { + lua_CFunction cf = call_detail::construct; + return stack::push(L, cf); + } + }; + + template + struct pusher>> { + template + static int push(lua_State* L, C&& c) { + lua_CFunction cf = call_detail::call_user>; + int closures = stack::push>>(L, std::forward(c)); + return stack::push(L, c_closure(cf, closures)); + } + }; + + template + struct pusher>> { + static int push(lua_State* L, destructor_wrapper) { + lua_CFunction cf = detail::usertype_alloc_destroy; + return stack::push(L, cf); + } + }; + + template + struct pusher>> { + static int push(lua_State* L, destructor_wrapper c) { + lua_CFunction cf = call_detail::call_user>; + int closures = stack::push>(L, std::move(c)); + return stack::push(L, c_closure(cf, closures)); + } + }; + + } // stack +} // sol + +// end of sol/function_types.hpp + +namespace sol { + template + class basic_function : public base_t { + private: + void luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount) const { + lua_callk(base_t::lua_state(), static_cast(argcount), static_cast(resultcount), 0, nullptr); + } + + template + auto invoke(types, std::index_sequence, std::ptrdiff_t n) const { + luacall(n, lua_size>::value); + return stack::pop>(base_t::lua_state()); + } + + template + Ret invoke(types, std::index_sequence, std::ptrdiff_t n) const { + luacall(n, lua_size::value); + return stack::pop(base_t::lua_state()); + } + + template + void invoke(types, std::index_sequence, std::ptrdiff_t n) const { + luacall(n, 0); + } + + function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) const { + int stacksize = lua_gettop(base_t::lua_state()); + int firstreturn = (std::max)(1, stacksize - static_cast(n)); + luacall(n, LUA_MULTRET); + int poststacksize = lua_gettop(base_t::lua_state()); + int returncount = poststacksize - (firstreturn - 1); + return function_result(base_t::lua_state(), firstreturn, returncount); + } + + public: + basic_function() = default; + template , basic_function>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_function(T&& r) noexcept : base_t(std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_function>::value) { + auto pp = stack::push_pop(*this); + stack::check(base_t::lua_state(), -1, type_panic); + } +#endif // Safety + } + basic_function(const basic_function&) = default; + basic_function& operator=(const basic_function&) = default; + basic_function(basic_function&&) = default; + basic_function& operator=(basic_function&&) = default; + basic_function(const stack_reference& r) : basic_function(r.lua_state(), r.stack_index()) {} + basic_function(stack_reference&& r) : basic_function(r.lua_state(), r.stack_index()) {} + template >>, meta::neg>> = meta::enabler> + basic_function(lua_State* L, T&& r) : basic_function(L, sol::ref_index(r.registry_index())) {} + basic_function(lua_State* L, int index = -1) : base_t(L, index) { +#ifdef SOL_CHECK_ARGUMENTS + stack::check(L, index, type_panic); +#endif // Safety + } + basic_function(lua_State* L, ref_index index) : base_t(L, index) { +#ifdef SOL_CHECK_ARGUMENTS + auto pp = stack::push_pop(*this); + stack::check(L, -1, type_panic); +#endif // Safety + } + + template + function_result operator()(Args&&... args) const { + return call<>(std::forward(args)...); + } + + template + decltype(auto) operator()(types, Args&&... args) const { + return call(std::forward(args)...); + } + + template + decltype(auto) call(Args&&... args) const { + base_t::push(); + int pushcount = stack::multi_push_reference(base_t::lua_state(), std::forward(args)...); + return invoke(types(), std::make_index_sequence(), pushcount); + } + }; + + namespace stack { + template + struct getter> { + typedef meta::bind_traits fx_t; + typedef typename fx_t::args_list args_lists; + typedef meta::tuple_types return_types; + + template + static std::function get_std_func(types, types, lua_State* L, int index) { + sol::function f(L, index); + auto fx = [f, L, index](Args&&... args) -> meta::return_type_t { + return f.call(std::forward(args)...); + }; + return std::move(fx); + } + + template + static std::function get_std_func(types, types, lua_State* L, int index) { + sol::function f(L, index); + auto fx = [f, L, index](FxArgs&&... args) -> void { + f(std::forward(args)...); + }; + return std::move(fx); + } + + template + static std::function get_std_func(types<>, types t, lua_State* L, int index) { + return get_std_func(types(), t, L, index); + } + + static std::function get(lua_State* L, int index, record& tracking) { + tracking.last = 1; + tracking.used += 1; + type t = type_of(L, index); + if (t == type::none || t == type::lua_nil) { + return nullptr; + } + return get_std_func(return_types(), args_lists(), L, index); + } + }; + } // stack +} // sol + +// end of sol/function.hpp + +// beginning of sol/protected_function.hpp + +// beginning of sol/protected_function_result.hpp + +namespace sol { + struct protected_function_result : public proxy_base { + private: + lua_State* L; + int index; + int returncount; + int popcount; + call_status err; + + template + decltype(auto) tagged_get(types>) const { + if (!valid()) { + return sol::optional(nullopt); + } + return stack::get>(L, index); + } + + template + decltype(auto) tagged_get(types) const { +#ifdef SOL_CHECK_ARGUMENTS + if (!valid()) { + type_panic(L, index, type_of(L, index), type::none); + } +#endif // Check Argument Safety + return stack::get(L, index); + } + + optional tagged_get(types>) const { + if (valid()) { + return nullopt; + } + return error(detail::direct_error, stack::get(L, index)); + } + + error tagged_get(types) const { +#ifdef SOL_CHECK_ARGUMENTS + if (valid()) { + type_panic(L, index, type_of(L, index), type::none); + } +#endif // Check Argument Safety + return error(detail::direct_error, stack::get(L, index)); + } + + public: + protected_function_result() = default; + protected_function_result(lua_State* Ls, int idx = -1, int retnum = 0, int popped = 0, call_status pferr = call_status::ok) noexcept : L(Ls), index(idx), returncount(retnum), popcount(popped), err(pferr) { + + } + protected_function_result(const protected_function_result&) = default; + protected_function_result& operator=(const protected_function_result&) = default; + protected_function_result(protected_function_result&& o) noexcept : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) { + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but we will be thorough + o.L = nullptr; + o.index = 0; + o.returncount = 0; + o.popcount = 0; + o.err = call_status::runtime; + } + protected_function_result& operator=(protected_function_result&& o) noexcept { + L = o.L; + index = o.index; + returncount = o.returncount; + popcount = o.popcount; + err = o.err; + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but we will be thorough + o.L = nullptr; + o.index = 0; + o.returncount = 0; + o.popcount = 0; + o.err = call_status::runtime; + return *this; + } + + call_status status() const noexcept { + return err; + } + + bool valid() const noexcept { + return status() == call_status::ok || status() == call_status::yielded; + } + + template + decltype(auto) get() const { + return tagged_get(types>()); + } + + lua_State* lua_state() const noexcept { return L; }; + int stack_index() const noexcept { return index; }; + + ~protected_function_result() { + stack::remove(L, index, popcount); + } + }; +} // sol + +// end of sol/protected_function_result.hpp + +#include + +namespace sol { + namespace detail { + inline reference& handler_storage() { + static sol::reference h; + return h; + } + + struct handler { + const reference& target; + int stackindex; + handler(const reference& target) : target(target), stackindex(0) { + if (target.valid()) { + stackindex = lua_gettop(target.lua_state()) + 1; + target.push(); + } + } + bool valid() const { return stackindex != 0; } + ~handler() { + if (valid()) { + lua_remove(target.lua_state(), stackindex); + } + } + }; + } + + template + class basic_protected_function : public base_t { + public: + static reference& get_default_handler() { + return detail::handler_storage(); + } + + static void set_default_handler(const reference& ref) { + detail::handler_storage() = ref; + } + + static void set_default_handler(reference&& ref) { + detail::handler_storage() = std::move(ref); + } + + private: + call_status luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount, detail::handler& h) const { + return static_cast(lua_pcallk(base_t::lua_state(), static_cast(argcount), static_cast(resultcount), h.stackindex, 0, nullptr)); + } + + template + auto invoke(types, std::index_sequence, std::ptrdiff_t n, detail::handler& h) const { + luacall(n, sizeof...(Ret), h); + return stack::pop>(base_t::lua_state()); + } + + template + Ret invoke(types, std::index_sequence, std::ptrdiff_t n, detail::handler& h) const { + luacall(n, 1, h); + return stack::pop(base_t::lua_state()); + } + + template + void invoke(types, std::index_sequence, std::ptrdiff_t n, detail::handler& h) const { + luacall(n, 0, h); + } + + protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n, detail::handler& h) const { + int stacksize = lua_gettop(base_t::lua_state()); + int poststacksize = stacksize; + int firstreturn = 1; + int returncount = 0; + call_status code = call_status::ok; +#ifndef SOL_NO_EXCEPTIONS + auto onexcept = [&](const char* error) { + h.stackindex = 0; + if (h.target.valid()) { + h.target.push(); + stack::push(base_t::lua_state(), error); + lua_call(base_t::lua_state(), 1, 1); + } + else { + stack::push(base_t::lua_state(), error); + } + }; + try { +#endif // No Exceptions + firstreturn = (std::max)(1, static_cast(stacksize - n - static_cast(h.valid()))); + code = luacall(n, LUA_MULTRET, h); + poststacksize = lua_gettop(base_t::lua_state()) - static_cast(h.valid()); + returncount = poststacksize - (firstreturn - 1); +#ifndef SOL_NO_EXCEPTIONS + } + // Handle C++ errors thrown from C++ functions bound inside of lua + catch (const char* error) { + onexcept(error); + firstreturn = lua_gettop(base_t::lua_state()); + return protected_function_result(base_t::lua_state(), firstreturn, 0, 1, call_status::runtime); + } + catch (const std::exception& error) { + onexcept(error.what()); + firstreturn = lua_gettop(base_t::lua_state()); + return protected_function_result(base_t::lua_state(), firstreturn, 0, 1, call_status::runtime); + } + catch (...) { + onexcept("caught (...) unknown error during protected_function call"); + firstreturn = lua_gettop(base_t::lua_state()); + return protected_function_result(base_t::lua_state(), firstreturn, 0, 1, call_status::runtime); + } +#endif // No Exceptions + return protected_function_result(base_t::lua_state(), firstreturn, returncount, returncount, code); + } + + public: + reference error_handler; + + basic_protected_function() = default; + template , basic_protected_function>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_protected_function(T&& r) noexcept : base_t(std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_function>::value) { + auto pp = stack::push_pop(*this); + stack::check(base_t::lua_state(), -1, type_panic); + } +#endif // Safety + } + basic_protected_function(const basic_protected_function&) = default; + basic_protected_function& operator=(const basic_protected_function&) = default; + basic_protected_function(basic_protected_function&&) = default; + basic_protected_function& operator=(basic_protected_function&&) = default; + basic_protected_function(const basic_function& b, reference eh = get_default_handler()) : base_t(b), error_handler(std::move(eh)) {} + basic_protected_function(basic_function&& b, reference eh = get_default_handler()) : base_t(std::move(b)), error_handler(std::move(eh)) {} + basic_protected_function(const stack_reference& r, reference eh = get_default_handler()) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {} + basic_protected_function(stack_reference&& r, reference eh = get_default_handler()) : basic_protected_function(r.lua_state(), r.stack_index(), std::move(eh)) {} + template + basic_protected_function(proxy_base&& p, reference eh = get_default_handler()) : basic_protected_function(p.operator basic_function(), std::move(eh)) {} + template + basic_protected_function(const proxy_base& p, reference eh = get_default_handler()) : basic_protected_function(p.operator basic_function(), std::move(eh)) {} + template >>, meta::neg>> = meta::enabler> + basic_protected_function(lua_State* L, T&& r, reference eh) : basic_protected_function(L, sol::ref_index(r.registry_index()), std::move(eh)) {} + basic_protected_function(lua_State* L, int index = -1, reference eh = get_default_handler()) : base_t(L, index), error_handler(std::move(eh)) { +#ifdef SOL_CHECK_ARGUMENTS + stack::check(L, index, type_panic); +#endif // Safety + } + basic_protected_function(lua_State* L, ref_index index, reference eh = get_default_handler()) : base_t(L, index), error_handler(std::move(eh)) { +#ifdef SOL_CHECK_ARGUMENTS + auto pp = stack::push_pop(*this); + stack::check(L, -1, type_panic); +#endif // Safety + } + + template + protected_function_result operator()(Args&&... args) const { + return call<>(std::forward(args)...); + } + + template + decltype(auto) operator()(types, Args&&... args) const { + return call(std::forward(args)...); + } + + template + decltype(auto) call(Args&&... args) const { + detail::handler h(error_handler); + base_t::push(); + int pushcount = stack::multi_push_reference(base_t::lua_state(), std::forward(args)...); + return invoke(types(), std::make_index_sequence(), pushcount, h); + } + }; +} // sol + +// end of sol/protected_function.hpp + +namespace sol { + struct stack_proxy : public proxy_base { + private: + lua_State* L; + int index; + + public: + stack_proxy() : L(nullptr), index(0) {} + stack_proxy(lua_State* L, int index) : L(L), index(index) {} + + template + decltype(auto) get() const { + return stack::get(L, stack_index()); + } + + int push() const { + return push(L); + } + + int push(lua_State* Ls) const { + lua_pushvalue(Ls, index); + return 1; + } + + lua_State* lua_state() const { return L; } + int stack_index() const { return index; } + + template + decltype(auto) call(Args&&... args) { + return get().template call(std::forward(args)...); + } + + template + decltype(auto) operator()(Args&&... args) { + return call<>(std::forward(args)...); + } + }; + + namespace stack { + template <> + struct getter { + static stack_proxy get(lua_State* L, int index = -1) { + return stack_proxy(L, index); + } + }; + + template <> + struct pusher { + static int push(lua_State*, const stack_proxy& ref) { + return ref.push(); + } + }; + } // stack + + namespace detail { + template <> + struct is_speshul : std::true_type {}; + template <> + struct is_speshul : std::true_type {}; + + template + stack_proxy get(types, index_value<0>, index_value, const T& fr) { + return stack_proxy(fr.lua_state(), static_cast(fr.stack_index() + I)); + } + + template 0)>> = meta::enabler> + stack_proxy get(types, index_value, index_value, const T& fr) { + return get(types(), index_value(), index_value::value>(), fr); + } + } + + template <> + struct tie_size : std::integral_constant {}; + + template + stack_proxy get(const function_result& fr) { + return stack_proxy(fr.lua_state(), static_cast(fr.stack_index() + I)); + } + + template + stack_proxy get(types t, const function_result& fr) { + return detail::get(t, index_value(), index_value<0>(), fr); + } + + template <> + struct tie_size : std::integral_constant {}; + + template + stack_proxy get(const protected_function_result& fr) { + return stack_proxy(fr.lua_state(), static_cast(fr.stack_index() + I)); + } + + template + stack_proxy get(types t, const protected_function_result& fr) { + return detail::get(t, index_value(), index_value<0>(), fr); + } +} // sol + +// end of sol/stack_proxy.hpp + +#include +#include + +namespace sol { + template + struct va_iterator : std::iterator, std::ptrdiff_t, std::conditional_t, std::conditional_t> { + typedef std::iterator, std::ptrdiff_t, std::conditional_t, std::conditional_t> base_t; + typedef typename base_t::reference reference; + typedef typename base_t::pointer pointer; + typedef typename base_t::value_type value_type; + typedef typename base_t::difference_type difference_type; + typedef typename base_t::iterator_category iterator_category; + lua_State* L; + int index; + int stacktop; + stack_proxy sp; + + va_iterator() : L(nullptr), index((std::numeric_limits::max)()), stacktop((std::numeric_limits::max)()) {} + va_iterator(lua_State* luastate, int idx, int topidx) : L(luastate), index(idx), stacktop(topidx), sp(luastate, idx) {} + + reference operator*() { + return stack_proxy(L, index); + } + + pointer operator->() { + sp = stack_proxy(L, index); + return &sp; + } + + va_iterator& operator++ () { + ++index; + return *this; + } + + va_iterator operator++ (int) { + auto r = *this; + this->operator ++(); + return r; + } + + va_iterator& operator-- () { + --index; + return *this; + } + + va_iterator operator-- (int) { + auto r = *this; + this->operator --(); + return r; + } + + va_iterator& operator+= (difference_type idx) { + index += static_cast(idx); + return *this; + } + + va_iterator& operator-= (difference_type idx) { + index -= static_cast(idx); + return *this; + } + + difference_type operator- (const va_iterator& r) const { + return index - r.index; + } + + va_iterator operator+ (difference_type idx) const { + va_iterator r = *this; + r += idx; + return r; + } + + reference operator[](difference_type idx) { + return stack_proxy(L, index + static_cast(idx)); + } + + bool operator==(const va_iterator& r) const { + if (stacktop == (std::numeric_limits::max)()) { + return r.index == r.stacktop; + } + else if (r.stacktop == (std::numeric_limits::max)()) { + return index == stacktop; + } + return index == r.index; + } + + bool operator != (const va_iterator& r) const { + return !(this->operator==(r)); + } + + bool operator < (const va_iterator& r) const { + return index < r.index; + } + + bool operator > (const va_iterator& r) const { + return index > r.index; + } + + bool operator <= (const va_iterator& r) const { + return index <= r.index; + } + + bool operator >= (const va_iterator& r) const { + return index >= r.index; + } + }; + + template + inline va_iterator operator+(typename va_iterator::difference_type n, const va_iterator& r) { + return r + n; + } + + struct variadic_args { + private: + lua_State* L; + int index; + int stacktop; + + public: + typedef stack_proxy reference_type; + typedef stack_proxy value_type; + typedef stack_proxy* pointer; + typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + typedef va_iterator iterator; + typedef va_iterator const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + variadic_args() = default; + variadic_args(lua_State* luastate, int stackindex = -1) : L(luastate), index(lua_absindex(luastate, stackindex)), stacktop(lua_gettop(luastate)) {} + variadic_args(const variadic_args&) = default; + variadic_args& operator=(const variadic_args&) = default; + variadic_args(variadic_args&& o) : L(o.L), index(o.index), stacktop(o.stacktop) { + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but will be thorough + o.L = nullptr; + o.index = 0; + o.stacktop = 0; + } + variadic_args& operator=(variadic_args&& o) { + L = o.L; + index = o.index; + stacktop = o.stacktop; + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but will be thorough + o.L = nullptr; + o.index = 0; + o.stacktop = 0; + return *this; + } + + iterator begin() { return iterator(L, index, stacktop + 1); } + iterator end() { return iterator(L, stacktop + 1, stacktop + 1); } + const_iterator begin() const { return const_iterator(L, index, stacktop + 1); } + const_iterator end() const { return const_iterator(L, stacktop + 1, stacktop + 1); } + const_iterator cbegin() const { return begin(); } + const_iterator cend() const { return end(); } + + reverse_iterator rbegin() { return std::reverse_iterator(begin()); } + reverse_iterator rend() { return std::reverse_iterator(end()); } + const_reverse_iterator rbegin() const { return std::reverse_iterator(begin()); } + const_reverse_iterator rend() const { return std::reverse_iterator(end()); } + const_reverse_iterator crbegin() const { return std::reverse_iterator(cbegin()); } + const_reverse_iterator crend() const { return std::reverse_iterator(cend()); } + + int push() const { + return push(L); + } + + int push(lua_State* target) const { + int pushcount = 0; + for (int i = index; i <= stacktop; ++i) { + lua_pushvalue(L, i); + pushcount += 1; + } + if (target != L) { + lua_xmove(L, target, pushcount); + } + return pushcount; + } + + template + decltype(auto) get(difference_type start = 0) const { + return stack::get(L, index + static_cast(start)); + } + + stack_proxy operator[](difference_type start) const { + return stack_proxy(L, index + static_cast(start)); + } + + lua_State* lua_state() const { return L; }; + int stack_index() const { return index; }; + int leftover_count() const { return stacktop - (index - 1); } + int top() const { return stacktop; } + }; + + namespace stack { + template <> + struct getter { + static variadic_args get(lua_State* L, int index, record& tracking) { + tracking.last = 0; + return variadic_args(L, index); + } + }; + + template <> + struct pusher { + static int push(lua_State* L, const variadic_args& ref) { + return ref.push(L); + } + }; + } // stack +} // sol + +// end of sol/variadic_args.hpp + +namespace sol { + + template ::value, typename T> + R make_reference(lua_State* L, T&& value) { + int backpedal = stack::push(L, std::forward(value)); + R r = stack::get(L, -backpedal); + if (should_pop) { + lua_pop(L, backpedal); + } + return r; + } + + template ::value, typename... Args> + R make_reference(lua_State* L, Args&&... args) { + int backpedal = stack::push(L, std::forward(args)...); + R r = stack::get(L, -backpedal); + if (should_pop) { + lua_pop(L, backpedal); + } + return r; + } + + template + class basic_object : public basic_object_base { + private: + typedef basic_object_base base_t; + + template + basic_object(std::integral_constant, lua_State* L, int index = -1) noexcept : base_t(L, index) { + if (invert_and_pop) { + lua_pop(L, -index); + } + } + + public: + basic_object() noexcept = default; + template , basic_object>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_object(T&& r) : base_t(std::forward(r)) {} + basic_object(lua_nil_t r) : base_t(r) {} + basic_object(const basic_object&) = default; + basic_object(basic_object&&) = default; + basic_object(const stack_reference& r) noexcept : basic_object(r.lua_state(), r.stack_index()) {} + basic_object(stack_reference&& r) noexcept : basic_object(r.lua_state(), r.stack_index()) {} + template + basic_object(const proxy_base& r) noexcept : basic_object(r.operator basic_object()) {} + template + basic_object(proxy_base&& r) noexcept : basic_object(r.operator basic_object()) {} + basic_object(lua_State* L, int index = -1) noexcept : base_t(L, index) {} + basic_object(lua_State* L, ref_index index) noexcept : base_t(L, index) {} + template + basic_object(lua_State* L, in_place_type_t, Args&&... args) noexcept : basic_object(std::integral_constant::value>(), L, -stack::push(L, std::forward(args)...)) {} + template + basic_object(lua_State* L, in_place_t, T&& arg, Args&&... args) noexcept : basic_object(L, in_place, std::forward(arg), std::forward(args)...) {} + basic_object& operator=(const basic_object&) = default; + basic_object& operator=(basic_object&&) = default; + basic_object& operator=(const base_type& b) { base_t::operator=(b); return *this; } + basic_object& operator=(base_type&& b) { base_t::operator=(std::move(b)); return *this; } + template + basic_object& operator=(const proxy_base& r) { this->operator=(r.operator basic_object()); return *this; } + template + basic_object& operator=(proxy_base&& r) { this->operator=(r.operator basic_object()); return *this; } + }; + + template + object make_object(lua_State* L, T&& value) { + return make_reference(L, std::forward(value)); + } + + template + object make_object(lua_State* L, Args&&... args) { + return make_reference(L, std::forward(args)...); + } +} // sol + +// end of sol/object.hpp + +namespace sol { + template + struct proxy : public proxy_base> { + private: + typedef meta::condition, Key, std::tuple>, Key&, meta::unqualified_t>>> key_type; + + template + decltype(auto) tuple_get(std::index_sequence) const { + return tbl.template traverse_get(std::get(key)...); + } + + template + void tuple_set(std::index_sequence, T&& value) { + tbl.traverse_set(std::get(key)..., std::forward(value)); + } + + public: + Table tbl; + key_type key; + + template + proxy(Table table, T&& k) : tbl(table), key(std::forward(k)) {} + + template + proxy& set(T&& item) { + tuple_set(std::make_index_sequence>::value>(), std::forward(item)); + return *this; + } + + template + proxy& set_function(Args&&... args) { + tbl.set_function(key, std::forward(args)...); + return *this; + } + + template>>, meta::is_callable>> = meta::enabler> + proxy& operator=(U&& other) { + return set_function(std::forward(other)); + } + + template>>, meta::is_callable>> = meta::enabler> + proxy& operator=(U&& other) { + return set(std::forward(other)); + } + + template + decltype(auto) get() const { + return tuple_get(std::make_index_sequence>::value>()); + } + + template + decltype(auto) get_or(T&& otherwise) const { + typedef decltype(get()) U; + sol::optional option = get>(); + if (option) { + return static_cast(option.value()); + } + return static_cast(std::forward(otherwise)); + } + + template + decltype(auto) get_or(D&& otherwise) const { + sol::optional option = get>(); + if (option) { + return static_cast(option.value()); + } + return static_cast(std::forward(otherwise)); + } + + template + decltype(auto) operator[](K&& k) const { + auto keys = meta::tuplefy(key, std::forward(k)); + return proxy(tbl, std::move(keys)); + } + + template + decltype(auto) call(Args&&... args) { + return get().template call(std::forward(args)...); + } + + template + decltype(auto) operator()(Args&&... args) { + return call<>(std::forward(args)...); + } + + bool valid() const { + auto pp = stack::push_pop(tbl); + auto p = stack::probe_get_field, global_table>::value>(tbl.lua_state(), key, lua_gettop(tbl.lua_state())); + lua_pop(tbl.lua_state(), p.levels); + return p; + } + }; + + template + inline bool operator==(T&& left, const proxy& right) { + typedef decltype(stack::get(nullptr, 0)) U; + return right.template get>() == left; + } + + template + inline bool operator==(const proxy& right, T&& left) { + typedef decltype(stack::get(nullptr, 0)) U; + return right.template get>() == left; + } + + template + inline bool operator!=(T&& left, const proxy& right) { + typedef decltype(stack::get(nullptr, 0)) U; + return right.template get>() == left; + } + + template + inline bool operator!=(const proxy& right, T&& left) { + typedef decltype(stack::get(nullptr, 0)) U; + return right.template get>() == left; + } + + template + inline bool operator==(lua_nil_t, const proxy& right) { + return !right.valid(); + } + + template + inline bool operator==(const proxy& right, lua_nil_t) { + return !right.valid(); + } + + template + inline bool operator!=(lua_nil_t, const proxy& right) { + return right.valid(); + } + + template + inline bool operator!=(const proxy& right, lua_nil_t) { + return right.valid(); + } + + namespace stack { + template + struct pusher> { + static int push(lua_State* L, const proxy& p) { + sol::reference r = p; + return r.push(L); + } + }; + } // stack +} // sol + +// end of sol/proxy.hpp + +// beginning of sol/usertype.hpp + +// beginning of sol/usertype_metatable.hpp + +// beginning of sol/deprecate.hpp + +#ifndef SOL_DEPRECATED + #ifdef _MSC_VER + #define SOL_DEPRECATED __declspec(deprecated) + #elif __GNUC__ + #define SOL_DEPRECATED __attribute__((deprecated)) + #else + #define SOL_DEPRECATED [[deprecated]] + #endif // compilers +#endif // SOL_DEPRECATED + +namespace sol { + namespace detail { + template + struct SOL_DEPRECATED deprecate_type { + using type = T; + }; + } // detail +} // sol + +// end of sol/deprecate.hpp + +#include +#include + +namespace sol { + namespace usertype_detail { + typedef void(*base_walk)(lua_State*, bool&, int&, string_detail::string_shim&); + typedef int(*member_search)(lua_State*, void*, int); + + struct call_information { + member_search index; + member_search new_index; + int runtime_target; + + call_information(member_search index, member_search newindex) : call_information(index, newindex, -1) {} + call_information(member_search index, member_search newindex, int runtimetarget) : index(index), new_index(newindex), runtime_target(runtimetarget) {} + }; + + typedef std::unordered_map mapping_t; + + struct variable_wrapper { + virtual int index(lua_State* L) = 0; + virtual int new_index(lua_State* L) = 0; + virtual ~variable_wrapper() {}; + }; + + template + struct callable_binding : variable_wrapper { + F fx; + + template + callable_binding(Arg&& arg) : fx(std::forward(arg)) {} + + virtual int index(lua_State* L) override { + return call_detail::call_wrapped(L, fx); + } + + virtual int new_index(lua_State* L) override { + return call_detail::call_wrapped(L, fx); + } + }; + + typedef std::unordered_map> variable_map; + typedef std::unordered_map function_map; + + struct simple_map { + const char* metakey; + variable_map variables; + function_map functions; + base_walk indexbaseclasspropogation; + base_walk newindexbaseclasspropogation; + + simple_map(const char* mkey, base_walk index, base_walk newindex, variable_map&& vars, function_map&& funcs) : metakey(mkey), variables(std::move(vars)), functions(std::move(funcs)), indexbaseclasspropogation(index), newindexbaseclasspropogation(newindex) {} + }; + } + + struct usertype_metatable_core { + usertype_detail::mapping_t mapping; + lua_CFunction indexfunc; + lua_CFunction newindexfunc; + std::vector runtime; + bool mustindex; + + usertype_metatable_core(lua_CFunction ifx, lua_CFunction nifx) : + mapping(), indexfunc(ifx), + newindexfunc(nifx), runtime(), mustindex(false) + { + + } + + usertype_metatable_core(const usertype_metatable_core&) = default; + usertype_metatable_core(usertype_metatable_core&&) = default; + usertype_metatable_core& operator=(const usertype_metatable_core&) = default; + usertype_metatable_core& operator=(usertype_metatable_core&&) = default; + + }; + + namespace usertype_detail { + const lua_Integer toplevel_magic = static_cast(0x00020001); + + struct add_destructor_tag {}; + struct check_destructor_tag {}; + struct verified_tag {} const verified{}; + + template + struct is_non_factory_constructor : std::false_type {}; + + template + struct is_non_factory_constructor> : std::true_type {}; + + template + struct is_non_factory_constructor> : std::true_type {}; + + template <> + struct is_non_factory_constructor : std::true_type {}; + + template + struct is_constructor : is_non_factory_constructor {}; + + template + struct is_constructor> : std::true_type {}; + + template + using has_constructor = meta::any>...>; + + template + struct is_destructor : std::false_type {}; + + template + struct is_destructor> : std::true_type {}; + + template + using has_destructor = meta::any>...>; + + struct no_comp { + template + bool operator()(A&&, B&&) const { + return false; + } + }; + + inline bool is_indexer(string_detail::string_shim s) { + return s == to_string(meta_function::index) || s == to_string(meta_function::new_index); + } + + inline bool is_indexer(meta_function mf) { + return mf == meta_function::index || mf == meta_function::new_index; + } + + inline bool is_indexer(call_construction) { + return false; + } + + inline bool is_indexer(base_classes_tag) { + return false; + } + + inline auto make_shim(string_detail::string_shim s) { + return s; + } + + inline auto make_shim(call_construction) { + return string_detail::string_shim(to_string(meta_function::call_function)); + } + + inline auto make_shim(meta_function mf) { + return string_detail::string_shim(to_string(mf)); + } + + inline auto make_shim(base_classes_tag) { + return string_detail::string_shim(detail::base_class_cast_key()); + } + + template + inline std::string make_string(Arg&& arg) { + string_detail::string_shim s = make_shim(arg); + return std::string(s.c_str(), s.size()); + } + + template + inline luaL_Reg make_reg(N&& n, lua_CFunction f) { + luaL_Reg l{ make_shim(std::forward(n)).c_str(), f }; + return l; + } + + struct registrar { + registrar() = default; + registrar(const registrar&) = default; + registrar(registrar&&) = default; + registrar& operator=(const registrar&) = default; + registrar& operator=(registrar&&) = default; + virtual int push_um(lua_State* L) = 0; + virtual ~registrar() {} + }; + + inline int runtime_object_call(lua_State* L, void*, int runtimetarget) { + usertype_metatable_core& umc = stack::get>(L, upvalue_index(2)); + std::vector& runtime = umc.runtime; + object& runtimeobj = runtime[runtimetarget]; + return stack::push(L, runtimeobj); + } + + template + inline int indexing_fail(lua_State* L) { + if (is_index) { +#if 0//def SOL_SAFE_USERTYPE + auto maybeaccessor = stack::get>(L, is_index ? -1 : -2); + string_detail::string_shim accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)")); + return luaL_error(L, "sol: attempt to index (get) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str()); +#else + int isnum = 0; + lua_Integer magic = lua_tointegerx(L, upvalue_index(4), &isnum); + if (isnum != 0 && magic == toplevel_magic) { + if (lua_getmetatable(L, 1) == 1) { + int metatarget = lua_gettop(L); + stack::get_field(L, stack_reference(L, raw_index(2)), metatarget); + return 1; + } + } + // With runtime extensibility, we can't hard-error things. They have to return nil, like regular table types, unfortunately... + return stack::push(L, lua_nil); +#endif + } + else { + auto maybeaccessor = stack::get>(L, is_index ? -1 : -2); + string_detail::string_shim accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)")); + return luaL_error(L, "sol: attempt to index (set) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str()); + } + } + + int runtime_new_index(lua_State* L, void*, int runtimetarget); + + template + inline int metatable_newindex(lua_State* L) { + int isnum = 0; + lua_Integer magic = lua_tointegerx(L, upvalue_index(4), &isnum); + if (isnum != 0 && magic == toplevel_magic) { + auto non_indexable = [&L]() { + if (is_simple) { + simple_map& sm = stack::get>(L, upvalue_index(1)); + function_map& functions = sm.functions; + sol::optional maybeaccessor = stack::get>(L, 2); + if (!maybeaccessor) { + return; + } + std::string& accessor = maybeaccessor.value(); + auto preexistingit = functions.find(accessor); + if (preexistingit == functions.cend()) { + functions.emplace_hint(preexistingit, std::move(accessor), sol::object(L, 3)); + } + else { + preexistingit->second = sol::object(L, 3); + } + return; + } + usertype_metatable_core& umc = stack::get>(L, upvalue_index(2)); + bool mustindex = umc.mustindex; + if (!mustindex) + return; + sol::optional maybeaccessor = stack::get>(L, 2); + if (!maybeaccessor) { + return; + } + std::string& accessor = maybeaccessor.value(); + mapping_t& mapping = umc.mapping; + std::vector& runtime = umc.runtime; + int target = static_cast(runtime.size()); + auto preexistingit = mapping.find(accessor); + if (preexistingit == mapping.cend()) { + runtime.emplace_back(L, 3); + mapping.emplace_hint(mapping.cend(), accessor, call_information(&runtime_object_call, &runtime_new_index, target)); + } + else { + target = preexistingit->second.runtime_target; + runtime[target] = sol::object(L, 3); + preexistingit->second = call_information(&runtime_object_call, &runtime_new_index, target); + } + }; + non_indexable(); + for (std::size_t i = 0; i < 4; lua_settop(L, 3), ++i) { + const char* metakey = nullptr; + switch (i) { + case 0: + metakey = &usertype_traits::metatable()[0]; + luaL_getmetatable(L, metakey); + break; + case 1: + metakey = &usertype_traits>::metatable()[0]; + luaL_getmetatable(L, metakey); + break; + case 2: + metakey = &usertype_traits::metatable()[0]; + luaL_getmetatable(L, metakey); + break; + case 3: + default: + metakey = &usertype_traits::user_metatable()[0]; + { + luaL_getmetatable(L, metakey); + lua_getmetatable(L, -1); + } + break; + } + int tableindex = lua_gettop(L); + if (type_of(L, tableindex) == type::lua_nil) { + continue; + } + stack::set_field(L, stack_reference(L, raw_index(2)), stack_reference(L, raw_index(3)), tableindex); + } + lua_settop(L, 0); + return 0; + } + return indexing_fail(L); + } + + inline int runtime_new_index(lua_State* L, void*, int runtimetarget) { + usertype_metatable_core& umc = stack::get>(L, upvalue_index(2)); + std::vector& runtime = umc.runtime; + object& runtimeobj = runtime[runtimetarget]; + runtimeobj = object(L, 3); + return 0; + } + + template + static void walk_single_base(lua_State* L, bool& found, int& ret, string_detail::string_shim&) { + if (found) + return; + const char* metakey = &usertype_traits::metatable()[0]; + const char* gcmetakey = &usertype_traits::gc_table()[0]; + const char* basewalkkey = is_index ? detail::base_class_index_propogation_key() : detail::base_class_new_index_propogation_key(); + + luaL_getmetatable(L, metakey); + if (type_of(L, -1) == type::lua_nil) { + lua_pop(L, 1); + return; + } + + stack::get_field(L, basewalkkey); + if (type_of(L, -1) == type::lua_nil) { + lua_pop(L, 2); + return; + } + lua_CFunction basewalkfunc = stack::pop(L); + lua_pop(L, 1); + + stack::get_field(L, gcmetakey); + int value = basewalkfunc(L); + if (value > -1) { + found = true; + ret = value; + } + } + + template + static void walk_all_bases(lua_State* L, bool& found, int& ret, string_detail::string_shim& accessor) { + (void)L; + (void)found; + (void)ret; + (void)accessor; + (void)detail::swallow{ 0, (walk_single_base(L, found, ret, accessor), 0)... }; + } + + template + inline int operator_wrap(lua_State* L) { + auto maybel = stack::check_get(L, 1); + if (maybel) { + auto mayber = stack::check_get(L, 2); + if (mayber) { + auto& l = *maybel; + auto& r = *mayber; + if (std::is_same::value) { + return stack::push(L, detail::ptr(l) == detail::ptr(r)); + } + else { + Op op; + return stack::push(L, (detail::ptr(l) == detail::ptr(r)) || op(detail::deref(l), detail::deref(r))); + } + } + } + return stack::push(L, false); + } + + template = meta::enabler> + inline void make_reg_op(Regs& l, int& index, const char* name) { + l[index] = { name, &operator_wrap }; + ++index; + } + + template = meta::enabler> + inline void make_reg_op(Regs&, int&, const char*) { + // Do nothing if there's no support + } + } // usertype_detail + + template + struct clean_type { + typedef std::conditional_t>::value, T&, std::decay_t> type; + }; + + template + using clean_type_t = typename clean_type::type; + + template + struct usertype_metatable : usertype_detail::registrar {}; + + template + struct usertype_metatable, Tn...> : usertype_metatable_core, usertype_detail::registrar { + typedef std::make_index_sequence indices; + typedef std::index_sequence half_indices; + typedef std::array regs_t; + typedef std::tuple RawTuple; + typedef std::tuple ...> Tuple; + template + struct check_binding : is_variable_binding> {}; + Tuple functions; + lua_CFunction destructfunc; + lua_CFunction callconstructfunc; + lua_CFunction indexbase; + lua_CFunction newindexbase; + usertype_detail::base_walk indexbaseclasspropogation; + usertype_detail::base_walk newindexbaseclasspropogation; + void* baseclasscheck; + void* baseclasscast; + bool secondarymeta; + bool hasequals; + bool hasless; + bool haslessequals; + + template >> = meta::enabler> + lua_CFunction make_func() const { + return std::get(functions); + } + + template >> = meta::enabler> + lua_CFunction make_func() const { + const auto& name = std::get(functions); + return (usertype_detail::make_shim(name) == "__newindex") ? &call : &call; + } + + static bool contains_variable() { + typedef meta::any...> has_variables; + return has_variables::value; + } + + bool contains_index() const { + bool idx = false; + (void)detail::swallow{ 0, ((idx |= usertype_detail::is_indexer(std::get(functions))), 0) ... }; + return idx; + } + + int finish_regs(regs_t& l, int& index) { + if (!hasless) { + const char* name = to_string(meta_function::less_than).c_str(); + usertype_detail::make_reg_op, meta::supports_op_less>(l, index, name); + } + if (!haslessequals) { + const char* name = to_string(meta_function::less_than_or_equal_to).c_str(); + usertype_detail::make_reg_op, meta::supports_op_less_equal>(l, index, name); + } + if (!hasequals) { + const char* name = to_string(meta_function::equal_to).c_str(); + usertype_detail::make_reg_op::value, std::equal_to<>, usertype_detail::no_comp>, std::true_type>(l, index, name); + } + if (destructfunc != nullptr) { + l[index] = { to_string(meta_function::garbage_collect).c_str(), destructfunc }; + ++index; + } + return index; + } + + template + void make_regs(regs_t&, int&, call_construction, F&&) { + callconstructfunc = call; + secondarymeta = true; + } + + template + void make_regs(regs_t&, int&, base_classes_tag, bases) { + static_assert(!meta::any_same::value, "base classes cannot list the original class as part of the bases"); + if (sizeof...(Bases) < 1) { + return; + } + mustindex = true; + (void)detail::swallow{ 0, ((detail::has_derived::value = true), 0)... }; + + static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report."); + static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: file a bug report."); + baseclasscheck = (void*)&detail::inheritance::type_check; + baseclasscast = (void*)&detail::inheritance::type_cast; + indexbaseclasspropogation = usertype_detail::walk_all_bases; + newindexbaseclasspropogation = usertype_detail::walk_all_bases; + } + + template , base_classes_tag, call_construction>::value>> + void make_regs(regs_t& l, int& index, N&& n, F&&) { + if (is_variable_binding>::value) { + return; + } + luaL_Reg reg = usertype_detail::make_reg(std::forward(n), make_func()); + // Returnable scope + // That would be a neat keyword for C++ + // returnable { ... }; + if (reg.name == to_string(meta_function::equal_to)) { + hasequals = true; + } + if (reg.name == to_string(meta_function::less_than)) { + hasless = true; + } + if (reg.name == to_string(meta_function::less_than_or_equal_to)) { + haslessequals = true; + } + if (reg.name == to_string(meta_function::garbage_collect)) { + destructfunc = reg.func; + return; + } + else if (reg.name == to_string(meta_function::index)) { + indexfunc = reg.func; + mustindex = true; + return; + } + else if (reg.name == to_string(meta_function::new_index)) { + newindexfunc = reg.func; + mustindex = true; + return; + } + l[index] = reg; + ++index; + } + + template > + usertype_metatable(Args&&... args) : usertype_metatable_core(&usertype_detail::indexing_fail, &usertype_detail::metatable_newindex), usertype_detail::registrar(), + functions(std::forward(args)...), + destructfunc(nullptr), callconstructfunc(nullptr), + indexbase(&core_indexing_call), newindexbase(&core_indexing_call), + indexbaseclasspropogation(usertype_detail::walk_all_bases), newindexbaseclasspropogation(usertype_detail::walk_all_bases), + baseclasscheck(nullptr), baseclasscast(nullptr), + secondarymeta(contains_variable()), + hasequals(false), hasless(false), haslessequals(false) { + std::initializer_list ilist{ { + std::pair( usertype_detail::make_string(std::get(functions)), + usertype_detail::call_information(&usertype_metatable::real_find_call, + &usertype_metatable::real_find_call) + ) + }... }; + this->mapping.insert(ilist); + for (const auto& n : meta_function_names()) { + this->mapping.erase(n); + } + this->mustindex = contains_variable() || contains_index(); + } + + usertype_metatable(const usertype_metatable&) = default; + usertype_metatable(usertype_metatable&&) = default; + usertype_metatable& operator=(const usertype_metatable&) = default; + usertype_metatable& operator=(usertype_metatable&&) = default; + + template + static int real_find_call(lua_State* L, void* um, int) { + auto& f = *static_cast(um); + if (is_variable_binding(f.functions))>::value) { + return real_call_with(L, f); + } + int upvalues = stack::push(L, light(f)); + auto cfunc = &call; + return stack::push(L, c_closure(cfunc, upvalues)); + } + + template + static int real_meta_call(lua_State* L, void* um, int) { + auto& f = *static_cast(um); + return is_index ? f.indexfunc(L) : f.newindexfunc(L); + } + + template + static int core_indexing_call(lua_State* L) { + usertype_metatable& f = toplevel ? stack::get>(L, upvalue_index(1)) : stack::pop>(L); + static const int keyidx = -2 + static_cast(is_index); + if (toplevel && stack::get(L, keyidx) != type::string) { + return is_index ? f.indexfunc(L) : f.newindexfunc(L); + } + std::string name = stack::get(L, keyidx); + auto memberit = f.mapping.find(name); + if (memberit != f.mapping.cend()) { + const usertype_detail::call_information& ci = memberit->second; + const usertype_detail::member_search& member = is_index ? ci.index: ci.new_index; + return (member)(L, static_cast(&f), ci.runtime_target); + } + string_detail::string_shim accessor = name; + int ret = 0; + bool found = false; + // Otherwise, we need to do propagating calls through the bases + if (is_index) + f.indexbaseclasspropogation(L, found, ret, accessor); + else + f.newindexbaseclasspropogation(L, found, ret, accessor); + if (found) { + return ret; + } + return toplevel ? (is_index ? f.indexfunc(L) : f.newindexfunc(L)) : -1; + } + + static int real_index_call(lua_State* L) { + return core_indexing_call(L); + } + + static int real_new_index_call(lua_State* L) { + return core_indexing_call(L); + } + + template + static int real_call(lua_State* L) { + usertype_metatable& f = stack::get>(L, upvalue_index(1)); + return real_call_with(L, f); + } + + template + static int real_call_with(lua_State* L, usertype_metatable& um) { + typedef meta::unqualified_tuple_element_t K; + typedef meta::unqualified_tuple_element_t F; + static const int boost = + !usertype_detail::is_non_factory_constructor::value + && std::is_same::value ? + 1 : 0; + auto& f = std::get(um.functions); + return call_detail::call_wrapped(L, f); + } + + template + static int call(lua_State* L) { + return detail::static_trampoline<(&real_call)>(L); + } + + template + static int call_with(lua_State* L) { + return detail::static_trampoline<(&real_call_with)>(L); + } + + static int index_call(lua_State* L) { + return detail::static_trampoline<(&real_index_call)>(L); + } + + static int new_index_call(lua_State* L) { + return detail::static_trampoline<(&real_new_index_call)>(L); + } + + virtual int push_um(lua_State* L) override { + return stack::push(L, std::move(*this)); + } + + ~usertype_metatable() override { + + } + }; + + namespace stack { + + template + struct pusher, Args...>> { + typedef usertype_metatable, Args...> umt_t; + typedef typename umt_t::regs_t regs_t; + + static umt_t& make_cleanup(lua_State* L, umt_t&& umx) { + // ensure some sort of uniqueness + static int uniqueness = 0; + std::string uniquegcmetakey = usertype_traits::user_gc_metatable(); + // std::to_string doesn't exist in android still, with NDK, so this bullshit + // is necessary + // thanks, Android :v + int appended = snprintf(nullptr, 0, "%d", uniqueness); + std::size_t insertionpoint = uniquegcmetakey.length() - 1; + uniquegcmetakey.append(appended, '\0'); + char* uniquetarget = &uniquegcmetakey[insertionpoint]; + snprintf(uniquetarget, uniquegcmetakey.length(), "%d", uniqueness); + ++uniqueness; + + const char* gcmetakey = &usertype_traits::gc_table()[0]; + // Make sure userdata's memory is properly in lua first, + // otherwise all the light userdata we make later will become invalid + stack::push>(L, metatable_key, uniquegcmetakey, std::move(umx)); + // Create the top level thing that will act as our deleter later on + stack_reference umt(L, -1); + stack::set_field(L, gcmetakey, umt); + umt.pop(); + + stack::get_field(L, gcmetakey); + return stack::pop>(L); + } + + static int push(lua_State* L, umt_t&& umx) { + + umt_t& um = make_cleanup(L, std::move(umx)); + usertype_metatable_core& umc = um; + regs_t value_table{ {} }; + int lastreg = 0; + (void)detail::swallow{ 0, (um.template make_regs<(I * 2)>(value_table, lastreg, std::get<(I * 2)>(um.functions), std::get<(I * 2 + 1)>(um.functions)), 0)... }; + um.finish_regs(value_table, lastreg); + value_table[lastreg] = { nullptr, nullptr }; + regs_t ref_table = value_table; + regs_t unique_table = value_table; + bool hasdestructor = !value_table.empty() && to_string(meta_function::garbage_collect) == value_table[lastreg - 1].name; + if (hasdestructor) { + ref_table[lastreg - 1] = { nullptr, nullptr }; + unique_table[lastreg - 1] = { value_table[lastreg - 1].name, detail::unique_destruct }; + } + + // Now use um + const bool& mustindex = umc.mustindex; + for (std::size_t i = 0; i < 3; ++i) { + // Pointer types, AKA "references" from C++ + const char* metakey = nullptr; + luaL_Reg* metaregs = nullptr; + switch (i) { + case 0: + metakey = &usertype_traits::metatable()[0]; + metaregs = ref_table.data(); + break; + case 1: + metakey = &usertype_traits>::metatable()[0]; + metaregs = unique_table.data(); + break; + case 2: + default: + metakey = &usertype_traits::metatable()[0]; + metaregs = value_table.data(); + break; + } + luaL_newmetatable(L, metakey); + stack_reference t(L, -1); + stack::push(L, make_light(um)); + luaL_setfuncs(L, metaregs, 1); + + if (um.baseclasscheck != nullptr) { + stack::set_field(L, detail::base_class_check_key(), um.baseclasscheck, t.stack_index()); + } + if (um.baseclasscast != nullptr) { + stack::set_field(L, detail::base_class_cast_key(), um.baseclasscast, t.stack_index()); + } + + stack::set_field(L, detail::base_class_index_propogation_key(), make_closure(um.indexbase, make_light(um), make_light(umc)), t.stack_index()); + stack::set_field(L, detail::base_class_new_index_propogation_key(), make_closure(um.newindexbase, make_light(um), make_light(umc)), t.stack_index()); + + if (mustindex) { + // Basic index pushing: specialize + // index and newindex to give variables and stuff + stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um), make_light(umc)), t.stack_index()); + stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um), make_light(umc)), t.stack_index()); + } + else { + // If there's only functions, we can use the fast index version + stack::set_field(L, meta_function::index, t, t.stack_index()); + } + // metatable on the metatable + // for call constructor purposes and such + lua_createtable(L, 0, 3); + stack_reference metabehind(L, -1); + if (um.callconstructfunc != nullptr) { + stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, make_light(um), make_light(umc)), metabehind.stack_index()); + } + if (um.secondarymeta) { + stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um), make_light(umc)), metabehind.stack_index()); + stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um), make_light(umc)), metabehind.stack_index()); + } + stack::set_field(L, metatable_key, metabehind, t.stack_index()); + metabehind.pop(); + // We want to just leave the table + // in the registry only, otherwise we return it + t.pop(); + } + + // Now for the shim-table that actually gets assigned to the name + luaL_newmetatable(L, &usertype_traits::user_metatable()[0]); + stack_reference t(L, -1); + stack::push(L, make_light(um)); + luaL_setfuncs(L, value_table.data(), 1); + { + lua_createtable(L, 0, 3); + stack_reference metabehind(L, -1); + if (um.callconstructfunc != nullptr) { + stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, make_light(um), make_light(umc)), metabehind.stack_index()); + } + + stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um), make_light(umc), 0, usertype_detail::toplevel_magic), metabehind.stack_index()); + stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um), make_light(umc), 0, usertype_detail::toplevel_magic), metabehind.stack_index()); + + stack::set_field(L, metatable_key, metabehind, t.stack_index()); + metabehind.pop(); + } + + return 1; + } + }; + + } // stack + +} // sol + +// end of sol/usertype_metatable.hpp + +// beginning of sol/simple_usertype_metatable.hpp + +namespace sol { + + namespace usertype_detail { + template + inline int simple_core_indexing_call(lua_State* L) { + simple_map& sm = toplevel ? stack::get>(L, upvalue_index(1)) : stack::pop>(L); + variable_map& variables = sm.variables; + function_map& functions = sm.functions; + static const int keyidx = -2 + static_cast(is_index); + if (toplevel) { + if (stack::get(L, keyidx) != type::string) { + lua_CFunction indexingfunc = is_index ? stack::get(L, upvalue_index(2)) : stack::get(L, upvalue_index(3)); + return indexingfunc(L); + } + } + string_detail::string_shim accessor = stack::get(L, keyidx); + std::string accessorkey = accessor.c_str(); + auto vit = variables.find(accessorkey); + if (vit != variables.cend()) { + auto& varwrap = *(vit->second); + if (is_index) { + return varwrap.index(L); + } + return varwrap.new_index(L); + } + auto fit = functions.find(accessorkey); + if (fit != functions.cend()) { + sol::object& func = fit->second; + if (is_index) { + return stack::push(L, func); + } + else { + lua_CFunction indexingfunc = is_index ? stack::get(L, upvalue_index(2)) : stack::get(L, upvalue_index(3)); + return indexingfunc(L); + } + } + // Check table storage first for a method that works + luaL_getmetatable(L, sm.metakey); + if (type_of(L, -1) != type::lua_nil) { + stack::get_field(L, accessor.c_str(), lua_gettop(L)); + if (type_of(L, -1) != type::lua_nil) { + // Woo, we found it? + lua_remove(L, -2); + return 1; + } + lua_pop(L, 1); + } + lua_pop(L, 1); + + int ret = 0; + bool found = false; + // Otherwise, we need to do propagating calls through the bases + if (is_index) { + sm.indexbaseclasspropogation(L, found, ret, accessor); + } + else { + sm.newindexbaseclasspropogation(L, found, ret, accessor); + } + if (found) { + return ret; + } + if (toplevel) { + lua_CFunction indexingfunc = is_index ? stack::get(L, upvalue_index(2)) : stack::get(L, upvalue_index(3)); + return indexingfunc(L); + } + return -1; + } + + inline int simple_real_index_call(lua_State* L) { + return simple_core_indexing_call(L); + } + + inline int simple_real_new_index_call(lua_State* L) { + return simple_core_indexing_call(L); + } + + inline int simple_index_call(lua_State* L) { + return detail::static_trampoline<(&simple_real_index_call)>(L); + } + + inline int simple_new_index_call(lua_State* L) { + return detail::static_trampoline<(&simple_real_new_index_call)>(L); + } + } + + struct simple_tag {} const simple{}; + + template + struct simple_usertype_metatable : usertype_detail::registrar { + public: + usertype_detail::function_map registrations; + usertype_detail::variable_map varmap; + object callconstructfunc; + lua_CFunction indexfunc; + lua_CFunction newindexfunc; + lua_CFunction indexbase; + lua_CFunction newindexbase; + usertype_detail::base_walk indexbaseclasspropogation; + usertype_detail::base_walk newindexbaseclasspropogation; + void* baseclasscheck; + void* baseclasscast; + bool mustindex; + bool secondarymeta; + + template + void insert(N&& n, object&& o) { + std::string key = usertype_detail::make_string(std::forward(n)); + auto hint = registrations.find(key); + if (hint == registrations.cend()) { + registrations.emplace_hint(hint, std::move(key), std::move(o)); + return; + } + hint->second = std::move(o); + } + + template + void insert_prepare(std::true_type, lua_State* L, N&&, F&& f, Args&&... args) { + object o = make_object(L, std::forward(f), function_detail::call_indicator(), std::forward(args)...); + callconstructfunc = std::move(o); + } + + template + void insert_prepare(std::false_type, lua_State* L, N&& n, F&& f, Args&&... args) { + object o = make_object(L, std::forward(f), std::forward(args)...); + insert(std::forward(n), std::move(o)); + } + + template + void add_member_function(std::true_type, lua_State* L, N&& n, F&& f) { + insert_prepare(std::is_same, call_construction>(), L, std::forward(n), std::forward(f), function_detail::class_indicator()); + } + + template + void add_member_function(std::false_type, lua_State* L, N&& n, F&& f) { + insert_prepare(std::is_same, call_construction>(), L, std::forward(n), std::forward(f)); + } + + template >> = meta::enabler> + void add_function(lua_State* L, N&& n, F&& f) { + object o = make_object(L, as_function_reference(std::forward(f))); + if (std::is_same, call_construction>::value) { + callconstructfunc = std::move(o); + return; + } + insert(std::forward(n), std::move(o)); + } + + template >> = meta::enabler> + void add_function(lua_State* L, N&& n, F&& f) { + add_member_function(std::is_member_pointer>(), L, std::forward(n), std::forward(f)); + } + + template >> = meta::enabler> + void add(lua_State* L, N&& n, F&& f) { + add_function(L, std::forward(n), std::forward(f)); + } + + template >> = meta::enabler> + void add(lua_State*, N&& n, F&& f) { + mustindex = true; + secondarymeta = true; + std::string key = usertype_detail::make_string(std::forward(n)); + auto o = std::make_unique>>(std::forward(f)); + auto hint = varmap.find(key); + if (hint == varmap.cend()) { + varmap.emplace_hint(hint, std::move(key), std::move(o)); + return; + } + hint->second = std::move(o); + } + + template + void add(lua_State* L, N&& n, constructor_wrapper c) { + object o(L, in_place>>, std::move(c)); + if (std::is_same, call_construction>::value) { + callconstructfunc = std::move(o); + return; + } + insert(std::forward(n), std::move(o)); + } + + template + void add(lua_State* L, N&& n, constructor_list c) { + object o(L, in_place>>, std::move(c)); + if (std::is_same, call_construction>::value) { + callconstructfunc = std::move(o); + return; + } + insert(std::forward(n), std::move(o)); + } + + template + void add(lua_State* L, N&& n, destructor_wrapper c) { + object o(L, in_place>>, std::move(c)); + if (std::is_same, call_construction>::value) { + callconstructfunc = std::move(o); + return; + } + insert(std::forward(n), std::move(o)); + } + + template + void add(lua_State* L, N&& n, destructor_wrapper c) { + object o(L, in_place>>, std::move(c)); + if (std::is_same, call_construction>::value) { + callconstructfunc = std::move(o); + return; + } + insert(std::forward(n), std::move(o)); + } + + template + void add(lua_State*, base_classes_tag, bases) { + static_assert(sizeof(usertype_detail::base_walk) <= sizeof(void*), "size of function pointer is greater than sizeof(void*); cannot work on this platform. Please file a bug report."); + static_assert(!meta::any_same::value, "base classes cannot list the original class as part of the bases"); + if (sizeof...(Bases) < 1) { + return; + } + mustindex = true; + (void)detail::swallow{ 0, ((detail::has_derived::value = true), 0)... }; + + static_assert(sizeof(void*) <= sizeof(detail::inheritance_check_function), "The size of this data pointer is too small to fit the inheritance checking function: Please file a bug report."); + static_assert(sizeof(void*) <= sizeof(detail::inheritance_cast_function), "The size of this data pointer is too small to fit the inheritance checking function: Please file a bug report."); + baseclasscheck = (void*)&detail::inheritance::type_check; + baseclasscast = (void*)&detail::inheritance::type_cast; + indexbaseclasspropogation = usertype_detail::walk_all_bases; + newindexbaseclasspropogation = usertype_detail::walk_all_bases; + } + + private: + template + simple_usertype_metatable(usertype_detail::verified_tag, std::index_sequence, lua_State* L, Tuple&& args) + : callconstructfunc(lua_nil), + indexfunc(&usertype_detail::indexing_fail), newindexfunc(&usertype_detail::metatable_newindex), + indexbase(&usertype_detail::simple_core_indexing_call), newindexbase(&usertype_detail::simple_core_indexing_call), + indexbaseclasspropogation(usertype_detail::walk_all_bases), newindexbaseclasspropogation(&usertype_detail::walk_all_bases), + baseclasscheck(nullptr), baseclasscast(nullptr), + mustindex(false), secondarymeta(false) { + (void)detail::swallow{ 0, + (add(L, detail::forward_get(args), detail::forward_get(args)),0)... + }; + } + + template + simple_usertype_metatable(lua_State* L, usertype_detail::verified_tag v, Args&&... args) : simple_usertype_metatable(v, std::make_index_sequence(), L, std::forward_as_tuple(std::forward(args)...)) {} + + template + simple_usertype_metatable(lua_State* L, usertype_detail::add_destructor_tag, Args&&... args) : simple_usertype_metatable(L, usertype_detail::verified, std::forward(args)..., "__gc", default_destructor) {} + + template + simple_usertype_metatable(lua_State* L, usertype_detail::check_destructor_tag, Args&&... args) : simple_usertype_metatable(L, meta::condition, meta::neg>>, usertype_detail::add_destructor_tag, usertype_detail::verified_tag>(), std::forward(args)...) {} + + public: + simple_usertype_metatable(lua_State* L) : simple_usertype_metatable(L, meta::condition>, decltype(default_constructor), usertype_detail::check_destructor_tag>()) {} + + template, + usertype_detail::verified_tag, + usertype_detail::add_destructor_tag, + usertype_detail::check_destructor_tag + >, + meta::is_specialization_of>, + meta::is_specialization_of> + > = meta::enabler> + simple_usertype_metatable(lua_State* L, Arg&& arg, Args&&... args) : simple_usertype_metatable(L, meta::condition, meta::neg>>, decltype(default_constructor), usertype_detail::check_destructor_tag>(), std::forward(arg), std::forward(args)...) {} + + template + simple_usertype_metatable(lua_State* L, constructors constructorlist, Args&&... args) : simple_usertype_metatable(L, usertype_detail::check_destructor_tag(), std::forward(args)..., "new", constructorlist) {} + + template + simple_usertype_metatable(lua_State* L, constructor_wrapper constructorlist, Args&&... args) : simple_usertype_metatable(L, usertype_detail::check_destructor_tag(), std::forward(args)..., "new", constructorlist) {} + + simple_usertype_metatable(const simple_usertype_metatable&) = default; + simple_usertype_metatable(simple_usertype_metatable&&) = default; + simple_usertype_metatable& operator=(const simple_usertype_metatable&) = default; + simple_usertype_metatable& operator=(simple_usertype_metatable&&) = default; + + virtual int push_um(lua_State* L) override { + return stack::push(L, std::move(*this)); + } + }; + + namespace stack { + template + struct pusher> { + typedef simple_usertype_metatable umt_t; + + static usertype_detail::simple_map& make_cleanup(lua_State* L, umt_t& umx) { + static int uniqueness = 0; + std::string uniquegcmetakey = usertype_traits::user_gc_metatable(); + // std::to_string doesn't exist in android still, with NDK, so this bullshit + // is necessary + // thanks, Android :v + int appended = snprintf(nullptr, 0, "%d", uniqueness); + std::size_t insertionpoint = uniquegcmetakey.length() - 1; + uniquegcmetakey.append(appended, '\0'); + char* uniquetarget = &uniquegcmetakey[insertionpoint]; + snprintf(uniquetarget, uniquegcmetakey.length(), "%d", uniqueness); + ++uniqueness; + + const char* gcmetakey = &usertype_traits::gc_table()[0]; + stack::push>(L, metatable_key, uniquegcmetakey, &usertype_traits::metatable()[0], + umx.indexbaseclasspropogation, umx.newindexbaseclasspropogation, + std::move(umx.varmap), std::move(umx.registrations) + ); + stack_reference stackvarmap(L, -1); + stack::set_field(L, gcmetakey, stackvarmap); + stackvarmap.pop(); + + stack::get_field(L, gcmetakey); + usertype_detail::simple_map& varmap = stack::pop>(L); + return varmap; + } + + static int push(lua_State* L, umt_t&& umx) { + auto& varmap = make_cleanup(L, umx); + bool hasequals = false; + bool hasless = false; + bool haslessequals = false; + auto register_kvp = [&](std::size_t i, stack_reference& t, const std::string& first, object& second) { + if (first == to_string(meta_function::equal_to)) { + hasequals = true; + } + else if (first == to_string(meta_function::less_than)) { + hasless = true; + } + else if (first == to_string(meta_function::less_than_or_equal_to)) { + haslessequals = true; + } + else if (first == to_string(meta_function::index)) { + umx.indexfunc = second.template as(); + } + else if (first == to_string(meta_function::new_index)) { + umx.newindexfunc = second.template as(); + } + switch (i) { + case 0: + if (first == to_string(meta_function::garbage_collect)) { + return; + } + break; + case 1: + if (first == to_string(meta_function::garbage_collect)) { + stack::set_field(L, first, detail::unique_destruct, t.stack_index()); + return; + } + break; + case 2: + default: + break; + } + stack::set_field(L, first, second, t.stack_index()); + }; + for (std::size_t i = 0; i < 3; ++i) { + // Pointer types, AKA "references" from C++ + const char* metakey = nullptr; + switch (i) { + case 0: + metakey = &usertype_traits::metatable()[0]; + break; + case 1: + metakey = &usertype_traits>::metatable()[0]; + break; + case 2: + default: + metakey = &usertype_traits::metatable()[0]; + break; + } + luaL_newmetatable(L, metakey); + stack_reference t(L, -1); + for (auto& kvp : varmap.functions) { + auto& first = std::get<0>(kvp); + auto& second = std::get<1>(kvp); + register_kvp(i, t, first, second); + } + luaL_Reg opregs[4]{}; + int opregsindex = 0; + if (!hasless) { + const char* name = to_string(meta_function::less_than).c_str(); + usertype_detail::make_reg_op, meta::supports_op_less>(opregs, opregsindex, name); + } + if (!haslessequals) { + const char* name = to_string(meta_function::less_than_or_equal_to).c_str(); + usertype_detail::make_reg_op, meta::supports_op_less_equal>(opregs, opregsindex, name); + } + if (!hasequals) { + const char* name = to_string(meta_function::equal_to).c_str(); + usertype_detail::make_reg_op::value, std::equal_to<>, usertype_detail::no_comp>, std::true_type>(opregs, opregsindex, name); + } + t.push(); + luaL_setfuncs(L, opregs, 0); + t.pop(); + + if (umx.baseclasscheck != nullptr) { + stack::set_field(L, detail::base_class_check_key(), umx.baseclasscheck, t.stack_index()); + } + if (umx.baseclasscast != nullptr) { + stack::set_field(L, detail::base_class_cast_key(), umx.baseclasscast, t.stack_index()); + } + + // Base class propagation features + stack::set_field(L, detail::base_class_index_propogation_key(), umx.indexbase, t.stack_index()); + stack::set_field(L, detail::base_class_new_index_propogation_key(), umx.newindexbase, t.stack_index()); + + if (umx.mustindex) { + // use indexing function + stack::set_field(L, meta_function::index, + make_closure(&usertype_detail::simple_index_call, + make_light(varmap), + umx.indexfunc, + umx.newindexfunc + ), t.stack_index()); + stack::set_field(L, meta_function::new_index, + make_closure(&usertype_detail::simple_new_index_call, + make_light(varmap), + umx.indexfunc, + umx.newindexfunc + ), t.stack_index()); + } + else { + // Metatable indexes itself + stack::set_field(L, meta_function::index, t, t.stack_index()); + } + // metatable on the metatable + // for call constructor purposes and such + lua_createtable(L, 0, 2 * static_cast(umx.secondarymeta) + static_cast(umx.callconstructfunc.valid())); + stack_reference metabehind(L, -1); + if (umx.callconstructfunc.valid()) { + stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index()); + } + if (umx.secondarymeta) { + stack::set_field(L, meta_function::index, + make_closure(&usertype_detail::simple_index_call, + make_light(varmap), + umx.indexfunc, + umx.newindexfunc + ), metabehind.stack_index()); + stack::set_field(L, meta_function::new_index, + make_closure(&usertype_detail::simple_new_index_call, + make_light(varmap), + umx.indexfunc, + umx.newindexfunc + ), metabehind.stack_index()); + } + stack::set_field(L, metatable_key, metabehind, t.stack_index()); + metabehind.pop(); + + t.pop(); + } + + // Now for the shim-table that actually gets pushed + luaL_newmetatable(L, &usertype_traits::user_metatable()[0]); + stack_reference t(L, -1); + for (auto& kvp : varmap.functions) { + auto& first = std::get<0>(kvp); + auto& second = std::get<1>(kvp); + register_kvp(2, t, first, second); + } + { + lua_createtable(L, 0, 2 + static_cast(umx.callconstructfunc.valid())); + stack_reference metabehind(L, -1); + if (umx.callconstructfunc.valid()) { + stack::set_field(L, sol::meta_function::call_function, umx.callconstructfunc, metabehind.stack_index()); + } + // use indexing function + stack::set_field(L, meta_function::index, + make_closure(&usertype_detail::simple_index_call, + make_light(varmap), + umx.indexfunc, + umx.newindexfunc, + usertype_detail::toplevel_magic + ), metabehind.stack_index()); + stack::set_field(L, meta_function::new_index, + make_closure(&usertype_detail::simple_new_index_call, + make_light(varmap), + umx.indexfunc, + umx.newindexfunc, + usertype_detail::toplevel_magic + ), metabehind.stack_index()); + stack::set_field(L, metatable_key, metabehind, t.stack_index()); + metabehind.pop(); + } + + // Don't pop the table when we're done; + // return it + return 1; + } + }; + } // stack +} // sol + +// end of sol/simple_usertype_metatable.hpp + +// beginning of sol/container_usertype_metatable.hpp + +namespace sol { + + namespace detail { + + template + struct has_find { + private: + typedef std::array one; + typedef std::array two; + + template static one test(decltype(&C::find)); + template static two test(...); + + public: + static const bool value = sizeof(test(0)) == sizeof(char); + }; + + template + struct has_push_back { + private: + typedef std::array one; + typedef std::array two; + + template static one test(decltype(std::declval().push_back(std::declval>()))*); + template static two test(...); + + public: + static const bool value = sizeof(test(0)) == sizeof(char); + }; + + template + struct has_clear { + private: + typedef std::array one; + typedef std::array two; + + template static one test(decltype(&C::clear)); + template static two test(...); + + public: + static const bool value = sizeof(test(0)) == sizeof(char); + }; + + template + struct has_insert { + private: + typedef std::array one; + typedef std::array two; + + template static one test(decltype(std::declval().insert(std::declval>(), std::declval>()))*); + template static two test(...); + + public: + static const bool value = sizeof(test(0)) == sizeof(char); + }; + + template + T& get_first(const T& t) { + return std::forward(t); + } + + template + decltype(auto) get_first(const std::pair& t) { + return t.first; + } + + template >> = meta::enabler> + auto find(C& c, I&& i) { + return c.find(std::forward(i)); + } + + template >> = meta::enabler> + auto find(C& c, I&& i) { + using std::begin; + using std::end; + return std::find_if(begin(c), end(c), [&i](auto&& x) { + return i == get_first(x); + }); + } + + } + + template + struct container_usertype_metatable { + typedef meta::has_key_value_pair> is_associative; + typedef meta::unqualified_t T; + typedef typename T::iterator I; + typedef std::conditional_t> KV; + typedef typename KV::first_type K; + typedef typename KV::second_type V; + typedef std::remove_reference_t())> IR; + + struct iter { + T& source; + I it; + + iter(T& source, I it) : source(source), it(std::move(it)) {} + }; + + static auto& get_src(lua_State* L) { +#ifdef SOL_SAFE_USERTYPE + auto p = stack::check_get(L, 1); + if (!p || p.value() == nullptr) { + luaL_error(L, "sol: 'self' argument is not the proper type (pass 'self' as first argument with ':' or call on proper type)"); + } + return *p.value(); +#else + return stack::get(L, 1); +#endif // Safe getting with error + } + + static int real_index_call_associative(std::true_type, lua_State* L) { + auto k = stack::check_get(L, 2); + if (k) { + auto& src = get_src(L); + using std::end; + auto it = detail::find(src, *k); + if (it != end(src)) { + auto& v = *it; + return stack::push_reference(L, v.second); + } + } + else { + auto maybename = stack::check_get(L, 2); + if (maybename) { + auto& name = *maybename; + if (name == "add") { + return stack::push(L, &add_call); + } + else if (name == "insert") { + return stack::push(L, &insert_call); + } + else if (name == "clear") { + return stack::push(L, &clear_call); + } + } + } + return stack::push(L, lua_nil); + } + + static int real_index_call_associative(std::false_type, lua_State* L) { + auto& src = get_src(L); + auto maybek = stack::check_get(L, 2); + if (maybek) { + using std::begin; + auto it = begin(src); + K k = *maybek; + if (k > src.size() || k < 1) { + return stack::push(L, lua_nil); + } + --k; + std::advance(it, k); + return stack::push_reference(L, *it); + } + else { + auto maybename = stack::check_get(L, 2); + if (maybename) { + auto& name = *maybename; + if (name == "add") { + return stack::push(L, &add_call); + } + else if (name == "insert") { + return stack::push(L, &insert_call); + } + else if (name == "clear") { + return stack::push(L, &clear_call); + } + } + } + + return stack::push(L, lua_nil); + } + + static int real_index_call(lua_State* L) { + return real_index_call_associative(is_associative(), L); + } + + static int real_new_index_call_const(std::false_type, std::false_type, lua_State* L) { + return luaL_error(L, "sol: cannot write to a const value type or an immutable iterator (e.g., std::set)"); + } + + static int real_new_index_call_const(std::false_type, std::true_type, lua_State* L) { + return luaL_error(L, "sol: cannot write to a const value type or an immutable iterator (e.g., std::set)"); + } + + static int real_new_index_call_const(std::true_type, std::true_type, lua_State* L) { + auto& src = get_src(L); + auto k = stack::check_get(L, 2); + if (k) { + using std::end; + auto it = detail::find(src, *k); + if (it != end(src)) { + auto& v = *it; + v.second = stack::get(L, 3); + } + else { + src.insert(it, { std::move(*k), stack::get(L, 3) }); + } + } + return 0; + } + + static int real_new_index_call_const(std::true_type, std::false_type, lua_State* L) { + auto& src = get_src(L); +#ifdef SOL_SAFE_USERTYPE + auto maybek = stack::check_get(L, 2); + if (!maybek) { + return 0; + } + K k = *maybek; +#else + K k = stack::get(L, 2); +#endif + using std::begin; + auto it = begin(src); + --k; + if (k == src.size()) { + real_add_call_push(std::integral_constant::value>(), L, src, 1); + return 0; + } + std::advance(it, k); + *it = stack::get(L, 3); + return 0; + } + + static int real_new_index_call(lua_State* L) { + return real_new_index_call_const(meta::neg, std::is_const>>(), is_associative(), L); + } + + static int real_pairs_next_call_assoc(std::true_type, lua_State* L) { + using std::end; + iter& i = stack::get>(L, 1); + auto& source = i.source; + auto& it = i.it; + if (it == end(source)) { + return 0; + } + int p = stack::multi_push_reference(L, it->first, it->second); + std::advance(it, 1); + return p; + } + + static int real_pairs_call_assoc(std::true_type, lua_State* L) { + auto& src = get_src(L); + using std::begin; + stack::push(L, pairs_next_call); + stack::push>(L, src, begin(src)); + stack::push(L, 1); + return 3; + } + + static int real_pairs_next_call_assoc(std::false_type, lua_State* L) { + using std::end; + iter& i = stack::get>(L, 1); + auto& source = i.source; + auto& it = i.it; + K k = stack::get(L, 2); + if (it == end(source)) { + return 0; + } + int p = stack::multi_push_reference(L, k + 1, *it); + std::advance(it, 1); + return p; + } + + static int real_pairs_call_assoc(std::false_type, lua_State* L) { + auto& src = get_src(L); + using std::begin; + stack::push(L, pairs_next_call); + stack::push>(L, src, begin(src)); + stack::push(L, 0); + return 3; + } + + static int real_pairs_next_call(lua_State* L) { + return real_pairs_next_call_assoc(is_associative(), L); + } + + static int real_pairs_call(lua_State* L) { + return real_pairs_call_assoc(is_associative(), L); + } + + static int real_length_call(lua_State*L) { + auto& src = get_src(L); + return stack::push(L, src.size()); + } + + static int real_add_call_insert(std::true_type, lua_State*L, T& src, int boost = 0) { + using std::end; + src.insert(end(src), stack::get(L, 2 + boost)); + return 0; + } + + static int real_add_call_insert(std::false_type, lua_State*L, T&, int = 0) { + static const std::string& s = detail::demangle(); + return luaL_error(L, "sol: cannot call insert on type %s", s.c_str()); + } + + static int real_add_call_push(std::true_type, lua_State*L, T& src, int boost = 0) { + src.push_back(stack::get(L, 2 + boost)); + return 0; + } + + static int real_add_call_push(std::false_type, lua_State*L, T& src, int boost = 0) { + return real_add_call_insert(std::integral_constant::value>(), L, src, boost); + } + + static int real_add_call_associative(std::true_type, lua_State* L) { + return real_insert_call(L); + } + + static int real_add_call_associative(std::false_type, lua_State* L) { + auto& src = get_src(L); + return real_add_call_push(std::integral_constant::value>(), L, src); + } + + static int real_add_call_capable(std::true_type, lua_State* L) { + return real_add_call_associative(is_associative(), L); + } + + static int real_add_call_capable(std::false_type, lua_State* L) { + static const std::string& s = detail::demangle(); + return luaL_error(L, "sol: cannot call add on type %s", s.c_str()); + } + + static int real_add_call(lua_State* L) { + return real_add_call_capable(std::integral_constant::value || detail::has_insert::value>(), L); + } + + static int real_insert_call_capable(std::false_type, std::false_type, lua_State*L) { + static const std::string& s = detail::demangle(); + return luaL_error(L, "sol: cannot call insert on type %s", s.c_str()); + } + + static int real_insert_call_capable(std::false_type, std::true_type, lua_State*L) { + return real_insert_call_capable(std::false_type(), std::false_type(), L); + } + + static int real_insert_call_capable(std::true_type, std::false_type, lua_State* L) { + using std::begin; + auto& src = get_src(L); + src.insert(std::next(begin(src), stack::get(L, 2)), stack::get(L, 3)); + return 0; + } + + static int real_insert_call_capable(std::true_type, std::true_type, lua_State* L) { + return real_new_index_call(L); + } + + static int real_insert_call(lua_State*L) { + return real_insert_call_capable(std::integral_constant::value>(), is_associative(), L); + } + + static int real_clear_call_capable(std::false_type, lua_State* L) { + static const std::string& s = detail::demangle(); + return luaL_error(L, "sol: cannot call clear on type %s", s.c_str()); + } + + static int real_clear_call_capable(std::true_type, lua_State* L) { + auto& src = get_src(L); + src.clear(); + return 0; + } + + static int real_clear_call(lua_State*L) { + return real_clear_call_capable(std::integral_constant::value>(), L); + } + + static int add_call(lua_State*L) { + return detail::static_trampoline<(&real_add_call)>(L); + } + + static int insert_call(lua_State*L) { + return detail::static_trampoline<(&real_insert_call)>(L); + } + + static int clear_call(lua_State*L) { + return detail::static_trampoline<(&real_clear_call)>(L); + } + + static int length_call(lua_State*L) { + return detail::static_trampoline<(&real_length_call)>(L); + } + + static int pairs_next_call(lua_State*L) { + return detail::static_trampoline<(&real_pairs_next_call)>(L); + } + + static int pairs_call(lua_State*L) { + return detail::static_trampoline<(&real_pairs_call)>(L); + } + + static int index_call(lua_State*L) { + return detail::static_trampoline<(&real_index_call)>(L); + } + + static int new_index_call(lua_State*L) { + return detail::static_trampoline<(&real_new_index_call)>(L); + } + }; + + namespace stack { + namespace stack_detail { + template + inline auto container_metatable() { + typedef container_usertype_metatable> meta_cumt; + std::array reg = { { + { "__index", &meta_cumt::index_call }, + { "__newindex", &meta_cumt::new_index_call }, + { "__pairs", &meta_cumt::pairs_call }, + { "__ipairs", &meta_cumt::pairs_call }, + { "__len", &meta_cumt::length_call }, + { "clear", &meta_cumt::clear_call }, + { "insert", &meta_cumt::insert_call }, + { "add", &meta_cumt::add_call }, + std::is_pointer::value ? luaL_Reg{ nullptr, nullptr } : luaL_Reg{ "__gc", &detail::usertype_alloc_destroy }, + { nullptr, nullptr } + } }; + return reg; + } + + template + inline auto container_metatable_behind() { + typedef container_usertype_metatable> meta_cumt; + std::array reg = { { + { "__index", &meta_cumt::index_call }, + { "__newindex", &meta_cumt::new_index_call }, + { nullptr, nullptr } + } }; + return reg; + } + + template + struct metatable_setup { + lua_State* L; + + metatable_setup(lua_State* L) : L(L) {} + + void operator()() { + static const auto reg = container_metatable(); + static const auto containerreg = container_metatable_behind(); + static const char* metakey = &usertype_traits::metatable()[0]; + + if (luaL_newmetatable(L, metakey) == 1) { + stack_reference metatable(L, -1); + luaL_setfuncs(L, reg.data(), 0); + + lua_createtable(L, 0, static_cast(containerreg.size())); + stack_reference metabehind(L, -1); + luaL_setfuncs(L, containerreg.data(), 0); + + stack::set_field(L, metatable_key, metabehind, metatable.stack_index()); + metabehind.pop(); + } + lua_setmetatable(L, -2); + } + }; + } + + template + struct pusher>, meta::neg>, std::is_base_of>>>>::value>> { + static int push(lua_State* L, const T& cont) { + stack_detail::metatable_setup fx(L); + return pusher>{}.push_fx(L, fx, cont); + } + + static int push(lua_State* L, T&& cont) { + stack_detail::metatable_setup fx(L); + return pusher>{}.push_fx(L, fx, std::move(cont)); + } + }; + + template + struct pusher>, meta::neg>, std::is_base_of>>>>::value>> { + static int push(lua_State* L, T* cont) { + stack_detail::metatable_setup>*> fx(L); + return pusher>{}.push_fx(L, fx, cont); + } + }; + } // stack + +} // sol + +// end of sol/container_usertype_metatable.hpp + +namespace sol { + + template + class usertype { + private: + std::unique_ptr metatableregister; + + template + usertype(usertype_detail::verified_tag, Args&&... args) : metatableregister(detail::make_unique_deleter, Args...>, detail::deleter>(std::forward(args)...)) {} + + template + usertype(usertype_detail::add_destructor_tag, Args&&... args) : usertype(usertype_detail::verified, std::forward(args)..., "__gc", default_destructor) {} + + template + usertype(usertype_detail::check_destructor_tag, Args&&... args) : usertype(meta::condition, meta::neg>>, usertype_detail::add_destructor_tag, usertype_detail::verified_tag>(), std::forward(args)...) {} + + public: + + template + usertype(Args&&... args) : usertype(meta::condition, meta::neg>>, decltype(default_constructor), usertype_detail::check_destructor_tag>(), std::forward(args)...) {} + + template + usertype(constructors constructorlist, Args&&... args) : usertype(usertype_detail::check_destructor_tag(), std::forward(args)..., "new", constructorlist) {} + + template + usertype(constructor_wrapper constructorlist, Args&&... args) : usertype(usertype_detail::check_destructor_tag(), std::forward(args)..., "new", constructorlist) {} + + template + usertype(simple_tag, lua_State* L, Args&&... args) : metatableregister(detail::make_unique_deleter, detail::deleter>(L, std::forward(args)...)) {} + + usertype_detail::registrar* registrar_data() { + return metatableregister.get(); + } + + int push(lua_State* L) { + int r = metatableregister->push_um(L); + metatableregister = nullptr; + return r; + } + }; + + template + class simple_usertype : public usertype { + private: + typedef usertype base_t; + lua_State* state; + + public: + template + simple_usertype(lua_State* L, Args&&... args) : base_t(simple, L, std::forward(args)...), state(L) {} + + template + void set(N&& n, F&& f) { + auto meta = static_cast*>(base_t::registrar_data()); + meta->add(state, n, f); + } + }; + + namespace stack { + template + struct pusher> { + static int push(lua_State* L, usertype& user) { + return user.push(L); + } + }; + } // stack +} // sol + +// end of sol/usertype.hpp + +// beginning of sol/table_iterator.hpp + +namespace sol { + + template + class basic_table_iterator : public std::iterator> { + private: + typedef std::iterator> base_t; + public: + typedef object key_type; + typedef object mapped_type; + typedef base_t::value_type value_type; + typedef base_t::iterator_category iterator_category; + typedef base_t::difference_type difference_type; + typedef base_t::pointer pointer; + typedef base_t::reference reference; + typedef const value_type& const_reference; + + private: + std::pair kvp; + reference_type ref; + int tableidx = 0; + int keyidx = 0; + std::ptrdiff_t idx = 0; + + public: + + basic_table_iterator() : keyidx(-1), idx(-1) { + + } + + basic_table_iterator(reference_type x) : ref(std::move(x)) { + ref.push(); + tableidx = lua_gettop(ref.lua_state()); + stack::push(ref.lua_state(), lua_nil); + this->operator++(); + if (idx == -1) { + return; + } + --idx; + } + + basic_table_iterator& operator++() { + if (idx == -1) + return *this; + + if (lua_next(ref.lua_state(), tableidx) == 0) { + idx = -1; + keyidx = -1; + return *this; + } + ++idx; + kvp.first = object(ref.lua_state(), -2); + kvp.second = object(ref.lua_state(), -1); + lua_pop(ref.lua_state(), 1); + // leave key on the stack + keyidx = lua_gettop(ref.lua_state()); + return *this; + } + + basic_table_iterator operator++(int) { + auto saved = *this; + this->operator++(); + return saved; + } + + reference operator*() { + return kvp; + } + + const_reference operator*() const { + return kvp; + } + + bool operator== (const basic_table_iterator& right) const { + return idx == right.idx; + } + + bool operator!= (const basic_table_iterator& right) const { + return idx != right.idx; + } + + ~basic_table_iterator() { + if (keyidx != -1) { + stack::remove(ref.lua_state(), keyidx, 1); + } + if (ref.valid()) { + stack::remove(ref.lua_state(), tableidx, 1); + } + } + }; + +} // sol + +// end of sol/table_iterator.hpp + +namespace sol { + namespace detail { + template + struct clean { lua_State* L; clean(lua_State* luastate) : L(luastate) {} ~clean() { lua_pop(L, static_cast(n)); } }; + struct ref_clean { lua_State* L; int& n; ref_clean(lua_State* luastate, int& n) : L(luastate), n(n) {} ~ref_clean() { lua_pop(L, static_cast(n)); } }; + inline int fail_on_newindex(lua_State* L) { + return luaL_error(L, "sol: cannot modify the elements of an enumeration table"); + } + } + + const new_table create = new_table{}; + + template + class basic_table_core : public basic_object_base { + typedef basic_object_base base_t; + friend class state; + friend class state_view; + + template + using is_global = meta::all, meta::is_c_str...>; + + template + void for_each(std::true_type, Fx&& fx) const { + auto pp = stack::push_pop(*this); + stack::push(base_t::lua_state(), lua_nil); + while (lua_next(base_t::lua_state(), -2)) { + sol::object key(base_t::lua_state(), -2); + sol::object value(base_t::lua_state(), -1); + std::pair keyvalue(key, value); + auto pn = stack::pop_n(base_t::lua_state(), 1); + fx(keyvalue); + } + } + + template + void for_each(std::false_type, Fx&& fx) const { + auto pp = stack::push_pop(*this); + stack::push(base_t::lua_state(), lua_nil); + while (lua_next(base_t::lua_state(), -2)) { + sol::object key(base_t::lua_state(), -2); + sol::object value(base_t::lua_state(), -1); + auto pn = stack::pop_n(base_t::lua_state(), 1); + fx(key, value); + } + } + + template + auto tuple_get(types, std::index_sequence<0, 1, I...>, Keys&& keys) const + -> decltype(stack::pop>(nullptr)) { + typedef decltype(stack::pop>(nullptr)) Tup; + return Tup( + traverse_get_optional(meta::is_specialization_of>(), detail::forward_get<0>(keys)), + traverse_get_optional(meta::is_specialization_of>(), detail::forward_get<1>(keys)), + traverse_get_optional(meta::is_specialization_of>(), detail::forward_get(keys))... + ); + } + + template + decltype(auto) tuple_get(types, std::index_sequence, Keys&& keys) const { + return traverse_get_optional(meta::is_specialization_of>(), detail::forward_get(keys)); + } + + template + void tuple_set(std::index_sequence, Pairs&& pairs) { + auto pp = stack::push_pop(pairs))...>::value)>(*this); + void(detail::swallow{ (stack::set_field(base_t::lua_state(), + detail::forward_get(pairs), + detail::forward_get(pairs), + lua_gettop(base_t::lua_state()) + ), 0)... }); + } + + template + decltype(auto) traverse_get_deep(Key&& key) const { + stack::get_field(base_t::lua_state(), std::forward(key)); + return stack::get(base_t::lua_state()); + } + + template + decltype(auto) traverse_get_deep(Key&& key, Keys&&... keys) const { + stack::get_field(base_t::lua_state(), std::forward(key)); + return traverse_get_deep(std::forward(keys)...); + } + + template + decltype(auto) traverse_get_deep_optional(int& popcount, Key&& key) const { + typedef decltype(stack::get(base_t::lua_state())) R; + auto p = stack::probe_get_field(base_t::lua_state(), std::forward(key), lua_gettop(base_t::lua_state())); + popcount += p.levels; + if (!p.success) + return R(nullopt); + return stack::get(base_t::lua_state()); + } + + template + decltype(auto) traverse_get_deep_optional(int& popcount, Key&& key, Keys&&... keys) const { + auto p = I > 0 ? stack::probe_get_field(base_t::lua_state(), std::forward(key), -1) : stack::probe_get_field(base_t::lua_state(), std::forward(key), lua_gettop(base_t::lua_state())); + popcount += p.levels; + if (!p.success) + return T(nullopt); + return traverse_get_deep_optional(popcount, std::forward(keys)...); + } + + template + decltype(auto) traverse_get_optional(std::false_type, Keys&&... keys) const { + detail::clean c(base_t::lua_state()); + return traverse_get_deep(std::forward(keys)...); + } + + template + decltype(auto) traverse_get_optional(std::true_type, Keys&&... keys) const { + int popcount = 0; + detail::ref_clean c(base_t::lua_state(), popcount); + return traverse_get_deep_optional(popcount, std::forward(keys)...); + } + + template + void traverse_set_deep(Key&& key, Value&& value) const { + stack::set_field(base_t::lua_state(), std::forward(key), std::forward(value)); + } + + template + void traverse_set_deep(Key&& key, Keys&&... keys) const { + stack::get_field(base_t::lua_state(), std::forward(key)); + traverse_set_deep(std::forward(keys)...); + } + + basic_table_core(lua_State* L, detail::global_tag t) noexcept : base_t(L, t) { } + + protected: + basic_table_core(detail::no_safety_tag, lua_State* L, int index) : base_t(L, index) {} + basic_table_core(detail::no_safety_tag, lua_State* L, ref_index index) : base_t(L, index) {} + template , basic_table_core>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_table_core(detail::no_safety_tag, T&& r) noexcept : base_t(std::forward(r)) {} + + public: + typedef basic_table_iterator iterator; + typedef iterator const_iterator; + + basic_table_core() noexcept = default; + basic_table_core(const basic_table_core&) = default; + basic_table_core(basic_table_core&&) = default; + basic_table_core& operator=(const basic_table_core&) = default; + basic_table_core& operator=(basic_table_core&&) = default; + basic_table_core(const stack_reference& r) : basic_table_core(r.lua_state(), r.stack_index()) {} + basic_table_core(stack_reference&& r) : basic_table_core(r.lua_state(), r.stack_index()) {} + template >>, meta::neg, ref_index>>> = meta::enabler> + basic_table_core(lua_State* L, T&& r) : basic_table_core(L, sol::ref_index(r.registry_index())) {} + basic_table_core(lua_State* L, new_table nt) : base_t(L, (lua_createtable(L, nt.sequence_hint, nt.map_hint), -1)) { + if (!std::is_base_of::value) { + lua_pop(L, 1); + } + } + basic_table_core(lua_State* L, int index = -1) : basic_table_core(detail::no_safety, L, index) { +#ifdef SOL_CHECK_ARGUMENTS + stack::check(L, index, type_panic); +#endif // Safety + } + basic_table_core(lua_State* L, ref_index index) : basic_table_core(detail::no_safety, L, index) { +#ifdef SOL_CHECK_ARGUMENTS + auto pp = stack::push_pop(*this); + stack::check(L, -1, type_panic); +#endif // Safety + } + template , basic_table_core>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_table_core(T&& r) noexcept : basic_table_core(detail::no_safety, std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_table>::value) { + auto pp = stack::push_pop(*this); + stack::check(base_t::lua_state(), -1, type_panic); + } +#endif // Safety + } + + iterator begin() const { + return iterator(*this); + } + + iterator end() const { + return iterator(); + } + + const_iterator cbegin() const { + return begin(); + } + + const_iterator cend() const { + return end(); + } + + template + decltype(auto) get(Keys&&... keys) const { + static_assert(sizeof...(Keys) == sizeof...(Ret), "number of keys and number of return types do not match"); + auto pp = stack::push_pop::value>(*this); + return tuple_get(types(), std::make_index_sequence(), std::forward_as_tuple(std::forward(keys)...)); + } + + template + decltype(auto) get_or(Key&& key, T&& otherwise) const { + typedef decltype(get("")) U; + sol::optional option = get>(std::forward(key)); + if (option) { + return static_cast(option.value()); + } + return static_cast(std::forward(otherwise)); + } + + template + decltype(auto) get_or(Key&& key, D&& otherwise) const { + sol::optional option = get>(std::forward(key)); + if (option) { + return static_cast(option.value()); + } + return static_cast(std::forward(otherwise)); + } + + template + decltype(auto) traverse_get(Keys&&... keys) const { + auto pp = stack::push_pop::value>(*this); + return traverse_get_optional(meta::is_specialization_of>(), std::forward(keys)...); + } + + template + basic_table_core& traverse_set(Keys&&... keys) { + auto pp = stack::push_pop::value>(*this); + auto pn = stack::pop_n(base_t::lua_state(), static_cast(sizeof...(Keys)-2)); + traverse_set_deep(std::forward(keys)...); + return *this; + } + + template + basic_table_core& set(Args&&... args) { + tuple_set(std::make_index_sequence(), std::forward_as_tuple(std::forward(args)...)); + return *this; + } + + template + basic_table_core& set_usertype(usertype& user) { + return set_usertype(usertype_traits::name(), user); + } + + template + basic_table_core& set_usertype(Key&& key, usertype& user) { + return set(std::forward(key), user); + } + + template + basic_table_core& new_usertype(const std::string& name, Args&&... args) { + usertype utype(std::forward(args)...); + set_usertype(name, utype); + return *this; + } + + template + basic_table_core& new_usertype(const std::string& name, Args&&... args) { + constructors> ctor{}; + return new_usertype(name, ctor, std::forward(args)...); + } + + template + basic_table_core& new_usertype(const std::string& name, constructors ctor, Args&&... args) { + usertype utype(ctor, std::forward(args)...); + set_usertype(name, utype); + return *this; + } + + template + basic_table_core& new_simple_usertype(const std::string& name, Args&&... args) { + simple_usertype utype(base_t::lua_state(), std::forward(args)...); + set_usertype(name, utype); + return *this; + } + + template + basic_table_core& new_simple_usertype(const std::string& name, Args&&... args) { + constructors> ctor{}; + return new_simple_usertype(name, ctor, std::forward(args)...); + } + + template + basic_table_core& new_simple_usertype(const std::string& name, constructors ctor, Args&&... args) { + simple_usertype utype(base_t::lua_state(), ctor, std::forward(args)...); + set_usertype(name, utype); + return *this; + } + + template + simple_usertype create_simple_usertype(Args&&... args) { + simple_usertype utype(base_t::lua_state(), std::forward(args)...); + return utype; + } + + template + simple_usertype create_simple_usertype(Args&&... args) { + constructors> ctor{}; + return create_simple_usertype(ctor, std::forward(args)...); + } + + template + simple_usertype create_simple_usertype(constructors ctor, Args&&... args) { + simple_usertype utype(base_t::lua_state(), ctor, std::forward(args)...); + return utype; + } + + template + basic_table_core& new_enum(const std::string& name, Args&&... args) { + if (read_only) { + table idx = create_with(std::forward(args)...); + table x = create_with( + meta_function::new_index, detail::fail_on_newindex, + meta_function::index, idx + ); + table target = create_named(name); + target[metatable_key] = x; + } + else { + create_named(name, std::forward(args)...); + } + return *this; + } + + template + void for_each(Fx&& fx) const { + typedef meta::is_invokable)> is_paired; + for_each(is_paired(), std::forward(fx)); + } + + size_t size() const { + auto pp = stack::push_pop(*this); + lua_len(base_t::lua_state(), -1); + return stack::pop(base_t::lua_state()); + } + + bool empty() const { + return cbegin() == cend(); + } + + template + proxy operator[](T&& key) & { + return proxy(*this, std::forward(key)); + } + + template + proxy operator[](T&& key) const & { + return proxy(*this, std::forward(key)); + } + + template + proxy operator[](T&& key) && { + return proxy(*this, std::forward(key)); + } + + template + basic_table_core& set_function(Key&& key, Args&&... args) { + set_fx(types(), std::forward(key), std::forward(args)...); + return *this; + } + + template + basic_table_core& set_function(Key&& key, Args&&... args) { + set_fx(types<>(), std::forward(key), std::forward(args)...); + return *this; + } + + template + basic_table_core& add(Args&&... args) { + auto pp = stack::push_pop(*this); + (void)detail::swallow{0, + (stack::set_ref(base_t::lua_state(), std::forward(args)), 0)... + }; + return *this; + } + + private: + template> + void set_fx(types, Key&& key, Fx&& fx) { + set_resolved_function(std::forward(key), std::forward(fx)); + } + + template>> = meta::enabler> + void set_fx(types<>, Key&& key, Fx&& fx) { + set(std::forward(key), std::forward(fx)); + } + + template>> = meta::enabler> + void set_fx(types<>, Key&& key, Fx&& fx, Args&&... args) { + set(std::forward(key), as_function_reference(std::forward(fx), std::forward(args)...)); + } + + template + void set_resolved_function(Key&& key, Args&&... args) { + set(std::forward(key), as_function_reference>(std::forward(args)...)); + } + + public: + static inline table create(lua_State* L, int narr = 0, int nrec = 0) { + lua_createtable(L, narr, nrec); + table result(L); + lua_pop(L, 1); + return result; + } + + template + static inline table create(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + lua_createtable(L, narr, nrec); + table result(L); + result.set(std::forward(key), std::forward(value), std::forward(args)...); + lua_pop(L, 1); + return result; + } + + template + static inline table create_with(lua_State* L, Args&&... args) { + static_assert(sizeof...(Args) % 2 == 0, "You must have an even number of arguments for a key, value ... list."); + static const int narr = static_cast(meta::count_2_for_pack::value); + return create(L, narr, static_cast((sizeof...(Args) / 2) - narr), std::forward(args)...); + } + + table create(int narr = 0, int nrec = 0) { + return create(base_t::lua_state(), narr, nrec); + } + + template + table create(int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + return create(base_t::lua_state(), narr, nrec, std::forward(key), std::forward(value), std::forward(args)...); + } + + template + table create(Name&& name, int narr = 0, int nrec = 0) { + table x = create(base_t::lua_state(), narr, nrec); + this->set(std::forward(name), x); + return x; + } + + template + table create(Name&& name, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + table x = create(base_t::lua_state(), narr, nrec, std::forward(key), std::forward(value), std::forward(args)...); + this->set(std::forward(name), x); + return x; + } + + template + table create_with(Args&&... args) { + return create_with(base_t::lua_state(), std::forward(args)...); + } + + template + table create_named(Name&& name, Args&&... args) { + static const int narr = static_cast(meta::count_2_for_pack::value); + return create(std::forward(name), narr, sizeof...(Args) / 2 - narr, std::forward(args)...); + } + + ~basic_table_core() { + + } + }; +} // sol + +// end of sol/table_core.hpp + +namespace sol { + typedef table_core table; + + namespace stack { + template <> + struct getter { + static table get(lua_State* L, int index = -1) { + if (lua_getmetatable(L, index) == 0) { + return table(L, ref_index(LUA_REFNIL)); + } + return table(L, -1); + } + }; + } // stack +} // sol + +// end of sol/table.hpp + +// beginning of sol/environment.hpp + +namespace sol { + + template + struct basic_environment : basic_table { + private: + typedef basic_table base_t; + + public: + basic_environment() noexcept = default; + basic_environment(const basic_environment&) = default; + basic_environment(basic_environment&&) = default; + basic_environment& operator=(const basic_environment&) = default; + basic_environment& operator=(basic_environment&&) = default; + basic_environment(const stack_reference& r) : basic_environment(r.lua_state(), r.stack_index()) {} + basic_environment(stack_reference&& r) : basic_environment(r.lua_state(), r.stack_index()) {} + + basic_environment(lua_State* L, new_table nt) : base_t(L, std::move(nt)) {} + basic_environment(lua_State* L, new_table t, const reference& fallback) : basic_environment(L, std::move(t)) { + sol::stack_table mt(L, sol::new_table(0, 1)); + mt.set(sol::meta_function::index, fallback); + this->set(metatable_key, mt); + mt.pop(); + } + + basic_environment(env_t, const stack_reference& extraction_target) : base_t(detail::no_safety, extraction_target.lua_state(), (stack::push_environment_of(extraction_target), -1)) { +#ifdef SOL_CHECK_ARGUMENTS + stack::check(this->lua_state(), -1, type_panic); +#endif // Safety + lua_pop(this->lua_state(), 2); + } + basic_environment(env_t, const reference& extraction_target) : base_t(detail::no_safety, extraction_target.lua_state(), (stack::push_environment_of(extraction_target), -1)) { +#ifdef SOL_CHECK_ARGUMENTS + stack::check(this->lua_state(), -1, type_panic); +#endif // Safety + lua_pop(this->lua_state(), 2); + } + basic_environment(lua_State* L, int index = -1) : base_t(detail::no_safety, L, index) { +#ifdef SOL_CHECK_ARGUMENTS + stack::check(L, index, type_panic); +#endif // Safety + } + basic_environment(lua_State* L, ref_index index) : base_t(detail::no_safety, L, index) { +#ifdef SOL_CHECK_ARGUMENTS + auto pp = stack::push_pop(*this); + stack::check(L, -1, type_panic); +#endif // Safety + } + template , basic_environment>>, meta::neg>, std::is_base_of>> = meta::enabler> + basic_environment(T&& r) noexcept : base_t(detail::no_safety, std::forward(r)) { +#ifdef SOL_CHECK_ARGUMENTS + if (!is_environment>::value) { + auto pp = stack::push_pop(*this); + stack::check(base_t::lua_state(), -1, type_panic); + } +#endif // Safety + } + + template + void set_on(const T& target) const { + lua_State* L = target.lua_state(); + auto pp = stack::push_pop(target); +#if SOL_LUA_VERSION < 502 + // Use lua_setfenv + this->push(); + lua_setfenv(L, -2); +#else + // Use upvalues as explained in Lua 5.2 and beyond's manual + this->push(); + if (lua_setupvalue(L, -2, 1) == nullptr) { + this->pop(); + } +#endif + } + }; + + template + void set_environment(const basic_environment& env, const T& target) { + env.set_on(target); + } + + template + basic_environment get_environment(const T& target) { + lua_State* L = target.lua_state(); + auto pp = stack::pop_n(L, stack::push_environment_of(target)); + return basic_environment(L, -1); + } + + namespace stack { + template <> + struct getter { + static environment get(lua_State* L, int index = -1) { + return get_environment(stack_reference(L, raw_index(index))); + } + }; + } // stack +} // sol + +// end of sol/environment.hpp + +// beginning of sol/load_result.hpp + +namespace sol { + struct load_result : public proxy_base { + private: + lua_State* L; + int index; + int returncount; + int popcount; + load_status err; + + template + decltype(auto) tagged_get(types>) const { + if (!valid()) { + return sol::optional(nullopt); + } + return stack::get>(L, index); + } + + template + decltype(auto) tagged_get(types) const { +#ifdef SOL_CHECK_ARGUMENTS + if (!valid()) { + type_panic(L, index, type_of(L, index), type::none); + } +#endif // Check Argument Safety + return stack::get(L, index); + } + + sol::optional tagged_get(types>) const { + if (valid()) { + return nullopt; + } + return sol::error(detail::direct_error, stack::get(L, index)); + } + + sol::error tagged_get(types) const { +#ifdef SOL_CHECK_ARGUMENTS + if (valid()) { + type_panic(L, index, type_of(L, index), type::none); + } +#endif // Check Argument Safety + return sol::error(detail::direct_error, stack::get(L, index)); + } + + public: + load_result() = default; + load_result(lua_State* Ls, int stackindex = -1, int retnum = 0, int popnum = 0, load_status lerr = load_status::ok) noexcept : L(Ls), index(stackindex), returncount(retnum), popcount(popnum), err(lerr) { + + } + load_result(const load_result&) = default; + load_result& operator=(const load_result&) = default; + load_result(load_result&& o) noexcept : L(o.L), index(o.index), returncount(o.returncount), popcount(o.popcount), err(o.err) { + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but we will be thorough + o.L = nullptr; + o.index = 0; + o.returncount = 0; + o.popcount = 0; + o.err = load_status::syntax; + } + load_result& operator=(load_result&& o) noexcept { + L = o.L; + index = o.index; + returncount = o.returncount; + popcount = o.popcount; + err = o.err; + // Must be manual, otherwise destructor will screw us + // return count being 0 is enough to keep things clean + // but we will be thorough + o.L = nullptr; + o.index = 0; + o.returncount = 0; + o.popcount = 0; + o.err = load_status::syntax; + return *this; + } + + load_status status() const noexcept { + return err; + } + + bool valid() const noexcept { + return status() == load_status::ok; + } + + template + T get() const { + return tagged_get(types>()); + } + + template + decltype(auto) call(Args&&... args) { + return get().template call(std::forward(args)...); + } + + template + decltype(auto) operator()(Args&&... args) { + return call<>(std::forward(args)...); + } + + lua_State* lua_state() const noexcept { return L; }; + int stack_index() const noexcept { return index; }; + + ~load_result() { + stack::remove(L, index, popcount); + } + }; +} // sol + +// end of sol/load_result.hpp + +namespace sol { + enum class lib : char { + base, + package, + coroutine, + string, + os, + math, + table, + debug, + bit32, + io, + ffi, + jit, + utf8, + count + }; + + inline std::size_t total_memory_used(lua_State* L) { + std::size_t kb = lua_gc(L, LUA_GCCOUNT, 0); + kb *= 1024; + kb += lua_gc(L, LUA_GCCOUNTB, 0); + return kb; + } + + inline protected_function_result simple_on_error(lua_State*, sol::protected_function_result result) { + return result; + } + + inline protected_function_result default_on_error( lua_State* L, protected_function_result pfr ) { + type t = type_of(L, pfr.stack_index()); + std::string err = to_string(pfr.status()) + " error"; + if (t == type::string) { + err += " "; + err += stack::get(L, pfr.stack_index()); + } +#ifdef SOL_NO_EXCEPTIONS + if (t != type::nil) { + lua_pop(L, 1); + } + stack::push(L, err); + lua_error(L); +#else + throw error(detail::direct_error, err); +#endif + return pfr; + } + + class state_view { + private: + lua_State* L; + table reg; + global_table global; + + optional is_loaded_package(const std::string& key) { + auto loaded = reg.traverse_get>("_LOADED", key); + bool is53mod = loaded && !(loaded->is() && !loaded->as()); + if (is53mod) + return loaded; +#if SOL_LUA_VERSION <= 501 + auto loaded51 = global.traverse_get>("package", "loaded", key); + bool is51mod = loaded51 && !(loaded51->is() && !loaded51->as()); + if (is51mod) + return loaded51; +#endif + return nullopt; + } + + template + void ensure_package(const std::string& key, T&& sr) { +#if SOL_LUA_VERSION <= 501 + auto pkg = global["package"]; + if (!pkg.valid()) { + pkg = create_table_with("loaded", create_table_with(key, sr)); + } + else { + auto ld = pkg["loaded"]; + if (!ld.valid()) { + ld = create_table_with(key, sr); + } + else { + ld[key] = sr; + } + } +#endif + auto loaded = reg["_LOADED"]; + if (!loaded.valid()) { + loaded = create_table_with(key, sr); + } + else { + loaded[key] = sr; + } + } + + template + object require_core(const std::string& key, Fx&& action, bool create_global = true) { + optional loaded = is_loaded_package(key); + if (loaded && loaded->valid()) + return std::move(*loaded); + action(); + auto sr = stack::get(L); + if (create_global) + set(key, sr); + ensure_package(key, sr); + return stack::pop(L); + } + + public: + typedef global_table::iterator iterator; + typedef global_table::const_iterator const_iterator; + + state_view(lua_State* Ls) : + L(Ls), + reg(Ls, LUA_REGISTRYINDEX), + global(Ls, detail::global_) { + + } + + state_view(this_state Ls) : state_view(Ls.L){ + + } + + lua_State* lua_state() const { + return L; + } + + template + void open_libraries(Args&&... args) { + static_assert(meta::all_same::value, "all types must be libraries"); + if (sizeof...(args) == 0) { + luaL_openlibs(L); + return; + } + + lib libraries[1 + sizeof...(args)] = { lib::count, std::forward(args)... }; + + for (auto&& library : libraries) { + switch (library) { +#if SOL_LUA_VERSION <= 501 && defined(SOL_LUAJIT) + case lib::coroutine: +#endif // luajit opens coroutine base stuff + case lib::base: + luaL_requiref(L, "base", luaopen_base, 1); + lua_pop(L, 1); + break; + case lib::package: + luaL_requiref(L, "package", luaopen_package, 1); + lua_pop(L, 1); + break; +#if !defined(SOL_LUAJIT) + case lib::coroutine: +#if SOL_LUA_VERSION > 501 + luaL_requiref(L, "coroutine", luaopen_coroutine, 1); + lua_pop(L, 1); +#endif // Lua 5.2+ only + break; +#endif // Not LuaJIT - comes builtin + case lib::string: + luaL_requiref(L, "string", luaopen_string, 1); + lua_pop(L, 1); + break; + case lib::table: + luaL_requiref(L, "table", luaopen_table, 1); + lua_pop(L, 1); + break; + case lib::math: + luaL_requiref(L, "math", luaopen_math, 1); + lua_pop(L, 1); + break; + case lib::bit32: +#ifdef SOL_LUAJIT + luaL_requiref(L, "bit32", luaopen_bit, 1); + lua_pop(L, 1); +#elif (SOL_LUA_VERSION == 502) || defined(LUA_COMPAT_BITLIB) || defined(LUA_COMPAT_5_2) + luaL_requiref(L, "bit32", luaopen_bit32, 1); + lua_pop(L, 1); +#else +#endif // Lua 5.2 only (deprecated in 5.3 (503)) (Can be turned on with Compat flags) + break; + case lib::io: + luaL_requiref(L, "io", luaopen_io, 1); + lua_pop(L, 1); + break; + case lib::os: + luaL_requiref(L, "os", luaopen_os, 1); + lua_pop(L, 1); + break; + case lib::debug: + luaL_requiref(L, "debug", luaopen_debug, 1); + lua_pop(L, 1); + break; + case lib::utf8: +#if SOL_LUA_VERSION > 502 && !defined(SOL_LUAJIT) + luaL_requiref(L, "utf8", luaopen_utf8, 1); + lua_pop(L, 1); +#endif // Lua 5.3+ only + break; + case lib::ffi: +#ifdef SOL_LUAJIT + luaL_requiref(L, "ffi", luaopen_ffi, 1); + lua_pop(L, 1); +#endif // LuaJIT only + break; + case lib::jit: +#ifdef SOL_LUAJIT + luaL_requiref(L, "jit", luaopen_jit, 1); + lua_pop(L, 1); +#endif // LuaJIT Only + break; + case lib::count: + default: + break; + } + } + } + + object require(const std::string& key, lua_CFunction open_function, bool create_global = true) { + luaL_requiref(L, key.c_str(), open_function, create_global ? 1 : 0); + return stack::pop(L); + } + + object require_script(const std::string& key, const std::string& code, bool create_global = true) { + return require_core(key, [this, &code]() {stack::script(L, code); }, create_global); + } + + object require_file(const std::string& key, const std::string& filename, bool create_global = true) { + return require_core(key, [this, &filename]() {stack::script_file(L, filename); }, create_global); + } + + template + protected_function_result do_string(const std::string& code, const basic_environment& env) { + load_status x = static_cast(luaL_loadstring(L, code.c_str())); + if (x != load_status::ok) { + return protected_function_result(L, -1, 0, 1, static_cast(x)); + } + protected_function pf(L, -1); + pf.pop(); + set_environment(env, pf); + return pf(); + } + + template + protected_function_result do_file(const std::string& filename, const basic_environment& env) { + load_status x = static_cast(luaL_loadfile(L, filename.c_str())); + if (x != load_status::ok) { + return protected_function_result(L, -1, 0, 1, static_cast(x)); + } + protected_function pf(L, -1); + pf.pop(); + set_environment(env, pf); + return pf(); + } + + protected_function_result do_string(const std::string& code) { + load_status x = static_cast(luaL_loadstring(L, code.c_str())); + if (x != load_status::ok) { + return protected_function_result(L, -1, 0, 1, static_cast(x)); + } + protected_function pf(L, -1); + pf.pop(); + return pf(); + } + + protected_function_result do_file(const std::string& filename) { + load_status x = static_cast(luaL_loadfile(L, filename.c_str())); + if (x != load_status::ok) { + return protected_function_result(L, -1, 0, 1, static_cast(x)); + } + protected_function pf(L, -1); + pf.pop(); + return pf(); + } + + protected_function_result script(const std::string& code, const environment& env) { + return script(code, env, sol::default_on_error); + } + + protected_function_result script_file(const std::string& filename, const environment& env) { + return script_file(filename, env, sol::default_on_error); + } + + template >> = meta::enabler> + protected_function_result script(const std::string& code, Fx&& on_error) { + protected_function_result pfr = do_string(code); + if (!pfr.valid()) { + return on_error(L, std::move(pfr)); + } + return pfr; + } + + template >> = meta::enabler> + protected_function_result script_file(const std::string& filename, Fx&& on_error) { + protected_function_result pfr = do_file(filename); + if (!pfr.valid()) { + return on_error(L, std::move(pfr)); + } + return pfr; + } + + template + protected_function_result script(const std::string& code, const basic_environment& env, Fx&& on_error) { + protected_function_result pfr = do_string(code, env); + if (!pfr.valid()) { + return on_error(L, std::move(pfr)); + } + return pfr; + } + + template + protected_function_result script_file(const std::string& filename, const basic_environment& env, Fx&& on_error) { + protected_function_result pfr = do_file(filename, env); + if (!pfr.valid()) { + return on_error(L, std::move(pfr)); + } + return pfr; + } + + function_result script(const std::string& code) { + int index = lua_gettop(L); + stack::script(L, code); + int postindex = lua_gettop(L); + int returns = postindex - index; + return function_result(L, (std::max)(postindex - (returns - 1), 1), returns); + } + + function_result script_file(const std::string& filename) { + int index = lua_gettop(L); + stack::script_file(L, filename); + int postindex = lua_gettop(L); + int returns = postindex - index; + return function_result(L, (std::max)(postindex - (returns - 1), 1), returns); + } + + load_result load(const std::string& code) { + load_status x = static_cast(luaL_loadstring(L, code.c_str())); + return load_result(L, lua_absindex(L, -1), 1, 1, x); + } + + load_result load_file(const std::string& filename) { + load_status x = static_cast(luaL_loadfile(L, filename.c_str())); + return load_result(L, lua_absindex(L, -1), 1, 1, x); + } + + load_result load_buffer(const char *buff, size_t size, const char *name, const char* mode = nullptr) { + load_status x = static_cast(luaL_loadbufferx(L, buff, size, name, mode)); + return load_result(L, lua_absindex(L, -1), 1, 1, x); + } + + iterator begin() const { + return global.begin(); + } + + iterator end() const { + return global.end(); + } + + const_iterator cbegin() const { + return global.cbegin(); + } + + const_iterator cend() const { + return global.cend(); + } + + global_table globals() const { + return global; + } + + table registry() const { + return reg; + } + + std::size_t memory_used() const { + return total_memory_used(lua_state()); + } + + void collect_garbage() { + lua_gc(lua_state(), LUA_GCCOLLECT, 0); + } + + operator lua_State* () const { + return lua_state(); + } + + void set_panic(lua_CFunction panic) { + lua_atpanic(L, panic); + } + + template + decltype(auto) get(Keys&&... keys) const { + return global.get(std::forward(keys)...); + } + + template + decltype(auto) get_or(Key&& key, T&& otherwise) const { + return global.get_or(std::forward(key), std::forward(otherwise)); + } + + template + decltype(auto) get_or(Key&& key, D&& otherwise) const { + return global.get_or(std::forward(key), std::forward(otherwise)); + } + + template + state_view& set(Args&&... args) { + global.set(std::forward(args)...); + return *this; + } + + template + decltype(auto) traverse_get(Keys&&... keys) const { + return global.traverse_get(std::forward(keys)...); + } + + template + state_view& traverse_set(Args&&... args) { + global.traverse_set(std::forward(args)...); + return *this; + } + + template + state_view& set_usertype(usertype& user) { + return set_usertype(usertype_traits::name(), user); + } + + template + state_view& set_usertype(Key&& key, usertype& user) { + global.set_usertype(std::forward(key), user); + return *this; + } + + template + state_view& new_usertype(const std::string& name, Args&&... args) { + global.new_usertype(name, std::forward(args)...); + return *this; + } + + template + state_view& new_usertype(const std::string& name, Args&&... args) { + global.new_usertype(name, std::forward(args)...); + return *this; + } + + template + state_view& new_usertype(const std::string& name, constructors ctor, Args&&... args) { + global.new_usertype(name, ctor, std::forward(args)...); + return *this; + } + + template + state_view& new_simple_usertype(const std::string& name, Args&&... args) { + global.new_simple_usertype(name, std::forward(args)...); + return *this; + } + + template + state_view& new_simple_usertype(const std::string& name, Args&&... args) { + global.new_simple_usertype(name, std::forward(args)...); + return *this; + } + + template + state_view& new_simple_usertype(const std::string& name, constructors ctor, Args&&... args) { + global.new_simple_usertype(name, ctor, std::forward(args)...); + return *this; + } + + template + simple_usertype create_simple_usertype(Args&&... args) { + return global.create_simple_usertype(std::forward(args)...); + } + + template + simple_usertype create_simple_usertype(Args&&... args) { + return global.create_simple_usertype(std::forward(args)...); + } + + template + simple_usertype create_simple_usertype(constructors ctor, Args&&... args) { + return global.create_simple_usertype(ctor, std::forward(args)...); + } + + template + state_view& new_enum(const std::string& name, Args&&... args) { + global.new_enum(name, std::forward(args)...); + return *this; + } + + template + void for_each(Fx&& fx) { + global.for_each(std::forward(fx)); + } + + template + proxy operator[](T&& key) { + return global[std::forward(key)]; + } + + template + proxy operator[](T&& key) const { + return global[std::forward(key)]; + } + + template + state_view& set_function(Key&& key, Args&&... args) { + global.set_function(std::forward(key), std::forward(args)...); + return *this; + } + + template + state_view& set_function(Key&& key, Args&&... args) { + global.set_function(std::forward(key), std::forward(args)...); + return *this; + } + + template + table create_table(Name&& name, int narr = 0, int nrec = 0) { + return global.create(std::forward(name), narr, nrec); + } + + template + table create_table(Name&& name, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + return global.create(std::forward(name), narr, nrec, std::forward(key), std::forward(value), std::forward(args)...); + } + + template + table create_named_table(Name&& name, Args&&... args) { + table x = global.create_with(std::forward(args)...); + global.set(std::forward(name), x); + return x; + } + + table create_table(int narr = 0, int nrec = 0) { + return create_table(lua_state(), narr, nrec); + } + + template + table create_table(int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + return create_table(lua_state(), narr, nrec, std::forward(key), std::forward(value), std::forward(args)...); + } + + template + table create_table_with(Args&&... args) { + return create_table_with(lua_state(), std::forward(args)...); + } + + static inline table create_table(lua_State* L, int narr = 0, int nrec = 0) { + return global_table::create(L, narr, nrec); + } + + template + static inline table create_table(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + return global_table::create(L, narr, nrec, std::forward(key), std::forward(value), std::forward(args)...); + } + + template + static inline table create_table_with(lua_State* L, Args&&... args) { + return global_table::create_with(L, std::forward(args)...); + } + }; +} // sol + +// end of sol/state_view.hpp + +namespace sol { + inline int default_at_panic(lua_State* L) { +#ifdef SOL_NO_EXCEPTIONS + (void)L; + return -1; +#else + const char* message = lua_tostring(L, -1); + if (message) { + std::string err = message; + lua_settop(L, 0); + throw error(err); + } + lua_settop(L, 0); + throw error(std::string("An unexpected error occurred and forced the lua state to call atpanic")); +#endif + } + + inline int default_error_handler(lua_State*L) { + using namespace sol; + std::string msg = "An unknown error has triggered the default error handler"; + optional maybetopmsg = stack::check_get(L, 1); + if (maybetopmsg) { + const string_detail::string_shim& topmsg = maybetopmsg.value(); + msg.assign(topmsg.c_str(), topmsg.size()); + } + luaL_traceback(L, L, msg.c_str(), 1); + optional maybetraceback = stack::check_get(L, -1); + if (maybetraceback) { + const string_detail::string_shim& traceback = maybetraceback.value(); + msg.assign(traceback.c_str(), traceback.size()); + } + return stack::push(L, msg); + } + + class state : private std::unique_ptr, public state_view { + private: + typedef std::unique_ptr unique_base; + public: + state(lua_CFunction panic = default_at_panic) : unique_base(luaL_newstate(), lua_close), + state_view(unique_base::get()) { + set_panic(panic); + stack::luajit_exception_handler(unique_base::get()); + } + + state(lua_CFunction panic, lua_Alloc alfunc, void* alpointer = nullptr) : unique_base(lua_newstate(alfunc, alpointer), lua_close), + state_view(unique_base::get()) { + set_panic(panic); + sol::protected_function::set_default_handler(sol::object(lua_state(), in_place, default_error_handler)); + stack::luajit_exception_handler(unique_base::get()); + } + + state(const state&) = delete; + state(state&&) = default; + state& operator=(const state&) = delete; + state& operator=(state&& that) { + state_view::operator=(std::move(that)); + unique_base::operator=(std::move(that)); + return *this; + } + + using state_view::get; + + ~state() { + auto& handler = protected_function::get_default_handler(); + if (handler.lua_state() == this->lua_state()) { + protected_function::set_default_handler(reference()); + } + } + }; +} // sol + +// end of sol/state.hpp + +// beginning of sol/coroutine.hpp + +// beginning of sol/thread.hpp + +namespace sol { + struct lua_thread_state { + lua_State* L; + operator lua_State* () const { + return L; + } + lua_State* operator-> () const { + return L; + } + }; + + namespace stack { + + template <> + struct pusher { + int push(lua_State*, lua_thread_state lts) { + lua_pushthread(lts.L); + return 1; + } + }; + + template <> + struct getter { + lua_thread_state get(lua_State* L, int index, record& tracking) { + tracking.use(1); + lua_thread_state lts{ lua_tothread(L, index) }; + return lts; + } + }; + + template <> + struct check_getter { + template + optional get(lua_State* L, int index, Handler&& handler, record& tracking) { + lua_thread_state lts{ lua_tothread(L, index) }; + if (lts.L == nullptr) { + handler(L, index, type::thread, type_of(L, index)); + return nullopt; + } + tracking.use(1); + return lts; + } + }; + + } + +#if SOL_LUA_VERSION < 502 + inline lua_State* main_thread(lua_State*, lua_State* backup_if_unsupported = nullptr) { + return backup_if_unsupported; + } +#else + inline lua_State* main_thread(lua_State* L, lua_State* = nullptr) { + lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD); + lua_thread_state s = stack::pop(L); + return s.L; + } +#endif // Lua 5.2+ has the main thread getter + + class thread : public reference { + public: + thread() noexcept = default; + thread(const thread&) = default; + thread(thread&&) = default; + template , thread>>, std::is_base_of>> = meta::enabler> + thread(T&& r) : reference(std::forward(r)) {} + thread(const stack_reference& r) : thread(r.lua_state(), r.stack_index()) {}; + thread(stack_reference&& r) : thread(r.lua_state(), r.stack_index()) {}; + thread& operator=(const thread&) = default; + thread& operator=(thread&&) = default; + template >>, meta::neg>> = meta::enabler> + thread(lua_State* L, T&& r) : thread(L, sol::ref_index(r.registry_index())) {} + thread(lua_State* L, int index = -1) : reference(L, index) { +#ifdef SOL_CHECK_ARGUMENTS + type_assert(L, index, type::thread); +#endif // Safety + } + thread(lua_State* L, ref_index index) : reference(L, index) { +#ifdef SOL_CHECK_ARGUMENTS + auto pp = stack::push_pop(*this); + type_assert(L, -1, type::thread); +#endif // Safety + } + thread(lua_State* L, lua_State* actualthread) : thread(L, lua_thread_state{ actualthread }) {} + thread(lua_State* L, sol::this_state actualthread) : thread(L, lua_thread_state{ actualthread.L }) {} + thread(lua_State* L, lua_thread_state actualthread) : reference(L, -stack::push(L, actualthread)) { +#ifdef SOL_CHECK_ARGUMENTS + type_assert(L, -1, type::thread); +#endif // Safety + lua_pop(L, 1); + } + + state_view state() const { + return state_view(this->thread_state()); + } + + bool is_main_thread() const { + int ismainthread = lua_pushthread(this->thread_state()); + lua_pop(this->thread_state(), 1); + return ismainthread == 1; + } + + lua_State* thread_state() const { + auto pp = stack::push_pop(*this); + lua_State* lthread = lua_tothread(lua_state(), -1); + return lthread; + } + + thread_status status() const { + lua_State* lthread = thread_state(); + thread_status lstat = static_cast(lua_status(lthread)); + if (lstat != thread_status::ok && lua_gettop(lthread) == 0) { + // No thing on the thread's stack means its dead + return thread_status::dead; + } + return lstat; + } + + thread create() { + return create(lua_state()); + } + + static thread create(lua_State* L) { + lua_newthread(L); + thread result(L); + lua_pop(L, 1); + return result; + } + }; +} // sol + +// end of sol/thread.hpp + +namespace sol { + class coroutine : public reference { + private: + call_status stats = call_status::yielded; + + void luacall(std::ptrdiff_t argcount, std::ptrdiff_t) { +#if SOL_LUA_VERSION < 502 + stats = static_cast(lua_resume(lua_state(), static_cast(argcount))); +#else + stats = static_cast(lua_resume(lua_state(), nullptr, static_cast(argcount))); +#endif // Lua 5.1 compat + } + + template + auto invoke(types, std::index_sequence, std::ptrdiff_t n) { + luacall(n, sizeof...(Ret)); + return stack::pop>(lua_state()); + } + + template + Ret invoke(types, std::index_sequence, std::ptrdiff_t n) { + luacall(n, 1); + return stack::pop(lua_state()); + } + + template + void invoke(types, std::index_sequence, std::ptrdiff_t n) { + luacall(n, 0); + } + + protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n) { + int stacksize = lua_gettop(lua_state()); + int firstreturn = (std::max)(1, stacksize - static_cast(n)); + luacall(n, LUA_MULTRET); + int poststacksize = lua_gettop(lua_state()); + int returncount = poststacksize - (firstreturn - 1); + if (error()) { + return protected_function_result(lua_state(), lua_absindex(lua_state(), -1), 1, returncount, status()); + } + return protected_function_result(lua_state(), firstreturn, returncount, returncount, status()); + } + + public: + coroutine() noexcept = default; + coroutine(const coroutine&) noexcept = default; + coroutine(coroutine&&) noexcept = default; + coroutine& operator=(const coroutine&) noexcept = default; + coroutine& operator=(coroutine&&) noexcept = default; + template , coroutine>>, std::is_base_of>> = meta::enabler> + coroutine(T&& r) : reference(std::forward(r)) {} + coroutine(lua_nil_t r) : reference(r) {} + coroutine(const stack_reference& r) noexcept : coroutine(r.lua_state(), r.stack_index()) {} + coroutine(stack_reference&& r) noexcept : coroutine(r.lua_state(), r.stack_index()) {} + template >>, meta::neg>> = meta::enabler> + coroutine(lua_State* L, T&& r) : coroutine(L, sol::ref_index(r.registry_index())) {} + coroutine(lua_State* L, int index = -1) : reference(L, index) { +#ifdef SOL_CHECK_ARGUMENTS + stack::check(L, index, type_panic); +#endif // Safety + } + coroutine(lua_State* L, ref_index index) : reference(L, index) { +#ifdef SOL_CHECK_ARGUMENTS + auto pp = stack::push_pop(*this); + stack::check(L, -1, type_panic); +#endif // Safety + } + + call_status status() const noexcept { + return stats; + } + + bool error() const noexcept { + call_status cs = status(); + return cs != call_status::ok && cs != call_status::yielded; + } + + bool runnable() const noexcept { + return valid() + && (status() == call_status::yielded); + } + + explicit operator bool() const noexcept { + return runnable(); + } + + template + protected_function_result operator()(Args&&... args) { + return call<>(std::forward(args)...); + } + + template + decltype(auto) operator()(types, Args&&... args) { + return call(std::forward(args)...); + } + + template + decltype(auto) call(Args&&... args) { + push(); + int pushcount = stack::multi_push(lua_state(), std::forward(args)...); + return invoke(types(), std::make_index_sequence(), pushcount); + } + }; +} // sol + +// end of sol/coroutine.hpp + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#elif defined _MSC_VER +#pragma warning( push ) +#endif // g++ + +#ifdef SOL_INSIDE_UNREAL +#ifdef SOL_INSIDE_UNREAL_REMOVED_CHECK +#if DO_CHECK +#define check(expr) { if(UNLIKELY(!(expr))) { FDebug::LogAssertFailedMessage( #expr, __FILE__, __LINE__ ); _DebugBreakAndPromptForRemote(); FDebug::AssertFailed( #expr, __FILE__, __LINE__ ); CA_ASSUME(false); } } +#else +#define check(expr) { CA_ASSUME(expr); } +#endif +#endif +#endif // Unreal Engine 4 Bullshit + +#endif // SOL_HPP +// end of sol.hpp + +#endif // SOL_SINGLE_INCLUDE_HPP diff --git a/contrib/lua/sol_changes.txt b/contrib/lua/sol_changes.txt new file mode 100644 index 00000000000..10d9ec46afd --- /dev/null +++ b/contrib/lua/sol_changes.txt @@ -0,0 +1,8 @@ +In order to user sol with non-installed Lua version these changes are +required to the sol.hpp file: + +Around line 800 #include needs to be replaced with: +#ifndef lua_h +#include +#endif + diff --git a/contrib/luabind b/contrib/luabind deleted file mode 160000 index a0edf58e14c..00000000000 --- a/contrib/luabind +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a0edf58e14cfb8cd4f13779707921b5e9caf686c diff --git a/cpack/PackageProject.rb b/cpack/PackageProject.rb index 511efc1548d..8c3457793d7 100755 --- a/cpack/PackageProject.rb +++ b/cpack/PackageProject.rb @@ -31,6 +31,12 @@ def checkRunFolder(suggestedfolder) end end +def projectFolder(baseDir) + + return baseDir + +end + require_relative '../linux_setup/RubySetupSystem' Dir.chdir(CurrentDir) do @@ -63,8 +69,7 @@ def checkRunFolder(suggestedfolder) ZipName = "#{PackageName}.7z" # Add Ogre plugins to the library list -findOgrePlugins(LibraryList, ["RenderSystem_GL", "RenderSystem_GL3Plus", "Plugin_ParticleFX", - "Plugin_CgProgramManager"]) +findOgrePlugins(LibraryList, ["RenderSystem_GL", "RenderSystem_GL3Plus", "Plugin_ParticleFX"]) # Add CEGUI plugins to the list findCEGUIPlugins(LibraryList, CEGUIVersion) @@ -114,8 +119,7 @@ def checkRunFolder(suggestedfolder) # Find dependencies of dynamic Ogre libraries -lddfound = lddFindLibraries File.join(TargetRoot, "bin/Plugin_CgProgramManager.so") -lddfound += lddFindLibraries File.join(TargetRoot, "bin/Plugin_ParticleFX.so") +lddfound = lddFindLibraries File.join(TargetRoot, "bin/Plugin_ParticleFX.so") info "Copying #{lddfound.count} libraries found by ldd on random things" @@ -189,7 +193,7 @@ def checkRunFolder(suggestedfolder) # Plugin=RenderSystem_GLES # Plugin=RenderSystem_GLES2 Plugin=Plugin_ParticleFX - Plugin=Plugin_CgProgramManager +# Plugin=Plugin_CgProgramManager eos } diff --git a/linux_setup/RubySetupSystem.rb b/linux_setup/RubySetupSystem.rb index b1012b41acb..7f260d03294 100644 --- a/linux_setup/RubySetupSystem.rb +++ b/linux_setup/RubySetupSystem.rb @@ -2,9 +2,10 @@ # A ruby script for downloading and installing C++ project dependencies # Made by Henri Hyyryläinen -# TODO: remove awk usage for windows compatibility and test this on windows +# TODO: make cmake use extra find paths on windows and test require_relative 'RubyCommon.rb' +require_relative 'DepGlobber.rb' require 'fileutils' require 'etc' @@ -22,6 +23,7 @@ CompileThreads = Etc.nprocessors # If set to true will install CEGUI editor +# Note: this doesn't work InstallCEED = false # If set to false won't install libs that need sudo @@ -36,6 +38,9 @@ # If true skips the main project OnlyDependencies = false +# If true new version of depot tools and breakpad won't be fetched on install +NoBreakpadUpdateOnWindows = false + # On windows visual studio will be automatically opened if required AutoOpenVS = true @@ -52,6 +57,17 @@ # This verifies that CurrentDir is good and assigns it to CurrentDir CurrentDir = checkRunFolder Dir.pwd +ProjectDir = projectFolder CurrentDir + +ProjectDebDir = File.join ProjectDir, "libraries" + +ProjectDebDirLibs = File.join ProjectDebDir, "lib" + +ProjectDebDirBinaries = File.join ProjectDebDir, "bin" + +ProjectDebDirInclude = File.join ProjectDebDir, "include" + + info "Running in dir '#{CurrentDir}'" @@ -88,7 +104,7 @@ def addLibrary(lib) # calls onError if fails def run() - if not SkipPullUpdates + if not SkipPullUpdates and not OnlyMainProject info "Retrieving dependencies" @Libraries.each do |x| @@ -304,6 +320,15 @@ def isInSubdirectory(directory, possiblesub) end +def createDependencyTargetFolder() + + FileUtils.mkdir_p ProjectDebDirLibs + + FileUtils.mkdir_p ProjectDebDirBinaries + + FileUtils.mkdir_p ProjectDebDirInclude + +end def createLinkIfDoesntExist(source, linkfile) @@ -608,8 +633,10 @@ def lddFindLibraries(binary) end +# #### Library Install Definitions ### # These are all the libraries that this script can install +# class Newton < BaseDep def initialize @@ -660,27 +687,27 @@ def DoCompile end def DoInstall - # Copy files to Leviathan folder - libfolder = File.join(CurrentDir, "Newton", "lib") - binfolder = File.join(CurrentDir, "Newton", "bin") - includefolder = File.join(CurrentDir, "Newton", "include") - FileUtils.mkdir_p libfolder - FileUtils.mkdir_p binfolder - FileUtils.mkdir_p includefolder + # Copy files to ProjectDir dependencies folder + createDependencyTargetFolder - FileUtils.cp File.join(@Folder, "coreLibrary_300/source/newton", "Newton.h"), includefolder + runGlobberAndCopy(Globber.new("Newton.h", File.join(@Folder, "coreLibrary_300/source")), + ProjectDebDirInclude) if BuildPlatform == "linux" - FileUtils.cp File.join(@Folder, "build/lib", "libNewton.so"), binfolder - + runGlobberAndCopy(Globber.new("libNewton.so", File.join(@Folder, "build/lib")), + ProjectDebDirLibs) + else - - basePath = "coreLibrary_300/projects/windows/project_vs2015_dll/x64/newton/release" - - FileUtils.cp File.join(@Folder, basePath, "newton.dll"), binfolder - FileUtils.cp File.join(@Folder, basePath, "newton.lib"), libfolder + + runGlobberAndCopy(Globber.new("newton.dll", + File.join(@Folder, "coreLibrary_300/projects/windows")), + ProjectDebDirBinaries) + + runGlobberAndCopy(Globber.new("newton.lib", + File.join(@Folder, "coreLibrary_300/projects/windows")), + ProjectDebDirLibs) end true end @@ -817,7 +844,7 @@ def DoInstall class AngelScript < BaseDep def initialize super("AngelScript", "angelscript") - @WantedURL = "http://svn.code.sf.net/p/angelscript/code/tags/2.31.0" + @WantedURL = "http://svn.code.sf.net/p/angelscript/code/tags/2.31.2" if @WantedURL[-1, 1] == '/' abort "Invalid configuraion in Setup.rb AngelScript tag has an ending '/'. Remove it!" @@ -832,7 +859,11 @@ def DoClone def DoUpdate # Check is tag correct - currenturl = `svn info | awk '$1 == "URL:" { print $2 }'`.strip! + match = `svn info`.strip.match(/.*URL:\s?(.*angelscript\S+).*/i) + + abort("'svn info' unable to find URL with regex") if !match + + currenturl = match.captures[0] if currenturl != @WantedURL @@ -847,7 +878,7 @@ def DoUpdate end def DoSetup - if BuildPlatform == "linux" + if BuildPlatform == "windows" return File.exist? "sdk/angelscript/projects/msvc2015/angelscript.sln" else @@ -881,16 +912,16 @@ def DoCompile def DoInstall - # Copy files to Leviathan folder - FileUtils.mkdir_p File.join(CurrentDir, "AngelScript", "include") - FileUtils.mkdir_p File.join(CurrentDir, "AngelScript", "add_on") - + # Copy files to Project folder + createDependencyTargetFolder + # First header files and addons FileUtils.cp File.join(@Folder, "sdk/angelscript/include", "angelscript.h"), - File.join(CurrentDir, "AngelScript", "include") + ProjectDebDirInclude - addondir = File.join(CurrentDir, "AngelScript", "add_on") + addondir = File.join(ProjectDebDirInclude, "add_on") + FileUtils.mkdir_p addondir # All the addons from # `ls -m | awk 'BEGIN { RS = ","; ORS = ", "}; NF { print "\""$1"\""};'` @@ -906,18 +937,15 @@ def DoInstall File.join(addondir, x) end - # Then the library - libfolder = File.join(CurrentDir, "AngelScript", "lib") - - FileUtils.mkdir_p libfolder - if BuildPlatform == "linux" - FileUtils.cp File.join(@Folder, "sdk/angelscript/lib", "libangelscript.a"), libfolder + FileUtils.cp File.join(@Folder, "sdk/angelscript/lib", "libangelscript.a"), + ProjectDebDirLibs else - FileUtils.cp File.join(@Folder, "sdk/angelscript/lib", "angelscript64.lib"), libfolder + FileUtils.cp File.join(@Folder, "sdk/angelscript/lib", "angelscript64.lib"), + ProjectDebDirLibs end true end @@ -1191,7 +1219,7 @@ def DoSetup "-DOGRE_BUILD_COMPONENT_OVERLAY=OFF " + "-DOGRE_BUILD_COMPONENT_PAGING=OFF -DOGRE_BUILD_COMPONENT_PROPERTY=OFF " + "-DOGRE_BUILD_COMPONENT_TERRAIN=OFF -DOGRE_BUILD_COMPONENT_VOLUME=OFF "+ - "-DOGRE_BUILD_PLUGIN_BSP=OFF -DOGRE_BUILD_PLUGIN_CG=ON " + + "-DOGRE_BUILD_PLUGIN_BSP=OFF -DOGRE_BUILD_PLUGIN_CG=OFF " + "-DOGRE_BUILD_PLUGIN_OCTREE=OFF -DOGRE_BUILD_PLUGIN_PCZ=OFF -DOGRE_BUILD_SAMPLES=OFF " + additionalCMake end @@ -1300,7 +1328,7 @@ def DoUpdate #system "hg update default" # TODO: allow configuring this commit - system "hg update 869014de5669" + system "hg update 6510156" $?.exitstatus == 0 end @@ -1432,6 +1460,8 @@ def isGoodLDDFound(lib) true when /.*swscale.*/i true + when /.*rtmp.*/i + true when /.*gsm.*/i true when /.*soxr.*/i @@ -1509,6 +1539,12 @@ def isGoodLDDFound(lib) true when /.*Xaw.*/i true + when /.*numa.*/i + true + when /.*hogweed.*/i + true + when /.*jasper.*/i + true else false end diff --git a/linux_setup/RunCodeIndexing.rb b/linux_setup/RunCodeIndexing.rb new file mode 100755 index 00000000000..0737a7a3fe4 --- /dev/null +++ b/linux_setup/RunCodeIndexing.rb @@ -0,0 +1,26 @@ +#!/usr/bin/env ruby + +require 'find' + + +if File.exists? "src" + runFolder = "." +else + runFolder = "../" +end + +Dir.chdir(runFolder){ + + file_paths = [] + Find.find('.') do |path| + file_paths << path if (not path =~ /.*\/contrib\/.*/) and + (not path =~ /.*\/build\/.*/) and ((path =~ /.*\.h/) or + (path =~ /.*\.cpp/)) + end + + File.open("cscope.files", "w") do |f| + f.puts(file_paths) + end + + system "cscope -b" +} diff --git a/mingw_setup/boost/install.ps1 b/mingw_setup/boost/install.ps1 index 7eec842fb15..d684ca43487 100644 --- a/mingw_setup/boost/install.ps1 +++ b/mingw_setup/boost/install.ps1 @@ -42,9 +42,9 @@ if (-Not (Get-Command $7z -errorAction SilentlyContinue)) # Download archive # #################### -$REMOTE_DIR="http://downloads.sourceforge.net/project/boost/boost/1.53.0" +$REMOTE_DIR="http://downloads.sourceforge.net/project/boost/boost/1.63.0" -$ARCHIVE="boost_1_53_0.7z" +$ARCHIVE="boost_1_63_0.7z" $DESTINATION = Join-Path $WORKING_DIR $ARCHIVE @@ -72,42 +72,6 @@ $ARGUMENTS = "x", & $7z $ARGUMENTS | out-null -################## -# Download tools # -################## - -$TOOLS_REMOTE_DIR="http://downloads.sourceforge.net/project/boost/boost-binaries/1.50.0" - -$TOOLS_ARCHIVE="boost_1_50_tools.zip" - -$TOOLS_DESTINATION = Join-Path $WORKING_DIR $TOOLS_ARCHIVE - -if (-Not (Test-Path $TOOLS_DESTINATION)) { - Write-Output "Downloading tools..." - $CLIENT = New-Object System.Net.WebClient - $CLIENT.DownloadFile("$TOOLS_REMOTE_DIR/$TOOLS_ARCHIVE", $TOOLS_DESTINATION) -} -else { - Write-Output "Found tools archive file, skipping download." -} - - -################ -# Unpack tools # -################ - -Write-Output "Unpacking tools..." - -$ARGUMENTS = "x", - "-y", - "-o$WORKING_DIR\tools", - $TOOLS_DESTINATION - -& $7z $ARGUMENTS | out-null - -Copy-Item (Join-Path $WORKING_DIR "tools\bin\bjam.exe") -destination (Join-Path $WORKING_DIR "boost_1_53_0\bjam.exe") - - ############################################# # Create user config for boost build system # ############################################# @@ -115,7 +79,7 @@ Copy-Item (Join-Path $WORKING_DIR "tools\bin\bjam.exe") -destination (Join-Path $MINGW_BIN_DIR = (Join-Path $MINGW_ENV bin).replace("\", "\\") $USER_CONFIG = " -using gcc : 4.7 : $MINGW_BIN_DIR\\g++.exe +using gcc : 5.4 : $MINGW_BIN_DIR\\g++.exe : $MINGW_BIN_DIR\\windres.exe $MINGW_BIN_DIR\\ar.exe @@ -131,7 +95,14 @@ Set-Content $USER_CONFIG_FILE $USER_CONFIG # Build # ######### -pushd (Join-Path $WORKING_DIR "boost_1_53_0") +pushd (Join-Path $WORKING_DIR "boost_1_63_0\tools\build") + +Write-Output "Running bootstrap to generate build tool b2..." +& .\bootstrap.bat + + +Write-Output "Building boost.build..." +& .\b2 install --prefix=$WORKING_DIR\boostbuild Write-Output "Building libraries..." @@ -153,6 +124,13 @@ $ARGUMENTS = "--layout=tagged", "install" -& .\bjam $ARGUMENTS +& .\b2 $ARGUMENTS + +Write-Output "Copying header files..." + +#I desperately tried using Copy-Item to copy header files but every attempt always failed to copy everything so I'm calling an xcopy +$cmd = "xcopy `$WORKING_DIR\boost_1_63_0\boost\*` `$MINGW_ENV\install\include\boost\*` /s/h/e/k/f/c" +$cmd = $ExecutionContext.InvokeCommand.ExpandString($cmd) +cmd.exe /c $cmd popd diff --git a/mingw_setup/cAudio/install.ps1 b/mingw_setup/cAudio/install.ps1 index 674f64084c6..0c576e7abaa 100644 --- a/mingw_setup/cAudio/install.ps1 +++ b/mingw_setup/cAudio/install.ps1 @@ -74,6 +74,12 @@ $ARGUMENTS = "x", & $7z $ARGUMENTS | out-null +(Get-Content $WORKING_DIR/cAudio-5c932101891e4e63b93b03803d34342fbdb9f0a3/cAudio/include/cAudioString.h) | +Foreach-Object {$_ -replace '1023, 0, false',' 1023, 0, (int)false'} | +Out-File -Encoding "UTF8" $WORKING_DIR/cAudio-5c932101891e4e63b93b03803d34342fbdb9f0a3/cAudio/include/cAudioString.h + + + ########### # Compile # ########### diff --git a/mingw_setup/cegui/install.ps1 b/mingw_setup/cegui/install.ps1 index c30aea32906..b5933783c98 100644 --- a/mingw_setup/cegui/install.ps1 +++ b/mingw_setup/cegui/install.ps1 @@ -131,7 +131,7 @@ foreach ($BUILD_TYPE in $BUILD_TYPES) { "-DCEGUI_TINYXML_HAS_2_6_API:bool=TRUE", "-DTINYXML_H_PATH:path=$MINGW_ENV/install/include/tinyxml", # -"DBoost_INCLUDE_DIR:path=$MINGW_ENV/install/include/boost", - "-DTINYXML_LIB_DBG:filepath=$MINGW_ENV/install/lib/libtinyxml.a", #This should be $MINGW_ENV/install... but that causes strange error. + "-DTINYXML_LIB_DBG:filepath=$MINGW_ENV/install/lib/libtinyxml.a", "$LIB_SRC" Write-Output $MINGW_ENV/install/lib/libtinyxml.a diff --git a/mingw_setup/luajit/install.ps1 b/mingw_setup/luajit/install.ps1 new file mode 100644 index 00000000000..fb836c8f132 --- /dev/null +++ b/mingw_setup/luajit/install.ps1 @@ -0,0 +1,50 @@ +param( + [string]$MINGW_ENV +) + +########## +# FFMPEG # +########## + +Write-Output "--- Installing luajit ---" + +$DIR = Split-Path $MyInvocation.MyCommand.Path + +################# +# Include utils # +################# + +. (Join-Path "$DIR\.." "utils.ps1") + +############################ +# Create working directory # +############################ + +$WORKING_DIR = "$DIR\..\..\contrib\lua\luajit" + +mkdir $WORKING_DIR -force | out-null + + +########### +# Compile # +########### + +Write-Output "Compiling..." + + + + + + +#$BUILD_DIR = Join-Path $WORKING_DIR "build-$BUILD_TYPE" +pushd $WORKING_DIR + +$env:Path += ";${MINGW_ENV}/bin" + + + +& $MINGW_ENV/bin/mingw32-make -j4 all | Tee-Object -FilePath compileroutput.txt +popd + + + diff --git a/mingw_setup/mingw/install.ps1 b/mingw_setup/mingw/install.ps1 index 0ccef785e3a..9d03d6e10cf 100644 --- a/mingw_setup/mingw/install.ps1 +++ b/mingw_setup/mingw/install.ps1 @@ -41,8 +41,10 @@ if (-Not (Get-Command $7z -errorAction SilentlyContinue)) # Download archive # #################### -$REMOTE_DIR="http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/4.8.5/threads-win32/dwarf/" -$ARCHIVE="i686-4.8.5-release-win32-dwarf-rt_v4-rev0.7z" +##$REMOTE_DIR="https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/4.9.3/threads-win32/dwarf/" +##$ARCHIVE="i686-4.9.3-release-win32-dwarf-rt_v4-rev1.7z" +$REMOTE_DIR="https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/5.4.0/threads-win32/dwarf/" +$ARCHIVE="i686-5.4.0-release-win32-dwarf-rt_v5-rev0.7z" $DESTINATION = Join-Path $WORKING_DIR $ARCHIVE diff --git a/mingw_setup/ogre/install.ps1 b/mingw_setup/ogre/install.ps1 index 83dbb7d9248..d8dc63e743a 100644 --- a/mingw_setup/ogre/install.ps1 +++ b/mingw_setup/ogre/install.ps1 @@ -47,8 +47,8 @@ $REPOSITORY_NAME="sinbad" $REMOTE_DIR="https://bitbucket.org/sinbad/ogre/get" - -$COMMIT_ID="9fba1c8ac0be" + +$COMMIT_ID="b6eeaf8a7c5d" $ARCHIVE="$COMMIT_ID.zip" @@ -79,7 +79,7 @@ $ARGUMENTS = "x", "-o$WORKING_DIR", $DESTINATION -& $7z $ARGUMENTS | out-null +#& $7z $ARGUMENTS | out-null ########### @@ -116,7 +116,7 @@ foreach ($BUILD_TYPE in $BUILD_TYPES) { "-DOGRE_BUILD_RENDERSYSTEM_D3D11=OFF", "-DOGRE_BUILD_SAMPLES=OFF", "-DOGRE_BUILD_TOOLS=OFF", - "-DCMAKE_CXX_FLAGS:string=-mstackrealign -msse2 -std=c++0x", + "-DCMAKE_CXX_FLAGS:string=-mstackrealign -std=c++1y", "-DDirectX_DXERR_LIBRARY=$MINGW_ENV/x86_64-mingw32/lib/libdxerr9.a", "$WORKING_DIR/sinbad-ogre-$COMMIT_ID" diff --git a/mingw_setup/ogre_dependencies/install.ps1 b/mingw_setup/ogre_dependencies/install.ps1 index f92bcb92a4c..8aba6a51530 100644 --- a/mingw_setup/ogre_dependencies/install.ps1 +++ b/mingw_setup/ogre_dependencies/install.ps1 @@ -98,6 +98,7 @@ foreach ($BUILD_TYPE in $BUILD_TYPES) { $ARGUMENTS = "-DCMAKE_PROGRAM_PATH=$MINGW_ENV/bin/", + "-DCMAKE_CXX_FLAGS:string=-Wno-narrowing", "-DCMAKE_TOOLCHAIN_FILE=$TOOLCHAIN_FILE", "-DCMAKE_INSTALL_PREFIX=$MINGW_ENV/install", "-DCMAKE_C_FLAGS=-shared-libgcc", diff --git a/mingw_setup/setup.ps1 b/mingw_setup/setup.ps1 index 0673ea052e2..0fc2bfde0c8 100644 --- a/mingw_setup/setup.ps1 +++ b/mingw_setup/setup.ps1 @@ -34,14 +34,15 @@ If ([string]::IsNullOrEmpty($MINGW_ENV)) { mkdir (Join-Path $MINGW_ENV cmake) -force | out-null mkdir (Join-Path $MINGW_ENV install) -force | out-null - - +mkdir (Join-Path $MINGW_ENV\install bin) -force | out-null +mkdir (Join-Path $MINGW_ENV\install\bin Release) -force +mkdir (Join-Path $MINGW_ENV\install\bin Debug) -force ##################### # Install libraries # ##################### -# -$LIBRARIES = $LIBRARIES = "7zip","cmake", "mingw", "boost", "ogre_dependencies", "ogre", "bullet", "ogg", "vorbis", "OpenAl", "TinyXML", "cegui_dependencies", "cegui","cAudio", "ffmpeg" + +$LIBRARIES = $LIBRARIES = "7zip","cmake", "mingw", "boost", "ogre_dependencies", "ogre", "bullet", "ogg", "vorbis", "OpenAl", "TinyXML", "cegui_dependencies", "cegui","cAudio", "ffmpeg", "luajit" foreach ($LIBRARY in $LIBRARIES) { $INSTALL_SCRIPT = Join-Path $DIR (Join-Path $LIBRARY install.ps1) & $INSTALL_SCRIPT $MINGW_ENV diff --git a/scripts/class.lua b/scripts/class.lua new file mode 100644 index 00000000000..49b95907df2 --- /dev/null +++ b/scripts/class.lua @@ -0,0 +1,101 @@ +-- Class creation functions + +-- see: http://lua-users.org/wiki/SimpleLuaClasses +-- Modified to use .new for instantiating classes to be consistent with C++ classes +function class(base, create) + local c = {} -- a new class instance + if not create and type(base) == 'function' then + create = base + base = nil + elseif type(base) == 'table' then + -- our new class is a shallow copy of the base class! + for i,v in pairs(base) do + c[i] = v + end + c._base = base + else + error("class base is not a table or a constructor") + end + -- the class will be the metatable for all its objects, + -- and they will look up their methods in it. + c.__index = c + + -- expose a constructor + local mt = {} + c.new = function(...) + local obj = {} + setmetatable(obj, c) + if create then + -- The create method must explicitly call base create + create(obj,...) + else + -- make sure that any stuff from the base class is createialized! + if base and base.create then + base.create(obj, ...) + end + end + return obj + end + + -- Expose a table call constructor + mt.__call = function(class_tbl, ...) + + return class_tbl.new(...) + + end + + c.create = create + c.is_a = function(self, klass) + local m = getmetatable(self) + while m do + if m == klass then return true end + m = m._base + end + return false + end + setmetatable(c, mt) + return c +end + + + + + +-- Helper file for creating Lua classes that inherit from C++ classes +-- Creates a subclass of a C++ class +function createSubclass(baseClass) + + error("todo: fix this") + + assert(baseClass ~= nil, "tried to create subclass of nil") + + local newClass = {} + + local metaTable = { __index = newClass } + + -- Helper for creating instances + -- arg must be a table of values to pass to base class or nil + function newClass._createInstance(arg) + + -- Create base object first + if arg ~= nil then + local baseInstance = baseClass.new(unpack(arg)) + else + local baseInstance = baseClass.new() + end + + local newinst = {} + setmetatable(newinst, metaTable) + + -- Attach to the base class + setmetatable(newinst, { __index = baseInstance }) + + newinst["_asBase"] = baseInstance + + return newinst + end + + return newClass +end + + diff --git a/scripts/colours.lua b/scripts/colours.lua index 947536df60b..371e26dea28 100644 --- a/scripts/colours.lua +++ b/scripts/colours.lua @@ -12,9 +12,10 @@ local COLOURS = { Blue = {0.0, 0.0, 1.0, 1.0}, } --- Put the above defined colours into the ColourValue class object +-- Put the above defined colours into COLOURS table +COLOURS = {} for name, components in pairs(COLOURS) do - ColourValue[name] = ColourValue( + COLOURS[name] = ColourValue.new( components[1], components[2], components[3], diff --git a/scripts/console.lua b/scripts/console.lua index e61c3c4afe9..7d0c015a227 100644 --- a/scripts/console.lua +++ b/scripts/console.lua @@ -8,18 +8,16 @@ -- will try to print out tables recursively, subject to the pretty_print_limit value. -- Steve Donovan, 2007 ---------------------- - -class "ConsoleHud" -class "Interpreter" - require "string" -function ConsoleHud:__init(interpreter) - self.active = false - self.interpreter = interpreter - self.inputHistory = {} - self.inputHistoryIndex = 0 -end +ConsoleHud = class( + function(self, interpreter) + self.active = false + self.interpreter = interpreter + self.inputHistory = {} + self.inputHistoryIndex = 0 + end +) function ConsoleHud:registerEvents(gameState) local root = gameState:rootGUIWindow() @@ -31,11 +29,11 @@ function ConsoleHud:registerEvents(gameState) end function ConsoleHud:update() - local gameState = Engine:currentGameState() - local root = gameState:rootGUIWindow() + local gameState = g_luaEngine.currentGameState + local root = gameState.guiWindow local consoleWindow = root:getChild("ConsoleWindow") local inputArea = consoleWindow:getChild("TextEntry") - if Engine.keyboard:wasKeyPressed(Keyboard.KC_F11) then + if Engine.keyboard:wasKeyPressed(KEYCODE.KC_F11) then self.active = not self.active if self.active then consoleWindow:show() @@ -50,7 +48,7 @@ function ConsoleHud:update() consoleWindow:hide() end elseif self.active then - if Engine.keyboard:wasKeyPressed(Keyboard.KC_RETURN) then + if Engine.keyboard:wasKeyPressed(KEYCODE.KC_RETURN) then -- push line to interpreter local outputArea = consoleWindow:getChild("History") local line = inputArea:getText() @@ -60,10 +58,10 @@ function ConsoleHud:update() self.inputHistoryIndex = #self.inputHistory self.inputHistory[self.inputHistoryIndex + 1] = line self.inputHistoryIndex = self.inputHistoryIndex + 1 - elseif Engine.keyboard:wasKeyPressed(Keyboard.KC_UP) and self.inputHistoryIndex > 0 then + elseif Engine.keyboard:wasKeyPressed(KEYCODE.KC_UP) and self.inputHistoryIndex > 0 then self.inputHistoryIndex = self.inputHistoryIndex - 1 inputArea:setText(self.inputHistory[self.inputHistoryIndex + 1]) - elseif Engine.keyboard:wasKeyPressed(Keyboard.KC_DOWN) and self.inputHistoryIndex < #self.inputHistory - 1 then + elseif Engine.keyboard:wasKeyPressed(KEYCODE.KC_DOWN) and self.inputHistoryIndex < #self.inputHistory - 1 then self.inputHistoryIndex = self.inputHistoryIndex + 1 inputArea:setText(self.inputHistory[self.inputHistoryIndex + 1]) end @@ -73,8 +71,8 @@ end function ConsoleHud:eval() -- push line to interpreter if not self.active then return end - local gameState = Engine:currentGameState() - local consoleWindow = gameState:rootGUIWindow():getChild("ConsoleWindow") + local gameState = g_luaEngine.currentGameState + local consoleWindow = gameState.guiWindow:getChild("ConsoleWindow") local inputArea = consoleWindow:getChild("TextEntry") local outputArea = consoleWindow:getChild("History") local line = inputArea:getText() @@ -87,9 +85,9 @@ function ConsoleHud:eval() end function ConsoleHud:handleKeys(key) - local consoleWindow = Engine:currentGameState():rootGUIWindow():getChild("ConsoleWindow") + local consoleWindow = g_luaEngine.currentGameState.guiWindow:getChild("ConsoleWindow") local inputArea = consoleWindow:getChild("TextEntry") - if key == Keyboard.KC_F11 then + if key == KEYCODE.KC_F11 then if self.active then consoleWindow:disable() consoleWindow:hide() @@ -98,113 +96,116 @@ function ConsoleHud:handleKeys(key) end end -function Interpreter:__init() - self.pretty_print_limit = 20 - self.max_depth = 7 - self.table_clever = true - self.prompt = '> ' - self.verbose = false - self.strict = false - -- suppress strict warnings - _ = true - - -- imported global functions - self.sub = string.sub - self.match = string.match - self.find = string.find - self.push = table.insert - self.pop = table.remove - self.append = table.insert - self.concat = table.concat - self.floor = math.floor - self.write = io.write - self.read = io.read - - self.savef = nil - self.collisions = {} - self.G_LIB = {} - self.declared = {} - self.line_handler_fn = nil - self.global_handler_fn = nil - self.print_handlers = {} - - self.ilua = {} - self.num_prec = nil - self.num_all = nil - - self.jstack = {} - - self.history = "" - - -- functions available in scripts - function self.ilua.precision(len,prec,all) - if not len then num_prec = nil - else - num_prec = '%'..len..'.'..prec..'f' - end - num_all = all - end +Interpreter = class( + function(self) + + self.pretty_print_limit = 20 + self.max_depth = 7 + self.table_clever = true + self.prompt = '> ' + self.verbose = false + self.strict = false + -- suppress strict warnings + _ = true + + -- imported global functions + self.sub = string.sub + self.match = string.match + self.find = string.find + self.push = table.insert + self.pop = table.remove + self.append = table.insert + self.concat = table.concat + self.floor = math.floor + self.write = io.write + self.read = io.read + + self.savef = nil + self.collisions = {} + self.G_LIB = {} + self.declared = {} + self.line_handler_fn = nil + self.global_handler_fn = nil + self.print_handlers = {} + + self.ilua = {} + self.num_prec = nil + self.num_all = nil + + self.jstack = {} + + self.history = "" + + -- functions available in scripts + function self.ilua.precision(len,prec,all) + if not len then num_prec = nil + else + num_prec = '%'..len..'.'..prec..'f' + end + num_all = all + end - function self.ilua.table_options(t) - if t.limit then self.pretty_print_limit = t.limit end - if t.depth then self.max_depth = t.depth end - if t.clever ~= nil then self.table_clever = t.clever end - end + function self.ilua.table_options(t) + if t.limit then self.pretty_print_limit = t.limit end + if t.depth then self.max_depth = t.depth end + if t.clever ~= nil then self.table_clever = t.clever end + end - -- inject @tbl into the global namespace - function self.ilua.import(tbl,dont_complain,lib) - lib = lib or '' - if type(tbl) == 'table' then - for k,v in pairs(tbl) do - local key = rawget(_G,k) - -- NB to keep track of collisions! - if key and k ~= '_M' and k ~= '_NAME' and k ~= '_PACKAGE' and k ~= '_VERSION' then - append(collisions,{k,lib,G_LIB[k]}) + -- inject @tbl into the global namespace + function self.ilua.import(tbl,dont_complain,lib) + lib = lib or '' + if type(tbl) == 'table' then + for k,v in pairs(tbl) do + local key = rawget(_G,k) + -- NB to keep track of collisions! + if key and k ~= '_M' and k ~= '_NAME' and k ~= '_PACKAGE' and k ~= '_VERSION' then + append(collisions,{k,lib,G_LIB[k]}) + end + _G[k] = v + G_LIB[k] = lib end - _G[k] = v - G_LIB[k] = lib end - end - if not dont_complain and #self.collisions > 0 then - for i, coll in ipairs(self.collisions) do - local name,lib,oldlib = coll[1],coll[2],coll[3] - write('warning: ',lib,'.',name,' overwrites ') - if oldlib then - self.write(oldlib,'.',name,'\n') - else - self.write('global ',name,'\n') + if not dont_complain and #self.collisions > 0 then + for i, coll in ipairs(self.collisions) do + local name,lib,oldlib = coll[1],coll[2],coll[3] + write('warning: ',lib,'.',name,' overwrites ') + if oldlib then + self.write(oldlib,'.',name,'\n') + else + self.write('global ',name,'\n') + end end end end - end - function self.ilua.print_handler(name,handler) - self.print_handlers[name] = handler - end + function self.ilua.print_handler(name,handler) + self.print_handlers[name] = handler + end - function self.ilua.line_handler(handler) - self.line_handler_fn = handler - end + function self.ilua.line_handler(handler) + self.line_handler_fn = handler + end - function self.ilua.global_handler(handler) - self.global_handler_fn = handler - end + function self.ilua.global_handler(handler) + self.global_handler_fn = handler + end - function self.ilua.print_variables() - for name,v in pairs(self.declared) do - print(name,type(_G[name])) + function self.ilua.print_variables() + for name,v in pairs(self.declared) do + print(name,type(_G[name])) + end end - end - -- any import complaints? - self.ilua.import() - - -- enable 'not declared' error - if self.strict then - self:set_strict() + -- any import complaints? + self.ilua.import() + + -- enable 'not declared' error + if self.strict then + self:set_strict() + end + end - -end +) function Interpreter:oprint(...) if self.savef then @@ -388,7 +389,7 @@ function Interpreter:set_strict() end -interpreter = Interpreter() +interpreter = Interpreter.new() function oprint(...) interpreter:oprint(...) @@ -402,5 +403,5 @@ function textAccepted() console:eval() end -console = ConsoleHud(interpreter) -Engine:registerConsoleObject(console) +console = ConsoleHud.new(interpreter) +g_luaEngine:registerConsoleObject(console) diff --git a/scripts/console_commands.lua b/scripts/console_commands.lua index 8b395811c5f..fec225baaf8 100644 --- a/scripts/console_commands.lua +++ b/scripts/console_commands.lua @@ -19,29 +19,31 @@ function toggleGuiMove() end function spawnCompounds(name, amount) - if Engine:currentGameState():name() ~= GameState.MICROBE:name() then + if g_luaEngine.currentGameState.name ~= GameState.MICROBE.name then print("Must be in microbe stage to spawn compounds") return end if global_consoleEmitter == nil then - global_consoleEmitter = Entity() - local emitterComponent = CompoundEmitterComponent() + global_consoleEmitter = Entity.new(g_luaEngine.currentGameState.wrapper) + local emitterComponent = CompoundEmitterComponent.new() emitterComponent.emissionRadius = 0 emitterComponent.maxInitialSpeed = 0 emitterComponent.minInitialSpeed = 0 emitterComponent.particleLifetime = 100000 global_consoleEmitter:addComponent(emitterComponent) - local sceneNode = OgreSceneNodeComponent() + local sceneNode = OgreSceneNodeComponent.new() global_consoleEmitter:addComponent(sceneNode) end - local playerCreature = Microbe(Entity(Engine:playerData():activeCreature())) + local playerCreature = Microbe.new(Entity.new(Engine:playerData():activeCreature(), + g_luaEngine.currentGameState.wrapper)) local compoundId = CompoundRegistry.getCompoundId(name) - local emitterSceneNode = global_consoleEmitter:getComponent(OgreSceneNodeComponent.TYPE_ID) + local emitterSceneNode = getComponent(global_consoleEmitter, OgreSceneNodeComponent) emitterSceneNode.transform.position = playerCreature.microbe.facingTargetPoint emitterSceneNode.transform:touch() local remainingAmount = amount while remainingAmount > 0 do - local compoundEmitterComponent = global_consoleEmitter:getComponent(CompoundEmitterComponent.TYPE_ID) + local compoundEmitterComponent = getComponent(global_consoleEmitter, + CompoundEmitterComponent) compoundAmount = math.min(3, remainingAmount) compoundEmitterComponent:emitCompound(compoundId, compoundAmount, 0, 0) remainingAmount = remainingAmount - compoundAmount @@ -50,20 +52,22 @@ end function reproduce() - if Engine:currentGameState():name() ~= GameState.MICROBE:name() then + if g_luaEngine.currentGameState.name ~= GameState.MICROBE.name then print("Must be in microbe stage to reproduce") return end - playerCreature = Microbe(Entity(Engine:playerData():activeCreature())) + playerCreature = Microbe.new(Entity.new(Engine:playerData():activeCreature(), + g_luaEngine.currentGameState.wrapper)) playerCreature:reproduce() end function suicide() - if Engine:currentGameState():name() ~= GameState.MICROBE:name() then + if g_luaEngine.currentGameState.name ~= GameState.MICROBE.name then print("Must be in microbe stage to suicide") return end - playerCreature = Microbe(Entity(Engine:playerData():activeCreature())) + playerCreature = Microbe.new(Entity.new(Engine:playerData():activeCreature(), + g_luaEngine.currentGameState.wrapper)) playerCreature:kill() end @@ -76,7 +80,7 @@ function unlockAll() end function mutationPoints() - if Engine:currentGameState():name() ~= GameState.MICROBE_EDITOR:name() then + if g_luaEngine.currentGameState.name ~= GameState.MICROBE.name then print("Must be in microbe editor to add mutation points") return end diff --git a/scripts/examples/component.lua b/scripts/examples/component.lua index 10244acb797..384ab65593e 100644 --- a/scripts/examples/component.lua +++ b/scripts/examples/component.lua @@ -1,25 +1,33 @@ --- Create class MyComponent, derived from Component -class 'MyComponent' (Component) - --- Define constructor -function MyComponent:__init() - -- Do not forget to call the constructor of the base class - Component.__init(self) - self.data = 0 -end +-- Create class MyComponent +MyComponent = class( + + -- Define constructor + function(self) + + self.stuff = 20 + self.prey = nil + + end +) + +-- Name the component +MyComponent.TYPE_NAME = "MyComponent" -- To enable proper serialization, you must override both the storage() -- and the load() (see below) functions -function MyComponent:storage() - local storage = Component.storage(self) - storage:set("data", self.data) +function MyComponent:storage(storage) + + storage:set("movementRadius", self.movementRadius) + end function MyComponent:load(storage) Component.load(self, storage) - self.data = storage:get("data", 0) + self.movementRadius = storage:get("movementRadius", 20) + end -- Register the new component type with the component factory REGISTER_COMPONENT("MyComponent", MyComponent) + diff --git a/scripts/examples/system.lua b/scripts/examples/system.lua index 792d5788cf7..e3cbeb45f4f 100644 --- a/scripts/examples/system.lua +++ b/scripts/examples/system.lua @@ -1,32 +1,38 @@ --- Create class MySystem, derived from System -class 'MySystem' (System) - --- Define constructor -function MySystem:__init() - -- Do not forget to call the constructor of the base class - System.__init(self) - self.entities = EntityFilter( - { - -- We only want to know about entities that have both a - -- MyComponent and an OgreSceneNodeComponent - MyComponent, - OgreSceneNodeComponent - }, - -- Optional. If true, we can ask the EntityFilter for added and - -- removed entities - true - ) -end +-- Create class MySystem, derived from LuaSystem +MySystem = class( + LuaSystem, + -- Define constructor + function(self) + -- Do not forget to call the constructor of the base class + LuaSystem.create(self) + + self.entities = EntityFilter.new( + { + -- We only want to know about entities that have both a + -- MyComponent and an OgreSceneNodeComponent + MyComponent, + OgreSceneNodeComponent + }, + -- Optional. If true, we can ask the EntityFilter for added and + -- removed entities + true + ) + end +) -- Called once before the first call to update() -function MySystem:init(engine) +function MySystem:init(gameState) + LuaSystem.init(self, "MySystem", gameState) + -- Enable the EntityFilter self.entities:init() end -- Called once after the last call to update() function MySystem:shutdown() + LuaSystem.shutdown(self) + -- Disable the EntityFilter self.entities:shutdown() end @@ -47,3 +53,4 @@ function MySystem:update(renderTime, logicTime) end end + diff --git a/scripts/game.lua b/scripts/game.lua new file mode 100644 index 00000000000..6dd5040bda8 --- /dev/null +++ b/scripts/game.lua @@ -0,0 +1,85 @@ +-- Main file + +function printStartMessage() + + print("Thrive version " .. Engine.thriveVersion .. + " with " .. _VERSION .. " from " .. jit.version .. + " ready to go. " + --.. "Let's rock" + ) + +end + + +-- Main loop for lua +--! @param cppGame thrive::Game object +function enterLuaMain(cppGame) + + printStartMessage() + + local fpsCount = 0 + + local lastUpdate = Game.now() + + -- For more accurate FPS counting + local lastSecond = Game.now() + + -- Counts frame times + local frameTimes = {} + + while cppGame.shouldQuit == false do + + local now = Game.now() + + local milliseconds = Game.asMS(Game.delta(now, lastUpdate)) + + lastUpdate = now + + -- Update engine stuff and GameStates + g_luaEngine:update(milliseconds) + + local frameDuration = Game.delta(Game.now(), now) + + table.insert(frameTimes, Game.asSeconds(frameDuration)) + + -- sleep if we are going too fast + cppGame:sleepIfNeeded(frameDuration) + + -- update fps counter + fpsCount = fpsCount + 1 + + local fpsTime = Game.asMS(Game.delta(now, lastSecond)) + if fpsTime >= 1000 then + + local fps = 1000 * (fpsCount / fpsTime) + + local avgFrameTime = 0 + + for i,t in ipairs(frameTimes) do + + avgFrameTime = avgFrameTime + t + + end + + avgFrameTime = (avgFrameTime / #frameTimes) * 1000 + + print(string.format("FPS: %.4f avg frame duration: %.5f ms", fps, + avgFrameTime)) + + -- Use to debug resource leaks in lua + --print("Used memory: " .. Engine.luaMemory) + + frameTimes = {} + lastSecond = now + fpsCount = 0 + end + end +end + + + + + + + + diff --git a/scripts/lua_engine/game_state.lua b/scripts/lua_engine/game_state.lua new file mode 100644 index 00000000000..34d4a2e6a42 --- /dev/null +++ b/scripts/lua_engine/game_state.lua @@ -0,0 +1,247 @@ +--! @file Gamestate, holds systems and updates the game systems and draws stuff + +-- This is what is said about the state in the C++ code: +-- GameState Represents a distinct set of active systems and entities +-- +-- The game has to switch between different states. Examples of a state are +-- "main menu", "microbe gameplay" or "microbe editor". These states usually +-- share very few entities and even fewer systems, so it is sensible to +-- separate them completely (and, if necessary, share data over other channels). +-- +-- Each GameState has its own EntityManager and its own set of systems. Game +-- states are identified by their name, a unique string. +-- +-- GameStates cannot be created directly. Use LuaEngine:createGameState to create +-- new GameStates. + + +GameState = class( + --! @brief Constructs a new GameState. Must be called from derived classes with + --! `GameState.create(self)` + --! @note calls this only through LuaEngine:createGameState + function(self, name, systems, engine, physics, guiLayoutName, extraInitializer) + + assert(name ~= nil) + assert(systems ~= nil) + assert(type(systems) == "table") + assert(engine ~= nil) + -- Physics must be true or false + assert(physics ~= nil) + -- TODO: make "none" skip creating the CEGUIWindow + assert(guiLayoutName ~= nil) + + self.extraInitializer = extraInitializer + + -- Systems container + self.systems = systems + self.name = name + self.engine = engine + self.guiLayoutName = guiLayoutName + + self.usePhysics = physics + + -- Make sure systems is valid + for i,s in ipairs(self.systems) do + + if s.isCppSystem then + + assert(s.init ~= nil, "C++ system object missing init property") + + else + + local err = nil + + if s.is_a == nil then + + err = "Lua table in GameState.systems is not a class (no 'is_a' method)!" + + else + + if s:is_a(LuaSystem) == false then + + err = "Lua table in GameState.systems is not derived from LuaSystem!" + + end + end + + if err then + + print(err) + print("Index " .. i .. " table:") + print_r(s) + error(err) + + end + + + assert(s.init ~= nil, "Lua system derived type is missing init") + + end + + end + + end +) + +--! @brief Initializes a state to be used. +--! @brief System initializer called once engine is set up +function GameState:init() + + -- Create entity manager + self.entityManager = EntityManager.new() + + self.guiWindow = CEGUIWindow.new(self.guiLayoutName) + + --! @brief Adds physics to this GameState + if self.usePhysics == true then + + self.physicsWorld = PhysicalWorld.new() + + end + + -- This is passed to C++ systems + self.cppData = GameStateData.new(self, Engine, self.entityManager, self.physicsWorld) + -- another name + self.wrapper = self.cppData + + assert(self.wrapper ~= nil, "GameState failed to create C++ wrapper") + + -- Init systems + for i,s in ipairs(self.systems) do + + if s.isCppSystem then + + s:init(self.wrapper) + + else + + s:init(self) + end + + end + + if self.extraInitializer ~= nil then + + self:extraInitializer() + + end + +end + + +--! @brief Must be called when this gamestate is no longer needed +--! +--! Shuts down all systems and releases the C++ data object +function GameState:shutdown() + + for i,s in ipairs(self.systems) do + + s:shutdown() + + end + + self.cppData = nil + self.physicsWorld = nil + self.entityManager = nil + self.guiWindow = nil +end + + +--! @brief Called when this gamestate is made the active one +function GameState:activate() + + self.guiWindow:show() + + -- Make this states' main window (and its children) visible + CEGUIWindow.getRootWindow():addChild(self.guiWindow) + + for i,s in ipairs(self.systems) do + + s:activate() + end + +end + +--! @brief Called when another gamestate becomes active +function GameState:deactivate() + + for i,s in ipairs(self.systems) do + + s:deactivate() + + end + + self.guiWindow:hide() + CEGUIWindow.getRootWindow():removeChild(self.guiWindow) + +end + + +--! @brief Updates game logic +function GameState:update(renderTime, logicTime) + + for i,s in ipairs(self.systems) do + --Uncomment to debug mystical crashes and other anomalies + -- print("Updating system " .. s.name) + s:update(renderTime, logicTime) + -- print("Done updating system " .. s.name) + end + + self.entityManager:processRemovals() + +end + + +--! @brief Restores saved entities from storage +--! @param storage the StorageContainer that was created with a previous call to +--! GameState:storage +function GameState:load(storage) + + local entities = storage:get("entities") + + self.entityManager:clear() + + self.entityManager:restore(entities, Engine.componentFactory) + +end + +--! @brief Saves all current entities into a StorageContainer +--! @see GameState:load +--! @returns StorageContainer +function GameState:storage() + + local entities = self.entityManager:storage(Engine.componentFactory) + + local storage = StorageContainer.new() + storage:set("entities", entities) + + return storage +end + +--! @brief Returns self.guiWindow +function GameState:rootGUIWindow() + + return self.guiWindow + +end + +--! @brief Returns an array of C++ based systems +function GameState:getCppSystems() + + local result = {} + local index = 1 + + for i,s in ipairs(self.systems) do + + if s.isCppSystem then + + result[index] = s + index = index + 1 + + end + end + + return result + +end + diff --git a/scripts/keymap.lua b/scripts/lua_engine/keymap.lua similarity index 76% rename from scripts/keymap.lua rename to scripts/lua_engine/keymap.lua index a894330c816..377f7de5a28 100644 --- a/scripts/keymap.lua +++ b/scripts/lua_engine/keymap.lua @@ -61,25 +61,25 @@ function keyCombo(combo) mods.shift = true elseif key == "alt" then mods.alt = true - elseif not Engine.keyboard:wasKeyPressed(Keyboard["KC_"..key]) then + elseif not Engine.keyboard:wasKeyPressed(KEYCODE["KC_"..key]) then return false end end -- fail if any modkey pressed unmatches required mods - if (Engine.keyboard:isKeyDown(Keyboard.KC_LCONTROL) - or Engine.keyboard:isKeyDown(Keyboard.KC_RCONTROL) - ) ~= mods.ctrl then + if (Engine.keyboard:isKeyDown(KEYCODE.KC_LCONTROL) + or Engine.keyboard:isKeyDown(KEYCODE.KC_RCONTROL) + ) ~= mods.ctrl then return false end - if (Engine.keyboard:isKeyDown(Keyboard.KC_LSHIFT) - or Engine.keyboard:isKeyDown(Keyboard.KC_RSHIFT) - ) ~= mods.shift then + if (Engine.keyboard:isKeyDown(KEYCODE.KC_LSHIFT) + or Engine.keyboard:isKeyDown(KEYCODE.KC_RSHIFT) + ) ~= mods.shift then return false end - if (Engine.keyboard:isKeyDown(Keyboard.KC_LMENU) - or Engine.keyboard:isKeyDown(Keyboard.KC_RMENU) - ) ~= mods.alt then + if (Engine.keyboard:isKeyDown(KEYCODE.KC_LMENU) + or Engine.keyboard:isKeyDown(KEYCODE.KC_RMENU) + ) ~= mods.alt then return false end return true diff --git a/scripts/lua_engine/lua_engine.lua b/scripts/lua_engine/lua_engine.lua new file mode 100644 index 00000000000..c780043e68f --- /dev/null +++ b/scripts/lua_engine/lua_engine.lua @@ -0,0 +1,460 @@ +--! @file Lua versions of functions in engine.cpp +--! +--! This is done to allow the main loop of the game to be in lua and +--! that way reduce calls from C++ to Lua. With JIT the Lua code +--! is fast enough to be the "glue" between C++ systems and Lua +--! systems and main loop + +LuaEngine = class( + + function(self) + + -- The state the engine is switching to on next frame + self.nextGameState = nil + + -- The current main GameState. Touching this directly WILL cause problems + -- (unless you are careful, but... don't do it) + self.currentGameState = nil + + -- List of all created GameStates + self.gameStates = {} + + + + -- The console object attaches itself here + self.console = nil + self.consoleGUIWindow = nil + + -- This is a table of systems that are going to be moved to prevShutdownSystems once + -- the GameState changes. So this is used to get all the systems that the current state + -- wants to timed shutdown + self.nextShutdownSystems = {} + + -- This is a table of currently running systems that need to be shutdown + self.prevShutdownSystems = {} + + end +) + +--! @brief Initializes the lua side of the engine +--! @param cppSide the engine object received from +--! c++ code +function LuaEngine:init(cppSide) + + assert(cppSide ~= nil) + + self.Engine = cppSide + + self.initialized = true + + print("LuaEngine init started") + + self.consoleGUIWindow = CEGUIWindow.new("Console") + + -- Store current state + local previousGameState = self.currentGameState + + -- Initialize states that have been created while loading all the scripts + for _,s in pairs(self.gameStates) do + + self.currentGameState = s + + s:init() + + end + + -- Restore the state + self.currentGameState = previousGameState + +end + +--! @brief Shutsdown all systems +function LuaEngine:shutdown() + + for _,s in pairs(self.gameStates) do + + s:shutdown() + + end +end + +--! @param name Unique name of the system +--! @param systems Array of systems that are in the new GameState. +--! Must be created with `table.insert(systems, s)` +--! @param physics If true creates a physics state in the GameState +--! @todo Make sure that .destroy() is called on these objects +--! @param extraInitializer Function to be ran just after the GameState +--! is initialized. The first parameter to the function is the gameState +function LuaEngine:createGameState(name, + systems, + physics, + guiLayoutName, + extraInitializer) + + assert(self.initialized ~= true, + "LuaEngine: trying to create state after init. State wouldn't be initialized!") + + if extraInitializer ~= nil then + + -- Initializer must be a function + assert(type(extraInitializer) == "function", + "extraInitializer must be a function") + + end + -- Type check everything for bad calls + assert(type(name) == "string") + assert(type(systems) == "table") + assert(type(physics) == "boolean") + assert(type(guiLayoutName) == "string") + + assert(self.gameStates[name] == nil, "Duplicate GameState name") + + local newState = GameState.new(name, systems, self, physics, + guiLayoutName, extraInitializer) + + self.gameStates[name] = newState + + return newState +end + +--! @brief Runs updates on some core systems and the current GameState +function LuaEngine:update(milliseconds) + + self.Engine:update(milliseconds) + + -- Update GameStates + + if self.nextGameState ~= nil then + + self:activateGameState(self.nextGameState) + self.nextGameState = nil + + end + + if self.currentGameState == nil then + error("currentGameState is nil") + end + + -- Update current GameState + local updateTime = milliseconds + + if self.Engine.paused then + updateTime = 0 + end + + self.currentGameState:update(milliseconds, updateTime) + + -- Update console + self.console:update() + + + -- Update any timed shutdown systems + -- Reverse iterate to safely remove items + for i = #self.prevShutdownSystems, 1, -1 do + + local delayed = self.prevShutdownSystems[i] + + local updateTime = math.min(delayed.timeLeft, milliseconds); + + + local pauseHelper = updateTime + + if self.Engine.paused then + + pauseHelper = 0 + + end + + delayed.system:update(updateTime, pauseHelper) + + delayed.timeLeft = delayed.timeLeft - updateTime + + if delayed.timeLeft <= 0 then + + -- Remove systems that had timed out + delayed.system:deactivate() + table.remove(self.prevShutdownSystems, i) + + end + end +end + + +-- Timed shutdown functions + +--! @brief Keeps a system alive after being shut down for a specified amount of time +--! +--! Note that this causes update to be called for the specified duration so be careful +--! to ensure that the system is not enabled or it will get update calls twice. +--! +--! @param system +--! The system to keep updated +--! +--! @param milliseconds +--! The number of milliseconds to keep the system updated for +--! +function LuaEngine:timedSystemShutdown(system, milliseconds) + + table.insert(self.prevShutdownSystems, { timeLeft = milliseconds, ["system"] = system }) + +end + +--! @brief Returns true if system is already queued for shutdown +function LuaEngine:isSystemTimedShutdown(system) + + for i,p in ipairs(self.prevShutdownSystems) do + + if p.system == system then + return true + end + + end + + return false + +end + + +--! @brief Sets the current game state +--! +--! The game state will be activated at the beginning of the next frame. +--! +--! \a gameState must not be \c null. +--! +--! @param gameState GameState The new game state +function LuaEngine:setCurrentGameState(gameState) + + assert(gameState ~= nil, "GameState must not be null") + + self.nextGameState = gameState; + + --Make sure systems are deactivated before any potential reactivations + + for _,p in pairs(self.prevShutdownSystems) do + + p.system:deactivate() + + end + + self.prevShutdownSystems = self.nextShutdownSystems + self.nextShutdownSystems = {} + +end + + + +--! @brief Retrieves a game state +--! @param name The game state's name +--! @return The GameState with the name or nil +function LuaEngine:getGameState(name) + + return self.gameStates[name] + +end + +--! @brief Returns a system that has the potential C++ side object +function LuaEngine:gameStateFromCpp(cppObj) + + local objType = type(cppObj) + + if objType == "table" then + + -- Already a Lua type + return nil + + end + + assert(objType == "userdata") + + local cppName = cppObj.name + + for _,s in pairs(self.gameStates) do + + --if s.wrapper == cppObj then + -- name compare, this seems to work better than equality + if s.name == cppName then + + return s + + end + + end + + return nil +end + +--! @brief Returns a lua State owning cppWrapper or asserts +function LuaEngine:getLuaStateFromWrapper(cppWrapper) + + assert(cppWrapper) + assert(type(cppWrapper) == "userdata") + + local state = self:gameStateFromCpp(cppWrapper) + + if state ~= nil then + + return state + end + + assert(false, "getLuaSystemFromWrapper(cppWrapper) failed to find state with wrapper") +end + +--! @brief Transfers an entity from one gamestate to another +--! +--! @param oldEntityId +--! The id of the entity to transfer in the old entitymanager +--! +--! @param oldEntityManager +--! The old entitymanager which is currently handling the entity. EntityManager type +--! +--! @param newGameState +--! The new gamestate to transfer the entity to +--! @return The new entity id in the new gamestate +function LuaEngine:transferEntityGameState(oldEntityId, + oldEntityManager, + newGameState) + + local state = self:gameStateFromCpp(newGameState) + + if state ~= nil then + newGameState = state + end + + local newEntity -- EntityId + + assert(oldEntityId) + assert(type(oldEntityId) == "number") + local nameMapping = oldEntityManager:getNameMappingFor(oldEntityId) + + if nameMapping ~= nil then + + newEntity = newGameState.entityManager:getNamedId(nameMapping, true) + + else + newEntity = newGameState.entityManager:generateNewId() + end + + oldEntityManager:transferEntity( + oldEntityId, newEntity, newGameState.entityManager, Engine.componentFactory); + + return newEntity; +end + + + +--! @protected @brief Changes the current GameState right now. May not +--! be called during an update! +function LuaEngine:activateGameState(gameState) + + if self.currentGameState ~= nil then + + self.currentGameState:deactivate() + + end + + self.currentGameState = gameState + + if self.currentGameState ~= nil then + + gameState:activate() + + gameState:rootGUIWindow():addChild(self.consoleGUIWindow) + + self.console:registerEvents(gameState) + end + +end + + +--! @protected @brief Called from C++ side to load game states from a StorageContainer +--! @param saveGame StorageContainer with saved data +function LuaEngine:loadSavegameGameStates(saveGame) + + local previousGameState = self.currentGameState + + self:activateGameState(nil) + + local gameStatesContainer = saveGame:get("gameStates") + + for name, system in pairs(self.gameStates) do + + if gameStatesContainer:contains(name) then + + -- In case anything relies on the current game state + -- during loading, temporarily switch it + self.currentGameState = system + + system:load(gameStatesContainer:get(name)) + + else + system.entityManager:clear() + end + + end + + for _,p in pairs(self.prevShutdownSystems) do + + p.system:deactivate() + + end + + for _,p in pairs(self.nextShutdownSystems) do + + p.system:deactivate() + + end + + self.nextShutdownSystems = {} + self.prevShutdownSystems = {} + + + self.currentGameState = nil + + -- Switch gamestate + local gameStateName = saveGame:get("currentGameState") + + local gameState = self:getGameState(gameStateName) + + if gameState ~= nil then + + self:activateGameState(gameState) + + else + + self:activateGameState(previousGameState) + print("Error loading GameStates: unkown name for 'currentGameState'") + + end + +end + + +--! @protected @brief Called from C++ side to load game states from a StorageContainer +--! @param saveGame StorageContainer to be filled with saved data +function LuaEngine:saveCurrentStates(saveGame) + + saveGame:set("currentGameState", self.currentGameState.name) + + local gameStatesContainer = StorageContainer.new() + + for name, system in pairs(self.gameStates) do + + gameStatesContainer:set(name, system:storage()) + + end + + saveGame:set("gameStates", gameStatesContainer) + +end + +--! Sets the console object. Called from console.lua +function LuaEngine:registerConsoleObject(console) + + self.console = console; + +end + +--! Global LuaEngine instance +g_luaEngine = LuaEngine.new() + + diff --git a/scripts/lua_engine/manifest.txt b/scripts/lua_engine/manifest.txt new file mode 100644 index 00000000000..bb4ba29cb3a --- /dev/null +++ b/scripts/lua_engine/manifest.txt @@ -0,0 +1,9 @@ +system.lua + +keymap.lua + +game_state.lua + +lua_engine.lua + + diff --git a/scripts/lua_engine/system.lua b/scripts/lua_engine/system.lua new file mode 100644 index 00000000000..06a8704b1de --- /dev/null +++ b/scripts/lua_engine/system.lua @@ -0,0 +1,63 @@ +-- Lua System base class + +LuaSystem = class( + --! @brief Constructs a new System. Should be called from derived classes with + --! `LuaSystem.create(self)` + function(self) + + -- Sanity check that fails if obj doesn't derive from system + assert(self:is_a(LuaSystem), + "LuaSystem.construct called on table that isn't a LuaSystem") + + -- This is no longer used to determine which systems to run + self.enabled = true + + self.isLuaSystem = true + + + + end +) + +-- default implementations +function LuaSystem:update(renderTime, logicTime) + + error("default LuaSystem:update called") + +end + +function LuaSystem:destroy() + + self.gameState = nil + +end + +--! Base init. Must be called from derived classes +function LuaSystem:init(name, gameState) + + assert(name ~= nil) + assert(gameState ~= nil) + + assert(type(name) == "string") + + self.name = name + self.gameState = gameState +end + + +--! Base shutdown. Does nothing. Doesn't need to be called +function LuaSystem:shutdown() + +end + +-- Looks like derived systems are really bad at calling these things +-- so these are now not required to be called as they do nothing + +function LuaSystem:activate() + +end + +function LuaSystem:deactivate() + +end + diff --git a/scripts/lua_notes.md b/scripts/lua_notes.md new file mode 100644 index 00000000000..6df51a0449d --- /dev/null +++ b/scripts/lua_notes.md @@ -0,0 +1,178 @@ +How to debug easier +=================== + +Enable more checks +------------------ + +By default most Lua safety checks are off. To make debugging easier +you can build thrive with extra safety checks by specifying `LUA_CHECKS=ON` +when running cmake. Like this: + +```bash +cmake .. -DLUA_CHECKS=ON +``` + + +Changes with the switch to sol +============================== + + +Lua syntax changes +------------------ + +creating instances of class are like this: +`ColourValue.new(arguments)` instead of `ColourValue(arguments)`. + + +Function calls, MUST have `(` on the same line as the call. This is a syntax error: + +```lua +self.id = currentSpawnSystem:addSpawnType +( + ... +) +``` + +This is the correct syntax: + +```lua +self.id = currentSpawnSystem:addSpawnType( + ... +) +``` + + +If you are getting errors about "attempt to call a string value" +without a stack trace. Then this is most likely what you have done +wrong. + + + +### Casting from base Component + +`entity:getComponent` returns the base Component type so it is +required to be casted to a specific type like +`CompoundAbsorberComponent` to be used. For example: +`CompoundAbsorberComponent.castFrom(entity:getComponent(CompoundAbsorberComponent.TYPE_ID))` + +Or you can use the helper `getComponent("main_menu_ambience", +self.gameState, SoundSourceComponent ).autoLoop = true` + + + +Lua components are handled as ComponentWrapper inside C++ so it s +required to be unwrapped like this: +`unwrapWrappedComponent(entity:getComponent(MicrobeComponent.TYPE_ID))`. +For performance reasons it might be worth it to also move the entity +manager to Lua, but that hasn't been done yet. + + +### The .new method + +Before all Lua objects were created like this: +`OgreSceneNodeComponent()` but now you need to call the `.new` method +like this: `OgreSceneNodeComponent.new()`. Though, for convenience +some classes expose (one of) their constructors the old way. For +example the vector class: `Vector3(1, 5, 0)` and `Degree` but only the +numeric constructors. So if you want to call `Degree` constructor with +a `Radian` you will need to use `Degree.new(radianVariable)`. + + +Renames and different function signatures +----------------------------------------- + +Renamed `CollisionShape.Axis.AXIS_X` to `SHAPE_AXIS.X` +also same with Y and Z + + +`CollisionFilter.collisions` now constructs a table from the iterator +that the actual `.collisions` method returns + + +`Keyboard.KeyCode` is now global enum `KEYCODE` + + +`Ogre::Ray::intersects` now returns a tuple + +Order of multiplication matters (sometimes) +------------------------------------------- + +Now because overloaded operators are only on the user types (by +default) the complex type needs to be on the left hand side: +`direction * impulseMagnitude` is correct (where direction is a +Vector3 and impulseMagnitude is a float). This is wrong and causes an +error: `direction * impulseMagnitude` (`sol: no matching function call +takes this number of arguments and the specified types`) + + +This is actually fixed for Vector3 class so the above example works +both ways. But some other classes might miss this. If they are it is +quite easy to add, just look at how +`lua.new_usertype("Vector3", ... ` registers its +addition metamethod overloads. + + +### New calls to C++ functions taking GameState arguments + +Now the GameState object is not exposed to C++ instead there is a +wrapper that needs to be passed to C++. It is stored in +`GameState.wrapper` so now `self.entities:init(gameState)` becomes +`self.entities:init(gameState.wrapper)` + + +If you don't pass the wrapper you will get a segmentation fault. But +if you have turned on LUA_CHECKS then you will get an error message +like this: `stack index 2, expected userdata, received table` + + + +C++ notes +--------- + +C++ systems now receive a `GameStateData` object that allows them to +query stuff that Lua has setup. + + +Don't screw up by using `sol::var` when you should have used +`sol::property`, this is specially when binding lambdas or other +*property* accessors. + + +#### Warning + +>Do NOT save the return type of a function_result with auto, as in +>`auto numwoof = woof(20);`, and do NOT store it anywhere. + +From here: [safety - sol](https://sol2.readthedocs.io/en/latest/safety.html) + + + +Running with valgrind +--------------------- + +To avoid false positives LuaJIT makefile needs to be altered to enable +debug info and valgrind support mode. Plus you might need to use a +luajit valgrind suppression +file. +[Some instructions here](https://gist.github.com/deltheil/3d446d00a39cca138978) + + +GDB Debugging +------------- + +LuaJIT can provide source file information for GDB with GDB version +7+. To use this uncomment `XCFLAGS+= -DLUAJIT_USE_GDBJIT` in the +LuaJIT makefile. See `lj_gdbjit.c` for instructions how to set +breakpoints in Lua. + + + + + + + + + + + + diff --git a/scripts/main_menu/main_menu_hud.lua b/scripts/main_menu/main_menu_hud.lua index e61bc6a1ffb..2654a0376ae 100644 --- a/scripts/main_menu/main_menu_hud.lua +++ b/scripts/main_menu/main_menu_hud.lua @@ -1,70 +1,97 @@ -- Updates the hud with relevant information -class 'MainMenuHudSystem' (System) -function MainMenuHudSystem:__init() - System.__init(self) -end +MainMenuHudSystem = class( + LuaSystem, + function(self) + + LuaSystem.create(self) + + end +) function MainMenuHudSystem:init(gameState) - System.init(self, "MainMenuHudSystem", gameState) - root = gameState:rootGUIWindow() - local microbeButton = root:getChild("Background"):getChild("MainMenuInteractive"):getChild("NewGameButton") - local quitButton = root:getChild("Background"):getChild("MainMenuInteractive"):getChild("ExitGameButton") - local loadButton = root:getChild("Background"):getChild("MainMenuInteractive"):getChild("LoadGameButton") - microbeButton:registerEventHandler("Clicked", mainMenuMicrobeStageButtonClicked) - loadButton:registerEventHandler("Clicked", mainMenuLoadButtonClicked) - quitButton:registerEventHandler("Clicked", quitButtonClicked) - updateLoadButton(); - self.videoPlayer = CEGUIVideoPlayer("IntroPlayer") - root:addChild( self.videoPlayer) - self.hasShownIntroVid = false - self.vidFadeoutStarted = false - self.skippedVideo = false - + LuaSystem.init(self, "MainMenuHudSystem", gameState) + root = gameState.guiWindow + + local microbeButton = root:getChild("Background"): + getChild("MainMenuInteractive"):getChild("NewGameButton") + local quitButton = root:getChild("Background"): + getChild("MainMenuInteractive"):getChild("ExitGameButton") + local loadButton = root:getChild("Background"): + getChild("MainMenuInteractive"):getChild("LoadGameButton") + + microbeButton:registerEventHandler("Clicked", mainMenuMicrobeStageButtonClicked) + loadButton:registerEventHandler("Clicked", mainMenuLoadButtonClicked) + quitButton:registerEventHandler("Clicked", quitButtonClicked) + + updateLoadButton(); + + self.videoPlayer = CEGUIVideoPlayer.new("IntroPlayer") + root:addChild( self.videoPlayer) + + self.hasShownIntroVid = false + self.vidFadeoutStarted = false + self.skippedVideo = false + + -- Set version in GUI + local versionLabel = root:getChild("Background"): + getChild("MainMenuInteractive"):getChild("VersionLabel") + + versionLabel:setText("v" .. Engine.thriveVersion) + end function MainMenuHudSystem:update(renderTime, logicTime) - if keyCombo(kmp.screenshot) then - Engine:screenShot("screenshot.png") - elseif keyCombo(kmp.skipvideo) then - if self.videoPlayer then - self.videoPlayer:close() + if keyCombo(kmp.screenshot) then + Engine:screenShot("screenshot.png") + elseif keyCombo(kmp.skipvideo) then + if self.videoPlayer then + self.videoPlayer:close() + self.videoPlayer:hide() + + getComponent("gui_sounds", self.gameState, SoundSourceComponent + ):interruptPlaying() + + getComponent("main_menu_ambience", self.gameState, SoundSourceComponent + ).autoLoop = true + + self.skippedVideo = true + end + elseif keyCombo(kmp.forward) then + + end + if self.videoPlayer then + self.videoPlayer:update() + if self.videoPlayer:getCurrentTime() >= self.videoPlayer:getDuration() - 3.0 then + if not self.vidFadeoutStarted then + self.videoPlayer:playAnimation("fadeout") + self.vidFadeoutStarted = true + end + if not self.skippedVideo and self.videoPlayer:getCurrentTime() >= self.videoPlayer:getDuration() then self.videoPlayer:hide() - Entity("gui_sounds"):getComponent(SoundSourceComponent.TYPE_ID):interruptPlaying() - Entity("main_menu_ambience"):getComponent(SoundSourceComponent.TYPE_ID).autoLoop = true - self.skippedVideo = true - end - elseif keyCombo(kmp.forward) then - - end - if self.videoPlayer then - self.videoPlayer:update() - if self.videoPlayer:getCurrentTime() >= self.videoPlayer:getDuration() - 3.0 then - if not self.vidFadeoutStarted then - self.videoPlayer:playAnimation("fadeout") - self.vidFadeoutStarted = true - end - if not self.skippedVideo and self.videoPlayer:getCurrentTime() >= self.videoPlayer:getDuration() then - self.videoPlayer:hide() - Entity("main_menu_ambience"):getComponent(SoundSourceComponent.TYPE_ID).autoLoop = true - end - end - end + + getComponent("main_menu_ambience", self.gameState, SoundSourceComponent + ).autoLoop = true + + end + end + end end function MainMenuHudSystem:shutdown() - -- Necessary to avoid failed assert in ogre on exit - CEGUIVideoPlayer.destroyVideoPlayer(self.videoPlayer) + -- Necessary to avoid failed assert in ogre on exit + CEGUIVideoPlayer.destroyVideoPlayer(self.videoPlayer) end function MainMenuHudSystem:activate() - updateLoadButton(); - if self.videoPlayer and not self.hasShownIntroVid then - self.videoPlayer:setVideo("intro.wmv") - self.hasShownIntroVid = true - self.videoPlayer:play() - end + updateLoadButton(); + if self.videoPlayer and not self.hasShownIntroVid then + self.videoPlayer:setVideo("intro.wmv") + self.hasShownIntroVid = true + self.videoPlayer:play() + end end + function updateLoadButton() if Engine:fileExists("quick.sav") then root:getChild("Background"):getChild("MainMenuInteractive"):getChild("LoadGameButton"):enable(); @@ -75,17 +102,21 @@ end function mainMenuLoadButtonClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") - Engine:setCurrentGameState(GameState.MICROBE) + + getComponent("gui_sounds", g_luaEngine.currentGameState, SoundSourceComponent + ):playSound("button-hover-click") + + g_luaEngine:setCurrentGameState(GameState.MICROBE) Engine:load("quick.sav") print("Game loaded"); end function mainMenuMicrobeStageButtonClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") - Engine:setCurrentGameState(GameState.MICROBE_TUTORIAL) + + getComponent("gui_sounds", g_luaEngine.currentGameState, SoundSourceComponent + ):playSound("button-hover-click") + + g_luaEngine:setCurrentGameState(GameState.MICROBE_TUTORIAL) end -- quitButtonClicked is already defined in microbe_stage_hud.lua diff --git a/scripts/main_menu/setup.lua b/scripts/main_menu/setup.lua index 559caeb2c3f..036e86f0e5e 100644 --- a/scripts/main_menu/setup.lua +++ b/scripts/main_menu/setup.lua @@ -1,28 +1,28 @@ -local function setupCamera() - local entity = Entity(CAMERA_NAME .. "2") +local function setupCamera(gameState) + local entity = Entity.new(CAMERA_NAME .. "2", gameState.wrapper) -- Camera - local camera = OgreCameraComponent("camera2") + local camera = OgreCameraComponent.new("camera2") camera.properties.nearClipDistance = 5 camera.properties:touch() entity:addComponent(camera) -- Scene node - local sceneNode = OgreSceneNodeComponent() + local sceneNode = OgreSceneNodeComponent.new() entity:addComponent(sceneNode) -- Workspace - local workspaceEntity = Entity() + local workspaceEntity = Entity.new(gameState.wrapper) -- TODO: could create a workspace without shadows - local workspaceComponent = OgreWorkspaceComponent("thrive_default") + local workspaceComponent = OgreWorkspaceComponent.new("thrive_default") workspaceComponent.properties.cameraEntity = entity workspaceComponent.properties.position = 0 workspaceComponent.properties:touch() workspaceEntity:addComponent(workspaceComponent) end -local function setupSound() +local function setupSound(gameState) -- Background music - local ambientEntity = Entity("main_menu_ambience") - local soundSource = SoundSourceComponent() + local ambientEntity = Entity.new("main_menu_ambience", gameState.wrapper) + local soundSource = SoundSourceComponent.new() soundSource.ambientSoundSource = true soundSource.autoLoop = false soundSource.volumeMultiplier = 0.8 @@ -30,8 +30,8 @@ local function setupSound() soundSource:addSound("main-menu-theme-1", "main-menu-theme-1.ogg") soundSource:addSound("main-menu-theme-2", "main-menu-theme-2.ogg") -- Gui effects - local guiSoundEntity = Entity("gui_sounds") - soundSource = SoundSourceComponent() + local guiSoundEntity = Entity.new("gui_sounds", gameState.wrapper) + soundSource = SoundSourceComponent.new() soundSource.ambientSoundSource = true soundSource.autoLoop = false soundSource.volumeMultiplier = 1.0 @@ -41,28 +41,31 @@ local function setupSound() end local function createMainMenu(name) - return Engine:createGameState( - name, - { - -- Graphics - OgreAddSceneNodeSystem(), - OgreUpdateSceneNodeSystem(), - OgreCameraSystem(), - MainMenuHudSystem(), - OgreWorkspaceSystem(), - OgreRemoveSceneNodeSystem(), - RenderSystem(), - -- Other - SoundSourceSystem(), - }, - function() - setupCamera() - setupSound() - end, - "MainMenu" - ) + + return g_luaEngine:createGameState( + name, + { + -- Graphics + OgreAddSceneNodeSystem.new(), + OgreUpdateSceneNodeSystem.new(), + OgreCameraSystem.new(), + MainMenuHudSystem.new(), + OgreWorkspaceSystem.new(), + OgreRemoveSceneNodeSystem.new(), + RenderSystem.new(), + -- Other + SoundSourceSystem.new(), + }, + -- No physics + false, + "MainMenu", + function(gameState) + setupCamera(gameState) + setupSound(gameState) + end + ) end GameState.MAIN_MENU = createMainMenu("main_menu") -Engine:setCurrentGameState(GameState.MAIN_MENU) +g_luaEngine:setCurrentGameState(GameState.MAIN_MENU) diff --git a/scripts/manifest.txt b/scripts/manifest.txt index 79656cf9527..3780aad51da 100644 --- a/scripts/manifest.txt +++ b/scripts/manifest.txt @@ -1,9 +1,13 @@ +// utilities and definitions +util.lua colours.lua +class.lua constants.lua -quick_save.lua -util.lua -keymap.lua +// engine stuff like gamestates +lua_engine + +quick_save.lua main_menu microbe_stage @@ -14,3 +18,6 @@ microbe_editor console.lua console_commands.lua +// main loop is defined here +game.lua + diff --git a/scripts/microbe_editor/microbe_editor.lua b/scripts/microbe_editor/microbe_editor.lua index 9012abb6fc7..5a4dbea3786 100644 --- a/scripts/microbe_editor/microbe_editor.lua +++ b/scripts/microbe_editor/microbe_editor.lua @@ -4,38 +4,39 @@ -- Contains the functionality associated with creating and augmenting microbes -- See http://www.redblobgames.com/grids/hexagons/ for mathematical basis of hex related code. -------------------------------------------------------------------------------- -class 'MicrobeEditor' +MicrobeEditor = class( + function(self, hudSystem) -function MicrobeEditor:__init(hudSystem) - self.currentMicrobe = nil - self.organelleCount = 0 - self.activeActionName = nil - self.hudSystem = hudSystem - self.nextMicrobeEntity = nil - self.gridSceneNode = nil - self.gridVisible = true - self.mutationPoints = 50 - self.placementFunctions = {["nucleus"] = MicrobeEditor.createNewMicrobe, - ["flagellum"] = MicrobeEditor.addOrganelle, - ["cytoplasm"] = MicrobeEditor.addOrganelle, - ["mitochondrion"] = MicrobeEditor.addOrganelle, - ["chloroplast"] = MicrobeEditor.addOrganelle, - ["oxytoxy"] = MicrobeEditor.addOrganelle, - ["vacuole"] = MicrobeEditor.addOrganelle, - ["remove"] = MicrobeEditor.removeOrganelle} - self.actionHistory = nil - self.actionIndex = 0 - self.organelleRot = 0 - self.occupiedHexes = {} - -- 0 is no symmetry, 1 is x-axis symmetry, 2 is 4-way symmetry, and 3 is 6-way symmetry. - self.symmetry = 0 -end + self.currentMicrobe = nil + self.organelleCount = 0 + self.activeActionName = nil + self.hudSystem = hudSystem + self.nextMicrobeEntity = nil + self.gridSceneNode = nil + self.gridVisible = true + self.mutationPoints = 50 + self.placementFunctions = {["nucleus"] = MicrobeEditor.createNewMicrobe, + ["flagellum"] = MicrobeEditor.addOrganelle, + ["cytoplasm"] = MicrobeEditor.addOrganelle, + ["mitochondrion"] = MicrobeEditor.addOrganelle, + ["chloroplast"] = MicrobeEditor.addOrganelle, + ["oxytoxy"] = MicrobeEditor.addOrganelle, + ["vacuole"] = MicrobeEditor.addOrganelle, + ["remove"] = MicrobeEditor.removeOrganelle} + self.actionHistory = nil + self.actionIndex = 0 + self.organelleRot = 0 + self.occupiedHexes = {} + -- 0 is no symmetry, 1 is x-axis symmetry, 2 is 4-way symmetry, and 3 is 6-way symmetry. + self.symmetry = 0 + end +) function MicrobeEditor:createHexComponent(q, r) local x, y = axialToCartesian(q, r) local s = encodeAxial(q, r) - self.occupiedHexes[s] = Entity() - local sceneNode = OgreSceneNodeComponent() + self.occupiedHexes[s] = Entity.new(g_luaEngine.currentGameState.wrapper) + local sceneNode = OgreSceneNodeComponent.new() sceneNode.transform.position = Vector3(x, y, 0) sceneNode.transform:touch() sceneNode.meshName = "hex.mesh" @@ -55,8 +56,8 @@ function MicrobeEditor:surroundsOrganelle(q, r) end function MicrobeEditor:init(gameState) - ent = Entity() - local sceneNode = OgreSceneNodeComponent() + ent = Entity.new(gameState.wrapper) + local sceneNode = OgreSceneNodeComponent.new() sceneNode.planeTexture = "EditorGridMaterial" ent:addComponent(sceneNode) sceneNode.transform.scale = Vector3(HEX_SIZE, HEX_SIZE, 1) @@ -66,14 +67,29 @@ function MicrobeEditor:init(gameState) end function MicrobeEditor:activate() - if Engine:playerData():activeCreatureGamestate():name() == GameState.MICROBE:name() or Engine:playerData():activeCreatureGamestate():name() == GameState.MICROBE_TUTORIAL:name() then - microbeStageMicrobe = Entity(Engine:playerData():activeCreature(), GameState.MICROBE) - self.nextMicrobeEntity = microbeStageMicrobe:transfer(GameState.MICROBE_EDITOR) + local creatureState = g_luaEngine:getLuaStateFromWrapper( + Engine:playerData():activeCreatureGamestate()) + + if creatureState.name == GameState.MICROBE.name or + creatureState.name == GameState.MICROBE_TUTORIAL.name then + + microbeStageMicrobe = Entity.new(Engine:playerData():activeCreature(), + GameState.MICROBE.wrapper) + + self.nextMicrobeEntity = Entity.new( + g_luaEngine:transferEntityGameState(microbeStageMicrobe.id, + creatureState.entityManager, + GameState.MICROBE_EDITOR), + GameState.MICROBE_EDITOR.wrapper) + -- Transfer the compounds - Microbe.transferCompounds(Microbe(microbeStageMicrobe), Microbe(self.nextMicrobeEntity, true)) + Microbe.transferCompounds(Microbe.new(microbeStageMicrobe), + Microbe.new(self.nextMicrobeEntity, true)) + self.nextMicrobeEntity:stealName("working_microbe") Engine:playerData():setBool("edited_microbe", true) - Engine:playerData():setActiveCreature(self.nextMicrobeEntity.id, GameState.MICROBE_EDITOR) + Engine:playerData():setActiveCreature(self.nextMicrobeEntity.id, + GameState.MICROBE_EDITOR.wrapper) end @@ -84,8 +100,9 @@ function MicrobeEditor:activate() cytoplasm:destroy() end - self.currentMicrobe = Microbe(self.nextMicrobeEntity, true) - self.currentMicrobe.sceneNode.transform.orientation = Quaternion(Radian(Degree(0)), Vector3(0, 0, 1))-- Orientation + self.currentMicrobe = Microbe.new(self.nextMicrobeEntity, true) + self.currentMicrobe.sceneNode.transform.orientation = Quaternion.new( + Radian.new(Degree(0)), Vector3(0, 0, 1))-- Orientation self.currentMicrobe.sceneNode.transform.position = Vector3(0, 0, 0) self.currentMicrobe.sceneNode.transform:touch() @@ -125,9 +142,10 @@ end function MicrobeEditor:renderHighlightedOrganelle(start, q, r, rotation) -- Render the hex under the cursor local sceneNode = {} - sceneNode[1] = self.hudSystem.hoverOrganelle[start]:getComponent(OgreSceneNodeComponent.TYPE_ID) + sceneNode[1] = getComponent(self.hudSystem.hoverOrganelle[start], OgreSceneNodeComponent) for i=2, 8 do - sceneNode[i] = self.hudSystem.hoverHex[i-1+(start-1)*7]:getComponent(OgreSceneNodeComponent.TYPE_ID) + sceneNode[i] = getComponent(self.hudSystem.hoverHex[i-1+(start-1)*7], + OgreSceneNodeComponent) end if self.activeActionName then @@ -241,7 +259,10 @@ end function MicrobeEditor:getMouseHex() local mousePosition = Engine.mouse:normalizedPosition() -- Get the position of the cursor in the plane that the microbes is floating in - local rayPoint = Entity(CAMERA_NAME .. "3"):getComponent(OgreCameraComponent.TYPE_ID):getCameraToViewportRay(mousePosition.x, mousePosition.y):getPoint(0) + local rayPoint = getComponent(CAMERA_NAME .. "3", g_luaEngine.currentGameState, + OgreCameraComponent + ):getCameraToViewportRay(mousePosition.x, mousePosition.y):getPoint(0) + -- Convert to the hex the cursor is currently located over. local q, r = cartesianToAxial(rayPoint.x, -1*rayPoint.y) -- Negating X to compensate for the fact that we are looking at the opposite side of the normal coordinate system local qr, rr = cubeToAxial(cubeHexRound(axialToCube(q, r))) -- This requires a conversion to hex cube coordinates and back for proper rounding. @@ -428,9 +449,11 @@ function MicrobeEditor:loadMicrobe(entityId) if self.currentMicrobe ~= nil then self.currentMicrobe.entity:destroy() end - self.currentMicrobe = Microbe(Entity(entityId), true) + self.currentMicrobe = Microbe.new(Entity.new(entityId, + g_luaEngine.currentGameState.wrapper), true) self.currentMicrobe.entity:stealName("working_microbe") - self.currentMicrobe.sceneNode.transform.orientation = Quaternion(Radian(Degree(0)), Vector3(0, 0, 1))-- Orientation + self.currentMicrobe.sceneNode.transform.orientation = Quaternion.new(Radian.new(Degree(0)), + Vector3(0, 0, 1))-- Orientation self.currentMicrobe.sceneNode.transform:touch() Engine:playerData():setActiveCreature(entityId, GameState.MICROBE_EDITOR) self.mutationPoints = 0 @@ -451,7 +474,8 @@ function MicrobeEditor:createNewMicrobe() for _, cytoplasm in pairs(self.occupiedHexes) do cytoplasm:destroy() end - self.currentMicrobe = Microbe.createMicrobeEntity(nil, false, "Editor_Microbe", true) + self.currentMicrobe = Microbe.createMicrobeEntity( + nil, false, 'Editor_Microbe', true, g_luaEngine.currentGameState) self.currentMicrobe.entity:stealName("working_microbe") --self.currentMicrobe.sceneNode.transform.orientation = Quaternion(Radian(Degree(180)), Vector3(0, 0, 1))-- Orientation self.currentMicrobe.sceneNode.transform:touch() @@ -464,7 +488,7 @@ function MicrobeEditor:createNewMicrobe() end self.mutationPoints = 100 self.activeActionName = "cytoplasm" - Engine:playerData():setActiveCreature(self.currentMicrobe.entity.id, GameState.MICROBE_EDITOR) + Engine:playerData():setActiveCreature(self.currentMicrobe.entity.id, GameState.MICROBE_EDITOR.wrapper) end } @@ -479,7 +503,8 @@ function MicrobeEditor:createNewMicrobe() action.undo = function() speciesName = self.currentMicrobe.microbe.speciesName self.currentMicrobe.entity:destroy() -- remove the "new" entity that has replaced the previous one - self.currentMicrobe = Microbe.createMicrobeEntity(nil, false, 'Editor_Microbe', true) + self.currentMicrobe = Microbe.createMicrobeEntity( + nil, false, 'Editor_Microbe', true, g_luaEngine.currentGameState) self.currentMicrobe.entity:stealName("working_microbe") self.currentMicrobe.sceneNode.transform.orientation = Quaternion(Radian(Degree(0)), Vector3(0, 0, 1))-- Orientation self.currentMicrobe.sceneNode.transform:touch() @@ -499,7 +524,7 @@ function MicrobeEditor:createNewMicrobe() -- no need to add the nucleus manually - it's alreary included in the organelleStorage self.mutationPoints = previousMP self.organelleCount = previousOrganelleCount - Engine:playerData():setActiveCreature(self.currentMicrobe.entity.id, GameState.MICROBE_EDITOR) + Engine:playerData():setActiveCreature(self.currentMicrobe.entity.id, GameState.MICROBE_EDITOR.wrapper) end self:enqueueAction(action) else diff --git a/scripts/microbe_editor/microbe_editor_hud.lua b/scripts/microbe_editor/microbe_editor_hud.lua index d9f5c1d1fbf..62b61d7a9c9 100644 --- a/scripts/microbe_editor/microbe_editor_hud.lua +++ b/scripts/microbe_editor/microbe_editor_hud.lua @@ -1,33 +1,35 @@ -- Updates the hud with relevant information -class 'MicrobeEditorHudSystem' (System) - -function MicrobeEditorHudSystem:__init() - System.__init(self) - self.organelleButtons = {} - self.initialized = false - self.editor = MicrobeEditor(self) - - -- Scene nodes for the organelle cursors for symmetry. - self.hoverHex = {} - self.hoverOrganelle = {} - - self.saveLoadPanel = nil - self.creationsListbox = nil - self.creationFileMap = {} -- Map from player creation name to filepath - self.activeButton = nil -- stores button, not name - self.helpPanelOpen = false - self.menuOpen = false -end +MicrobeEditorHudSystem = class( + LuaSystem, + function(self) + + LuaSystem.create(self) + self.organelleButtons = {} + self.initialized = false + self.editor = MicrobeEditor.new(self) + + -- Scene nodes for the organelle cursors for symmetry. + self.hoverHex = {} + self.hoverOrganelle = {} + + self.saveLoadPanel = nil + self.creationsListbox = nil + self.creationFileMap = {} -- Map from player creation name to filepath + self.activeButton = nil -- stores button, not name + self.helpPanelOpen = false + self.menuOpen = false + end +) function MicrobeEditorHudSystem:init(gameState) - System.init(self, "MicrobeEditorHudSystem", gameState) + LuaSystem.init(self, "MicrobeEditorHudSystem", gameState) self.editor:init(gameState) -- This seems really cluttered, there must be a better way. for i=1, 42 do - self.hoverHex[i] = Entity("hover-hex" .. i) - local sceneNode = OgreSceneNodeComponent() + self.hoverHex[i] = Entity.new("hover-hex" .. i, gameState.wrapper) + local sceneNode = OgreSceneNodeComponent.new() sceneNode.transform.position = Vector3(0,0,0) sceneNode.transform:touch() sceneNode.meshName = "hex.mesh" @@ -35,8 +37,8 @@ function MicrobeEditorHudSystem:init(gameState) self.hoverHex[i]:addComponent(sceneNode) end for i=1, 6 do - self.hoverOrganelle[i] = Entity("hover-organelle" .. i) - local sceneNode = OgreSceneNodeComponent() + self.hoverOrganelle[i] = Entity.new("hover-organelle" .. i, gameState.wrapper) + local sceneNode = OgreSceneNodeComponent.new() sceneNode.transform.position = Vector3(0,0,0) sceneNode.transform:touch() sceneNode.transform.scale = Vector3(HEX_SIZE, HEX_SIZE, HEX_SIZE) @@ -44,7 +46,7 @@ function MicrobeEditorHudSystem:init(gameState) end - local root = gameState:rootGUIWindow() + local root = self.gameState.guiWindow self.mpLabel = root:getChild("MpPanel"):getChild("MpBar"):getChild("NumberLabel") self.mpProgressBar = root:getChild("MpPanel"):getChild("MpBar") self.mpProgressBar:setProperty("ThriveGeneric/MpBar", "FillImage") @@ -106,8 +108,8 @@ function MicrobeEditorHudSystem:init(gameState) end function MicrobeEditorHudSystem:loadmicrobeSelectionChanged() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") + getComponent("gui_sounds", g_luaEngine.currentGameState, SoundSourceComponent + ):playSound("button-hover-click") end function MicrobeEditorHudSystem:activate() @@ -134,13 +136,13 @@ end function MicrobeEditorHudSystem:update(renderTime, logicTime) for i=1, 42 do - local sceneNode = self.hoverHex[i]:getComponent(OgreSceneNodeComponent.TYPE_ID) + local sceneNode = getComponent(self.hoverHex[i], OgreSceneNodeComponent) sceneNode.transform.position = Vector3(0,0,0) sceneNode.transform.scale = Vector3(0,0,0) sceneNode.transform:touch() end for i=1, 6 do - local sceneNode = self.hoverOrganelle[i]:getComponent(OgreSceneNodeComponent.TYPE_ID) + local sceneNode = getComponent(self.hoverOrganelle[i], OgreSceneNodeComponent) sceneNode.transform.position = Vector3(0,0,0) sceneNode.transform.scale = Vector3(0,0,0) sceneNode.transform:touch() @@ -203,10 +205,14 @@ function MicrobeEditorHudSystem:update(renderTime, logicTime) self:updateMicrobeName() end - if Engine.keyboard:wasKeyPressed(Keyboard.KC_LEFT) or Engine.keyboard:wasKeyPressed(Keyboard.KC_A) then + if Engine.keyboard:wasKeyPressed(KEYCODE.KC_LEFT) or + Engine.keyboard:wasKeyPressed(KEYCODE.KC_A) then + self.editor.organelleRot = (self.editor.organelleRot + 60)%360 end - if Engine.keyboard:wasKeyPressed(Keyboard.KC_RIGHT) or Engine.keyboard:wasKeyPressed(Keyboard.KC_D) then + if Engine.keyboard:wasKeyPressed(KEYCODE.KC_RIGHT) or + Engine.keyboard:wasKeyPressed(KEYCODE.KC_D) then + self.editor.organelleRot = (self.editor.organelleRot - 60)%360 end @@ -214,8 +220,8 @@ function MicrobeEditorHudSystem:update(renderTime, logicTime) Engine:screenShot("screenshot.png") end - if Engine.keyboard:isKeyDown(Keyboard.KC_LSHIFT) then - properties = Entity(CAMERA_NAME .. 3):getComponent(OgreCameraComponent.TYPE_ID).properties + if Engine.keyboard:isKeyDown(KEYCODE.KC_LSHIFT) then + properties = getComponent(CAMERA_NAME .. 3, self.gameState, OgreCameraComponent).properties newFovY = properties.fovY + Degree(Engine.mouse:scrollChange()/10) if newFovY < Degree(10) then newFovY = Degree(10) @@ -239,63 +245,63 @@ end function playClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") - Engine:setCurrentGameState(GameState.MICROBE) + getComponent("gui_sounds", g_luaEngine.currentGameState, SoundSourceComponent + ):playSound("button-hover-click") + g_luaEngine:setCurrentGameState(GameState.MICROBE) end function menuPlayClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") - Engine:currentGameState():rootGUIWindow():getChild("MenuPanel"):hide() + getComponent("gui_sounds", g_luaEngine.currentGameState, SoundSourceComponent + ):playSound("button-hover-click") + g_luaEngine.currentGameState.guiWindow:getChild("MenuPanel"):hide() playClicked() end function MicrobeEditorHudSystem:menuMainMenuClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") - Engine:setCurrentGameState(GameState.MAIN_MENU) + getComponent("gui_sounds", g_luaEngine.currentGameState, SoundSourceComponent + ):playSound("button-hover-click") + g_luaEngine:setCurrentGameState(GameState.MAIN_MENU) end function MicrobeEditorHudSystem:quitButtonClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") + getComponent("gui_sounds", g_luaEngine.currentGameState, SoundSourceComponent + ):playSound("button-hover-click") Engine:quit() end -- the rest of the event handlers are MicrobeEditorHudSystem methods function MicrobeEditorHudSystem:helpButtonClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):getChild("HelpPanel"):show() - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):getChild("CloseHelpButton"):show() - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):getChild("ResumeButton"):hide() - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):getChild("QuicksaveButton"):hide() - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):getChild("SaveGameButton"):hide() - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):getChild("LoadGameButton"):hide() - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):getChild("StatsButton"):hide() - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):getChild("HelpButton"):hide() - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):getChild("OptionsButton"):hide() - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):getChild("MainMenuButton"):hide() - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):getChild("QuitButton"):hide() + getComponent("gui_sounds", g_luaEngine.currentGameState, SoundSourceComponent + ):playSound("button-hover-click") + self.gameState.guiWindow:getChild("PauseMenu"):getChild("HelpPanel"):show() + self.gameState.guiWindow:getChild("PauseMenu"):getChild("CloseHelpButton"):show() + self.gameState.guiWindow:getChild("PauseMenu"):getChild("ResumeButton"):hide() + self.gameState.guiWindow:getChild("PauseMenu"):getChild("QuicksaveButton"):hide() + self.gameState.guiWindow:getChild("PauseMenu"):getChild("SaveGameButton"):hide() + self.gameState.guiWindow:getChild("PauseMenu"):getChild("LoadGameButton"):hide() + self.gameState.guiWindow:getChild("PauseMenu"):getChild("StatsButton"):hide() + self.gameState.guiWindow:getChild("PauseMenu"):getChild("HelpButton"):hide() + self.gameState.guiWindow:getChild("PauseMenu"):getChild("OptionsButton"):hide() + self.gameState.guiWindow:getChild("PauseMenu"):getChild("MainMenuButton"):hide() + self.gameState.guiWindow:getChild("PauseMenu"):getChild("QuitButton"):hide() self.helpOpen = not self.helpOpen end function MicrobeEditorHudSystem:closeHelpButtonClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):getChild("HelpPanel"):hide() - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):getChild("CloseHelpButton"):hide() - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):getChild("ResumeButton"):show() - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):getChild("QuicksaveButton"):show() - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):getChild("SaveGameButton"):show() - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):getChild("LoadGameButton"):show() - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):getChild("StatsButton"):show() - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):getChild("HelpButton"):show() - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):getChild("OptionsButton"):show() - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):getChild("MainMenuButton"):show() - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):getChild("QuitButton"):show() + getComponent("gui_sounds", g_luaEngine.currentGameState, SoundSourceComponent + ):playSound("button-hover-click") + self.gameState.guiWindow:getChild("PauseMenu"):getChild("HelpPanel"):hide() + self.gameState.guiWindow:getChild("PauseMenu"):getChild("CloseHelpButton"):hide() + self.gameState.guiWindow:getChild("PauseMenu"):getChild("ResumeButton"):show() + self.gameState.guiWindow:getChild("PauseMenu"):getChild("QuicksaveButton"):show() + self.gameState.guiWindow:getChild("PauseMenu"):getChild("SaveGameButton"):show() + self.gameState.guiWindow:getChild("PauseMenu"):getChild("LoadGameButton"):show() + self.gameState.guiWindow:getChild("PauseMenu"):getChild("StatsButton"):show() + self.gameState.guiWindow:getChild("PauseMenu"):getChild("HelpButton"):show() + self.gameState.guiWindow:getChild("PauseMenu"):getChild("OptionsButton"):show() + self.gameState.guiWindow:getChild("PauseMenu"):getChild("MainMenuButton"):show() + self.gameState.guiWindow:getChild("PauseMenu"):getChild("QuitButton"):show() self.helpOpen = not self.helpOpen end @@ -379,8 +385,8 @@ function MicrobeEditorHudSystem:removeClicked() end function MicrobeEditorHudSystem:rootSaveCreationClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") + getComponent("gui_sounds", g_luaEngine.currentGameState, SoundSourceComponent + ):playSound("button-hover-click") print ("Save button clicked") --[[ panel = self.saveLoadPanel @@ -393,8 +399,8 @@ function MicrobeEditorHudSystem:rootSaveCreationClicked() end --[[ function MicrobeEditorHudSystem:rootLoadCreationClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") + getComponent("gui_sounds", g_luaEngine.currentGameState, SoundSourceComponent + ):playSound("button-hover-click") panel = self.saveLoadPanel -- panel:getChild("SaveButton"):hide() -- root:getChild("CreationNameDialogLabel"):hide() @@ -418,8 +424,8 @@ function MicrobeEditorHudSystem:rootLoadCreationClicked() end function MicrobeEditorHudSystem:saveCreationClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") + getComponent("gui_sounds", g_luaEngine.currentGameState, SoundSourceComponent + ):playSound("button-hover-click") name = self.editor.currentMicrobe.microbe.speciesName print("saving "..name) -- Todo: Additional input sanitation @@ -432,8 +438,8 @@ function MicrobeEditorHudSystem:saveCreationClicked() end function MicrobeEditorHudSystem:loadCreationClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") + getComponent("gui_sounds", g_luaEngine.currentGameState, SoundSourceComponent + ):playSound("button-hover-click") item = self.creationsListbox:listWidgetGetFirstSelectedItemText() if self.creationFileMap[item] ~= nil then entity = Engine:loadCreation(self.creationFileMap[item]) @@ -495,20 +501,20 @@ function saveMicrobe() global_activeMicrobeEditorHudSystem:saveCreationClicked() function loadMicrobe(name) global_activeMicrobeEditorHudSystem:loadByName(name) end function MicrobeEditorHudSystem:menuButtonClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") + getComponent("gui_sounds", g_luaEngine.currentGameState, SoundSourceComponent + ):playSound("button-hover-click") print("played sound") - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):show() - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):moveToFront() + self.gameState.guiWindow:getChild("PauseMenu"):show() + self.gameState.guiWindow:getChild("PauseMenu"):moveToFront() Engine:pauseGame() self.menuOpen = true end function MicrobeEditorHudSystem:resumeButtonClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") + getComponent("gui_sounds", g_luaEngine.currentGameState, SoundSourceComponent + ):playSound("button-hover-click") print("played sound") - Engine:currentGameState():rootGUIWindow():getChild("PauseMenu"):hide() + self.gameState.guiWindow:getChild("PauseMenu"):hide() Engine:resumeGame() self.menuOpen = false end diff --git a/scripts/microbe_editor/setup.lua b/scripts/microbe_editor/setup.lua index 00d31e2c17e..414316ba4e8 100644 --- a/scripts/microbe_editor/setup.lua +++ b/scripts/microbe_editor/setup.lua @@ -1,55 +1,55 @@ -local function setupBackground() - local entity = Entity("background") - local skyplane = SkyPlaneComponent() +local function setupBackground(gameState) + local entity = Entity.new("background", gameState.wrapper) + local skyplane = SkyPlaneComponent.new() skyplane.properties.plane.normal = Vector3(0, 0, 2000) skyplane.properties.materialName = "background/blue_01" skyplane.properties.scale = 4 skyplane.properties:touch() entity:addComponent(skyplane) -- Create floating arrow entity - entity = Entity("directionarrow") - local sceneNode = OgreSceneNodeComponent() + entity = Entity.new("directionarrow", gameState.wrapper) + local sceneNode = OgreSceneNodeComponent.new() sceneNode.meshName = "arrow.mesh" sceneNode.transform.position = Vector3(0,7,-4) - sceneNode.transform.orientation = Quaternion(Radian(Degree(90)), Vector3(1, 1, 1)) + sceneNode.transform.orientation = Quaternion.new(Radian.new(Degree(90)), Vector3(1, 1, 1)) sceneNode.transform.scale = Vector3(0.5,0.5,0.5) sceneNode.transform:touch() sceneNode:playAnimation("Stand", true) entity:addComponent(sceneNode) end -local function setupCamera() - local entity = Entity(CAMERA_NAME .. "3") +local function setupCamera(gameState) + local entity = Entity.new(CAMERA_NAME .. "3", gameState.wrapper) -- Camera - local camera = OgreCameraComponent("camera3") + local camera = OgreCameraComponent.new("camera3") camera.properties.nearClipDistance = 5 camera.properties.orthographicalMode = true camera.properties.fovY = Degree(30.0) camera.properties:touch() entity:addComponent(camera) -- Scene node - local sceneNode = OgreSceneNodeComponent() + local sceneNode = OgreSceneNodeComponent.new() sceneNode.transform.position.z = 30 sceneNode.transform.position.y = -3 sceneNode.transform:touch() entity:addComponent(sceneNode) -- Light - local light = OgreLightComponent() + local light = OgreLightComponent.new() light:setRange(200) entity:addComponent(light) -- Workspace - local workspaceEntity = Entity() - local workspaceComponent = OgreWorkspaceComponent("thrive_default") + local workspaceEntity = Entity.new(gameState.wrapper) + local workspaceComponent = OgreWorkspaceComponent.new("thrive_default") workspaceComponent.properties.cameraEntity = entity workspaceComponent.properties.position = 0 workspaceComponent.properties:touch() workspaceEntity:addComponent(workspaceComponent) end -local function setupSound() - local ambientEntity = Entity("editor_ambience") - local soundSource = SoundSourceComponent() +local function setupSound(gameState) + local ambientEntity = Entity.new("editor_ambience", gameState.wrapper) + local soundSource = SoundSourceComponent.new() soundSource.autoLoop = true soundSource.ambientSoundSource = true soundSource.volumeMultiplier = 0.6 @@ -62,8 +62,8 @@ local function setupSound() soundSource:addSound("microbe-editor-theme-4", "microbe-editor-theme-4.ogg") soundSource:addSound("microbe-editor-theme-5", "microbe-editor-theme-5.ogg") -- Gui effects - local guiSoundEntity = Entity("gui_sounds") - soundSource = SoundSourceComponent() + local guiSoundEntity = Entity.new("gui_sounds", gameState.wrapper) + soundSource = SoundSourceComponent.new() soundSource.ambientSoundSource = true soundSource.autoLoop = false soundSource.volumeMultiplier = 1.0 @@ -71,8 +71,8 @@ local function setupSound() -- Sound soundSource:addSound("button-hover-click", "soundeffects/gui/button-hover-click.ogg") - local ambientEntity2 = Entity("editor_ambience2") - local soundSource2 = SoundSourceComponent() + local ambientEntity2 = Entity.new("editor_ambience2", gameState.wrapper) + local soundSource2 = SoundSourceComponent.new() soundSource2.volumeMultiplier = 0.1 soundSource2.ambientSoundSource = true soundSource2:addSound("microbe-ambient", "soundeffects/microbe-ambience.ogg") @@ -82,29 +82,31 @@ end local function createMicrobeEditor(name) - return Engine:createGameState( + return g_luaEngine:createGameState( name, { - -- MicrobeSystem(), - MicrobeEditorHudSystem(), + -- MicrobeSystem.new(), + MicrobeEditorHudSystem.new(), -- Graphics - OgreAddSceneNodeSystem(), - OgreUpdateSceneNodeSystem(), - OgreCameraSystem(), - OgreLightSystem(), - SkySystem(), - OgreWorkspaceSystem(), - OgreRemoveSceneNodeSystem(), - RenderSystem(), + OgreAddSceneNodeSystem.new(), + OgreUpdateSceneNodeSystem.new(), + OgreCameraSystem.new(), + OgreLightSystem.new(), + SkySystem.new(), + OgreWorkspaceSystem.new(), + OgreRemoveSceneNodeSystem.new(), + RenderSystem.new(), -- Other - SoundSourceSystem(), + SoundSourceSystem.new(), }, - function() - setupBackground() - setupCamera() - setupSound() - end, - "MicrobeEditor" + -- TODO: check whether physics is required in the editor + true, + "MicrobeEditor", + function(gameState) + setupBackground(gameState) + setupCamera(gameState) + setupSound(gameState) + end ) end diff --git a/scripts/microbe_stage/agent_vacuole.lua b/scripts/microbe_stage/agent_vacuole.lua index bf83f6765d2..c7d8a79ec83 100644 --- a/scripts/microbe_stage/agent_vacuole.lua +++ b/scripts/microbe_stage/agent_vacuole.lua @@ -1,33 +1,35 @@ -------------------------------------------------------------------------------- -- Class for Organelles capable of producing and storing agents -------------------------------------------------------------------------------- -class 'AgentVacuole' (OrganelleComponent) +AgentVacuole = class( + OrganelleComponent, + -- Constructor + -- + -- @param arguments.process + -- The process that creates the agent this organelle produces. + -- + -- @param arguments.compound + -- The agent this organelle produces. + function(self, arguments, data) --- See organelle_component.lua for more information about the --- organelle component methods and the arguments they receive. + OrganelleComponent.create(self, arguments, data) + + --making sure this doesn't run when load() is called + if arguments == nil and data == nil then + return + end --- Constructor --- --- @param arguments.process --- The process that creates the agent this organelle produces. --- --- @param arguments.compound --- The agent this organelle produces. -function AgentVacuole:__init(arguments, data) - OrganelleComponent.__init(self, arguments, data) - - --making sure this doesn't run when load() is called - if arguments == nil and data == nil then - return + self.position = {} + self.position.q = data.q + self.position.r = data.r + self.compoundId = CompoundRegistry.getCompoundId(arguments.compound) + self.capacityIntervalTimer = PROCESS_CAPACITY_UPDATE_INTERVAL + end +) - self.position = {} - self.position.q = data.q - self.position.r = data.r - self.compoundId = CompoundRegistry.getCompoundId(arguments.compound) - self.capacityIntervalTimer = PROCESS_CAPACITY_UPDATE_INTERVAL - return self -end +-- See organelle_component.lua for more information about the +-- organelle component methods and the arguments they receive. -- Overridded from ProcessOrganelle:onAddedToMicrobe function AgentVacuole:onAddedToMicrobe(microbe, q, r, rotation, organelle) @@ -58,7 +60,7 @@ end function AgentVacuole:storage() - local storage = StorageContainer() + local storage = StorageContainer.new() storage:set("compoundId", self.compoundId) storage:set("q", self.position.q) storage:set("r", self.position.r) diff --git a/scripts/microbe_stage/biome.lua b/scripts/microbe_stage/biome.lua index f08819b53fe..e906374cc10 100644 --- a/scripts/microbe_stage/biome.lua +++ b/scripts/microbe_stage/biome.lua @@ -2,7 +2,10 @@ currentBiome = {} --Setting the current biome to the one with the specified name. -function setBiome(biomeName) +function setBiome(biomeName, gameState) + + assert(gameState ~= nil, "setBiome requires gameState") + --Getting the base biome to change to. local baseBiome = biomeTable[biomeName] @@ -19,8 +22,8 @@ function setBiome(biomeName) end --Changing the background. - local entity = Entity("background") - local skyplane = SkyPlaneComponent() + local entity = Entity.new("background", gameState.wrapper) + local skyplane = SkyPlaneComponent.new() skyplane.properties.plane.normal = Vector3(0, 0, 2000) skyplane.properties.materialName = currentBiome.background skyplane.properties.scale = 200 @@ -29,7 +32,7 @@ function setBiome(biomeName) end --Setting the current biome to a random biome selected from the biome table. -function setRandomBiome() +function setRandomBiome(gameState) --Getting the size of the biome table. local numberOfBiomes = 0 local biomeNameTable = {} @@ -44,5 +47,5 @@ function setRandomBiome() local currentBiomeName = biomeNameTable[rand] --Switching to that biome. - setBiome(currentBiomeName) -end \ No newline at end of file + setBiome(currentBiomeName, gameState) +end diff --git a/scripts/microbe_stage/camera.lua b/scripts/microbe_stage/camera.lua index 0a672fd1322..e92d3be6968 100644 --- a/scripts/microbe_stage/camera.lua +++ b/scripts/microbe_stage/camera.lua @@ -1,28 +1,31 @@ -- This system updates the camera position to stay above the player microbe -class 'MicrobeCameraSystem' (System) +MicrobeCameraSystem = class( + LuaSystem, + function(self) -function MicrobeCameraSystem:__init() - System.__init(self) - -- The offset from player microbe to camera - self.camera = nil - self.cameraScenenode = nil -end + LuaSystem.create(self) + + -- The offset from player microbe to camera + self.camera = nil + self.cameraScenenode = nil + end +) -function MicrobeCameraSystem:init() - System.init(self, "MicrobeCameraSystem", gameState) +function MicrobeCameraSystem:init(gameState) + LuaSystem.init(self, "MicrobeCameraSystem", gameState) end function MicrobeCameraSystem:activate() - local camera = Entity(CAMERA_NAME) - self.camera = camera:getComponent(OgreCameraComponent.TYPE_ID) + local camera = Entity.new(CAMERA_NAME, self.gameState.wrapper) + self.camera = getComponent(camera, OgreCameraComponent) self.camera.properties.offset = Vector3(0, 0, 30) self.camera.properties:touch() - self.cameraScenenode = camera:getComponent(OgreSceneNodeComponent.TYPE_ID) + self.cameraScenenode = getComponent(camera, OgreSceneNodeComponent) end function MicrobeCameraSystem:update(renderTime, logicTime) - local player = Entity(PLAYER_NAME) - local playerNode = player:getComponent(OgreSceneNodeComponent.TYPE_ID) + local player = Entity.new(PLAYER_NAME, self.gameState.wrapper) + local playerNode = getComponent(player, OgreSceneNodeComponent) self.cameraScenenode.transform.position = playerNode.transform.position + self.camera.properties.offset self.cameraScenenode.transform:touch() end diff --git a/scripts/microbe_stage/configs.lua b/scripts/microbe_stage/configs.lua index 5cc8159e625..60fbd05a034 100644 --- a/scripts/microbe_stage/configs.lua +++ b/scripts/microbe_stage/configs.lua @@ -27,7 +27,7 @@ function toxinEffect(entityId) showMessage("Toxin Unlocked!") Engine:playerData():lockedMap():unlock("Toxin") local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("microbe-pickup-organelle") + getComponent(guiSoundEntity, SoundSourceComponent):playSound("microbe-pickup-organelle") end return true end @@ -38,7 +38,7 @@ function chloroplastEffect(entityId) showMessage("Chloroplast Unlocked!") Engine:playerData():lockedMap():unlock("chloroplast") local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("microbe-pickup-organelle") + getComponent(guiSoundEntity, SoundSourceComponent):playSound("microbe-pickup-organelle") end return true end diff --git a/scripts/microbe_stage/microbe.lua b/scripts/microbe_stage/microbe.lua index 58fa6723ec5..f5bf9c3e5a5 100644 --- a/scripts/microbe_stage/microbe.lua +++ b/scripts/microbe_stage/microbe.lua @@ -4,7 +4,37 @@ -- Holds data common to all microbes. You probably shouldn't use this directly, -- use the Microbe class (below) instead. -------------------------------------------------------------------------------- -class 'MicrobeComponent' (Component) +MicrobeComponent = class( + function(self, isPlayerMicrobe, speciesName) + + self.speciesName = speciesName + self.hitpoints = 0 + self.maxHitpoints = 0 + self.dead = false + self.deathTimer = 0 + self.organelles = {} + self.processOrganelles = {} -- Organelles responsible for producing compounds from other compounds + self.specialStorageOrganelles = {} -- Organelles with complete resonsiblity for a specific compound (such as agentvacuoles) + self.movementDirection = Vector3(0, 0, 0) + self.facingTargetPoint = Vector3(0, 0, 0) + self.movementFactor = 1.0 -- Multiplied on the movement speed of the microbe. + self.capacity = 0 -- The amount that can be stored in the microbe. NOTE: This does not include special storage organelles + self.stored = 0 -- The amount stored in the microbe. NOTE: This does not include special storage organelles + self.compounds = {} + self.initialized = false + self.isPlayerMicrobe = isPlayerMicrobe + self.maxBandwidth = 10.0*BANDWIDTH_PER_ORGANELLE + self.remainingBandwidth = 0 + self.compoundCollectionTimer = EXCESS_COMPOUND_COLLECTION_INTERVAL + self.isCurrentlyEngulfing = false + self.isBeingEngulfed = false + self.wasBeingEngulfed = false + self.hostileEngulfer = nil + + end +) + +MicrobeComponent.TYPE_NAME = "MicrobeComponent" COMPOUND_PROCESS_DISTRIBUTION_INTERVAL = 100 -- quantity of physics time between each loop distributing compounds to organelles. TODO: Modify to reflect microbe size. BANDWIDTH_PER_ORGANELLE = 1.0 -- amount the microbes maxmimum bandwidth increases with per organelle added. This is a temporary replacement for microbe surface area @@ -19,34 +49,7 @@ INITIAL_EMISSION_RADIUS = 0.5 ENGULFING_MOVEMENT_DIVISION = 3 ENGULFED_MOVEMENT_DIVISION = 4 ENGULFING_ATP_COST_SECOND = 1.5 -ENGULF_HP_RATIO_REQ = 1.5 - -function MicrobeComponent:__init(isPlayerMicrobe, speciesName) - Component.__init(self) - self.speciesName = speciesName - self.hitpoints = 0 - self.maxHitpoints = 0 - self.dead = false - self.deathTimer = 0 - self.organelles = {} - self.processOrganelles = {} -- Organelles responsible for producing compounds from other compounds - self.specialStorageOrganelles = {} -- Organelles with complete resonsiblity for a specific compound (such as agentvacuoles) - self.movementDirection = Vector3(0, 0, 0) - self.facingTargetPoint = Vector3(0, 0, 0) - self.movementFactor = 1.0 -- Multiplied on the movement speed of the microbe. - self.capacity = 0 -- The amount that can be stored in the microbe. NOTE: This does not include special storage organelles - self.stored = 0 -- The amount stored in the microbe. NOTE: This does not include special storage organelles - self.compounds = {} - self.initialized = false - self.isPlayerMicrobe = isPlayerMicrobe - self.maxBandwidth = 10.0*BANDWIDTH_PER_ORGANELLE - self.remainingBandwidth = 0 - self.compoundCollectionTimer = EXCESS_COMPOUND_COLLECTION_INTERVAL - self.isCurrentlyEngulfing = false - self.isBeingEngulfed = false - self.wasBeingEngulfed = false - self.hostileEngulfer = nil -end +ENGULF_HP_RATIO_REQ = 1.5 -- Attempts to obtain an amount of bandwidth for immediate use -- This should be in conjunction with most operations ejecting or absorbing compounds and agents for microbe @@ -71,9 +74,47 @@ function MicrobeComponent:regenerateBandwidth(logicTime) self.remainingBandwidth = math.min(addedBandwidth, self.maxBandwidth) end +function MicrobeComponent:storage(storage) + + -- Organelles + local organelles = StorageList.new() + for _, organelle in pairs(self.organelles) do + local organelleStorage = organelle:storage() + organelles:append(organelleStorage) + end + storage:set("organelles", organelles) + storage:set("hitpoints", self.hitpoints) + storage:set("speciesName", self.speciesName) + storage:set("maxHitpoints", self.maxHitpoints) + storage:set("remainingBandwidth", self.remainingBandwidth) + storage:set("maxBandwidth", self.maxBandwidth) + storage:set("isPlayerMicrobe", self.isPlayerMicrobe) + storage:set("speciesName", self.speciesName) + local storedCompounds = StorageList.new() + for _, compoundId in pairs(CompoundRegistry.getCompoundList()) do + --[[ + if self:getCompoundAmount(compoundId) > 0 then + compound = StorageContainer() + compound:set("compoundId", compoundId) + compound:set("amount", amount) + storedCompounds:append(compound) + end + --]] + end + storage:set("storedCompounds", storedCompounds) + -- local compoundPriorities = StorageList() + -- for compoundId, priority in pairs(self.compoundPriorities) do + -- compound = StorageContainer() + -- compound:set("compoundId", compoundId) + -- compound:set("priority", priority) + -- compoundPriorities:append(compound) + -- end + -- storage:set("compoundPriorities", compoundPriorities) + +end function MicrobeComponent:load(storage) - Component.load(self, storage) + local organelles = storage:get("organelles", {}) for i = 1,organelles:size() do local organelleStorage = organelles:get(i) @@ -106,10 +147,10 @@ function MicrobeComponent:load(storage) end -function MicrobeComponent:storage() - local storage = Component.storage(self) +function MicrobeComponent:storage(storage) + -- Organelles - local organelles = StorageList() + local organelles = StorageList.new() for _, organelle in pairs(self.organelles) do local organelleStorage = organelle:storage() organelles:append(organelleStorage) @@ -122,8 +163,8 @@ function MicrobeComponent:storage() storage:set("maxBandwidth", self.maxBandwidth) storage:set("isPlayerMicrobe", self.isPlayerMicrobe) storage:set("speciesName", self.speciesName) - local storedCompounds = StorageList() - for compoundId in CompoundRegistry.getCompoundList() do + local storedCompounds = StorageList.new() + for _, compoundId in pairs(CompoundRegistry.getCompoundList()) do --[[ if self:getCompoundAmount(compoundId) > 0 then compound = StorageContainer() @@ -142,7 +183,6 @@ function MicrobeComponent:storage() -- compoundPriorities:append(compound) -- end -- storage:set("compoundPriorities", compoundPriorities) - return storage end REGISTER_COMPONENT("MicrobeComponent", MicrobeComponent) @@ -153,7 +193,61 @@ REGISTER_COMPONENT("MicrobeComponent", MicrobeComponent) -- -- This class serves mostly as an interface for manipulating microbe entities -------------------------------------------------------------------------------- -class 'Microbe' +Microbe = class( + -- Constructor + -- + -- Requires all necessary components (see Microbe.COMPONENTS) to be present in + -- the entity. + -- + -- @param entity + -- The entity this microbe wraps + function(self, entity, in_editor) + + assert(entity ~= nil) + self.entity = entity + + for key, ctype in pairs(Microbe.COMPONENTS) do + local component = getComponent(entity, ctype) + assert(component ~= nil, "Can't create microbe from this entity, it's missing " .. key) + + self[key] = component + end + + for _, compound in pairs(CompoundRegistry.getCompoundList()) do + self.compoundAbsorber:setCanAbsorbCompound(compound, true) + end + if not self.microbe.initialized then + self:_initialize() + if in_editor ~= true then + local processor = getComponent(self.microbe.speciesName, + g_luaEngine.currentGameState, + ProcessorComponent) + assert(processor) + self.compoundBag:setProcessor(processor, + self.microbe.speciesName) + + SpeciesSystem.template(self, self:getSpeciesComponent()) + end + end + self:_updateCompoundAbsorber() + self.playerAlreadyShownAtpDamage = false + self.membraneHealth = 1.0 + self.reproductionStage = 0 -- 1 for G1 complete, 2 for S complete, 3 for G2 complete, and 4 for reproduction finished. + end +) + +-- I don't feel like checking for each component separately, so let's make a +-- loop do it with an assert for good measure (see Microbe.create) +Microbe.COMPONENTS = { + compoundAbsorber = CompoundAbsorberComponent, + microbe = MicrobeComponent, + rigidBody = RigidBodyComponent, + sceneNode = OgreSceneNodeComponent, + collisionHandler = CollisionComponent, + soundSource = SoundSourceComponent, + membraneComponent = MembraneComponent, + compoundBag = CompoundBagComponent +} -- Creates a new microbe with all required components @@ -164,26 +258,30 @@ class 'Microbe' -- @returns microbe -- An object of type Microbe -function Microbe.createMicrobeEntity(name, aiControlled, speciesName, in_editor) +function Microbe.createMicrobeEntity(name, aiControlled, speciesName, in_editor, gameState) + + assert(gameState ~= nil, "Microbe.createMicrobeEntity requires gameState") + assert(type(gameState) == "table") + local entity if name then - entity = Entity(name) + entity = Entity.new(name, gameState.wrapper) else - entity = Entity() + entity = Entity.new(gameState.wrapper) end - local rigidBody = RigidBodyComponent() - rigidBody.properties.shape = CompoundShape() + local rigidBody = RigidBodyComponent.new() + rigidBody.properties.shape = CompoundShape.new() rigidBody.properties.linearDamping = 0.5 rigidBody.properties.friction = 0.2 rigidBody.properties.mass = 0.0 rigidBody.properties.linearFactor = Vector3(1, 1, 0) rigidBody.properties.angularFactor = Vector3(0, 0, 1) rigidBody.properties:touch() - local reactionHandler = CollisionComponent() + local reactionHandler = CollisionComponent.new() reactionHandler:addCollisionGroup("microbe") - local membraneComponent = MembraneComponent() + local membraneComponent = MembraneComponent.new() - local soundComponent = SoundSourceComponent() + local soundComponent = SoundSourceComponent.new() local s1 = nil soundComponent:addSound("microbe-release-toxin", "soundeffects/microbe-release-toxin.ogg") soundComponent:addSound("microbe-toxin-damage", "soundeffects/microbe-toxin-damage.ogg") @@ -203,74 +301,36 @@ function Microbe.createMicrobeEntity(name, aiControlled, speciesName, in_editor) s1.properties:touch() local components = { - CompoundAbsorberComponent(), - OgreSceneNodeComponent(), - CompoundBagComponent(), - MicrobeComponent(not aiControlled, speciesName), + CompoundAbsorberComponent.new(), + OgreSceneNodeComponent.new(), + CompoundBagComponent.new(), + MicrobeComponent.new(not aiControlled, speciesName), reactionHandler, rigidBody, soundComponent, membraneComponent } if aiControlled then - local aiController = MicrobeAIControllerComponent() + local aiController = MicrobeAIControllerComponent.new() table.insert(components, aiController) end for _, component in ipairs(components) do entity:addComponent(component) end - return Microbe(entity, in_editor) -end - --- I don't feel like checking for each component separately, so let's make a --- loop do it with an assert for good measure (see Microbe.__init) -Microbe.COMPONENTS = { - compoundAbsorber = CompoundAbsorberComponent.TYPE_ID, - microbe = MicrobeComponent.TYPE_ID, - rigidBody = RigidBodyComponent.TYPE_ID, - sceneNode = OgreSceneNodeComponent.TYPE_ID, - collisionHandler = CollisionComponent.TYPE_ID, - soundSource = SoundSourceComponent.TYPE_ID, - membraneComponent = MembraneComponent.TYPE_ID, - compoundBag = CompoundBagComponent.TYPE_ID, -} - + + local newMicrobe = Microbe(entity, in_editor) + assert(newMicrobe) + assert(newMicrobe.microbe.initialized == true) --- Constructor --- --- Requires all necessary components (see Microbe.COMPONENTS) to be present in --- the entity. --- --- @param entity --- The entity this microbe wraps -function Microbe:__init(entity, in_editor) - self.entity = entity - for key, typeId in pairs(Microbe.COMPONENTS) do - local component = entity:getComponent(typeId) - assert(component ~= nil, "Can't create microbe from this entity, it's missing " .. key) - self[key] = entity:getComponent(typeId) - end - for compound in CompoundRegistry.getCompoundList() do - self.compoundAbsorber:setCanAbsorbCompound(compound, true) - end - if not self.microbe.initialized then - self:_initialize() - if in_editor == nil then - self.compoundBag:setProcessor(Entity(self.microbe.speciesName):getComponent(ProcessorComponent.TYPE_ID), self.microbe.speciesName) - SpeciesSystem.template(self, self:getSpeciesComponent()) - end - end - self:_updateCompoundAbsorber() - self.playerAlreadyShownAtpDamage = false - self.membraneHealth = 1.0 - self.reproductionStage = 0 -- 1 for G1 complete, 2 for S complete, 3 for G2 complete, and 4 for reproduction finished. + return newMicrobe end -- Getter for microbe species -- -- returns the species component or nil if it doesn't have a valid species function Microbe:getSpeciesComponent() - return Entity(self.microbe.speciesName):getComponent(SpeciesComponent.TYPE_ID) + return getComponent(self.microbe.speciesName, g_luaEngine.currentGameState, + SpeciesComponent) end -- Adds a new organelle @@ -296,9 +356,11 @@ function Microbe:addOrganelle(q, r, rotation, organelle) local x, y = axialToCartesian(q, r) local translation = Vector3(x, y, 0) -- Collision shape - self.rigidBody.properties.shape:addChildShape( + -- TODO: cache for performance + local compoundShape = CompoundShape.castFrom(self.rigidBody.properties.shape) + compoundShape:addChildShape( translation, - Quaternion(Radian(0), Vector3(1,0,0)), + Quaternion.new(Radian(0), Vector3(1,0,0)), organelle.collisionShape ) self.rigidBody.properties.mass = self.rigidBody.properties.mass + organelle.mass @@ -346,24 +408,6 @@ function Microbe:removeStorageOrganelle(storageOrganelle) self.microbe.capacity = self.microbe.capacity - storageOrganelle.capacity end --- Removes a process organelle --- This will be called automatically by process organelles removed with with removeOrganelle(...) --- --- @param processOrganelle --- An object of type ProcessOrganelle -function Microbe:removeProcessOrganelle(processOrganelle) - self.microbe.processOrganelles[processOrganelle] = nil -end - --- Adds a process organelle --- This will be called automatically by process organelles added with addOrganelle(...) --- --- @param processOrganelle --- An object of type ProcessOrganelle -function Microbe:addProcessOrganelle(processOrganelle) - self.microbe.processOrganelles[processOrganelle] = processOrganelle -end - -- Removes a special storage organelle -- This will be called automatically by process organelles removed with with removeOrganelle(...) -- @@ -422,7 +466,9 @@ function Microbe:removeOrganelle(q, r) self.rigidBody.properties.mass = self.rigidBody.properties.mass - organelle.mass self.rigidBody.properties:touch() - self.rigidBody.properties.shape:removeChildShape( + -- TODO: cache for performance + local compoundShape = CompoundShape.castFrom(self.rigidBody.properties.shape) + compoundShape:removeChildShape( organelle.collisionShape ) @@ -444,7 +490,7 @@ end -- @returns amount -- The amount stored in the microbe's storage oraganelles function Microbe:getCompoundAmount(compoundId) - return self.entity:getComponent(CompoundBagComponent.TYPE_ID):getCompoundAmount(compoundId) + return getComponent(self.entity, CompoundBagComponent):getCompoundAmount(compoundId) end -- Damages the microbe, killing it if its hitpoints drop low enough @@ -545,7 +591,9 @@ function Microbe:storeCompound(compoundId, amount, bandwidthLimited) storedAmount = self.microbe:getBandwidth(amount, compoundId) end storedAmount = math.min(storedAmount , self.microbe.capacity - self.microbe.stored) - self.entity:getComponent(CompoundBagComponent.TYPE_ID):giveCompound(tonumber(compoundId), storedAmount) + getComponent(self.entity, CompoundBagComponent + ):giveCompound(tonumber(compoundId), storedAmount) + self.microbe.stored = self.microbe.stored + storedAmount return amount - storedAmount end @@ -564,7 +612,9 @@ end function Microbe:takeCompound(compoundId, maxAmount) --if self.microbe.specialStorageOrganelles[compoundId] == nil then - local takenAmount = self.entity:getComponent(CompoundBagComponent.TYPE_ID):takeCompound(compoundId, maxAmount) + local takenAmount = getComponent(self.entity, CompoundBagComponent + ):takeCompound(compoundId, maxAmount) + self.microbe.stored = self.microbe.stored - takenAmount return takenAmount end @@ -577,6 +627,7 @@ end -- -- @param amount -- The amount to eject +local EJECTION_DISTANCE = 3.0 function Microbe:ejectCompound(compoundId, amount) -- The back of the microbe local exitX, exitY = axialToCartesian(0, 1) @@ -628,7 +679,7 @@ end function Microbe:kill() local compoundsToRelease = {} -- Eject the compounds that was in the microbe - for compoundId in CompoundRegistry.getCompoundList() do + for _, compoundId in pairs(CompoundRegistry.getCompoundList()) do local total = self:getCompoundAmount(compoundId) local ejectedAmount = self:takeCompound(compoundId, total) compoundsToRelease[compoundId] = ejectedAmount @@ -658,12 +709,12 @@ function Microbe:kill() _amount = _amount - ejectedAmount end end - local microbeSceneNode = self.entity:getComponent(OgreSceneNodeComponent.TYPE_ID) - local deathAnimationEntity = Entity() - local lifeTimeComponent = TimedLifeComponent() + local microbeSceneNode = getComponent(self.entity, OgreSceneNodeComponent) + local deathAnimationEntity = Entity.new(g_luaEngine.currentGameState.wrapper) + local lifeTimeComponent = TimedLifeComponent.new() lifeTimeComponent.timeToLive = 4000 deathAnimationEntity:addComponent(lifeTimeComponent) - local deathAnimSceneNode = OgreSceneNodeComponent() + local deathAnimSceneNode = OgreSceneNodeComponent.new() deathAnimSceneNode.meshName = "MicrobeDeath.mesh" deathAnimSceneNode:playAnimation("Death", false) deathAnimSceneNode.transform.position = Vector3(microbeSceneNode.transform.position.x, microbeSceneNode.transform.position.y, 0) @@ -697,17 +748,21 @@ function Microbe:readyToReproduce() end end -function Microbe:divide() +function Microbe:divide(currentGameState) + + assert(currentGameState, "Microbe:divide needs currentGameState") + print("dividing cell ") -- Create the two daughter cells. - local copy = Microbe.createMicrobeEntity(nil, true, self.microbe.speciesName) + local copy = Microbe.createMicrobeEntity(nil, true, self.microbe.speciesName, self.entity, + currentGameState) --Separate the two cells. copy.rigidBody.dynamicProperties.position = Vector3(self.rigidBody.dynamicProperties.position.x - self.membraneComponent.dimensions/2, self.rigidBody.dynamicProperties.position.y, 0) self.rigidBody.dynamicProperties.position = Vector3(self.rigidBody.dynamicProperties.position.x + self.membraneComponent.dimensions/2, self.rigidBody.dynamicProperties.position.y, 0) -- Split the compounds evenly between the two cells. - for compoundID in CompoundRegistry.getCompoundList() do + for _, compoundID in pairs(CompoundRegistry.getCompoundList()) do local amount = self:getCompoundAmount(compoundID) if amount ~= 0 then @@ -719,12 +774,12 @@ function Microbe:divide() self.reproductionStage = 0 copy.reproductionStage = 0 - copy.entity:addComponent(SpawnedComponent()) + copy.entity:addComponent(SpawnedComponent.new()) self.soundSource:playSound("microbe-reproduction") end function Microbe.transferCompounds(from, to) - for compoundID in CompoundRegistry.getCompoundList() do + for _, compoundID in pairs(CompoundRegistry.getCompoundList()) do local amount = from:getCompoundAmount(compoundID) if amount ~= 0 then @@ -767,27 +822,16 @@ function Microbe:flashMembraneColour(duration, colour) end end -function Microbe:calculateStorageSpace() - self.microbe.stored = 0 - for compoundId in CompoundRegistry.getCompoundList() do - self.microbe.stored = self.microbe.stored + self.entity:getComponent(CompoundBagComponent.TYPE_ID):getCompoundAmount(compoundId) - end -end -- Updates the microbe's state function Microbe:update(logicTime) if not self.microbe.dead then - --calculate storage. - self:calculateStorageSpace() - - self.compoundBag.storageSpace = self.microbe.capacity - -- StorageOrganelles self:_updateCompoundAbsorber() -- Regenerate bandwidth self.microbe:regenerateBandwidth(logicTime) -- Attempt to absorb queued compounds - for compound in self.compoundAbsorber:getAbsorbedCompounds() do + for _, compound in pairs(self.compoundAbsorber:getAbsorbedCompounds()) do local amount = self.compoundAbsorber:absorbedCompoundAmount(compound) if amount > 0.0 then self:storeCompound(compound, amount, true) @@ -831,7 +875,7 @@ function Microbe:update(logicTime) -- If the organelle is hurt. if organelle:getCompoundBin() < 1.0 then -- Give the organelle access to the compound bag to take some compound. - organelle:growOrganelle(self.entity:getComponent(CompoundBagComponent.TYPE_ID), logicTime) + organelle:growOrganelle(getComponent(self.entity, CompoundBagComponent), logicTime) -- An organelle was damaged and we tried to heal it, so out health might be different. self:calculateHealthFromOrganelles() end @@ -852,12 +896,12 @@ function Microbe:update(logicTime) -- If the organelle is not split, give it some compounds to make it larger. if organelle:getCompoundBin() < 2.0 and not organelle.wasSplit then -- Give the organelle access to the compound bag to take some compound. - organelle:growOrganelle(self.entity:getComponent(CompoundBagComponent.TYPE_ID), logicTime) + organelle:growOrganelle(getComponent(self.entity, CompoundBagComponent), logicTime) reproductionStageComplete = false -- If the organelle was split and has a bin less then 1, it must have been damaged. elseif organelle:getCompoundBin() < 1.0 and organelle.wasSplit then -- Give the organelle access to the compound bag to take some compound. - organelle:growOrganelle(self.entity:getComponent(CompoundBagComponent.TYPE_ID), logicTime) + organelle:growOrganelle(getComponent(self.entity, CompoundBagComponent), logicTime) -- If the organelle is twice its size... elseif organelle:getCompoundBin() >= 2.0 then --Queue this organelle for splitting after the loop. @@ -870,7 +914,7 @@ function Microbe:update(logicTime) -- If the nucleus hasn't finished replicating its DNA, give it some compounds. if organelle:getCompoundBin() < 2.0 then -- Give the organelle access to the compound back to take some compound. - organelle:growOrganelle(self.entity:getComponent(CompoundBagComponent.TYPE_ID), logicTime) + organelle:growOrganelle(getComponent(self.entity, CompoundBagComponent), logicTime) reproductionStageComplete = false end end @@ -1023,10 +1067,11 @@ function Microbe:validPlacement(organelle, q, r) end end +PURGE_SCALE = 0.4 function Microbe:purgeCompounds() local compoundAmountToDump = self.microbe.stored - self.microbe.capacity - compoundBag = self.entity:getComponent(CompoundBagComponent.TYPE_ID) + compoundBag = getComponent(self.entity, CompoundBagComponent) -- Uncomment to print compound economic information to the console. --[[ @@ -1040,7 +1085,7 @@ function Microbe:purgeCompounds() ]] -- Dumping all the useless compounds (with price = 0). - for compoundId in CompoundRegistry.getCompoundList() do + for _, compoundId in pairs(CompoundRegistry.getCompoundList()) do local price = compoundBag:getPrice(compoundId) if price <= 0 then local amountToEject = compoundBag:getCompoundAmount(compoundId) @@ -1053,8 +1098,9 @@ function Microbe:purgeCompounds() --Calculating each compound price to dump proportionally. local compoundPrices = {} local priceSum = 0 - for compoundId in CompoundRegistry.getCompoundList() do - local amount = self.entity:getComponent(CompoundBagComponent.TYPE_ID):getCompoundAmount(compoundId) + for _, compoundId in CompoundRegistry.getCompoundList() do + local amount = getComponent(self.entity, CompoundBagComponent) + :getCompoundAmount(compoundId) if amount > 0 then local price = compoundBag:getPrice(compoundId) @@ -1064,7 +1110,7 @@ function Microbe:purgeCompounds() end --Dumping each compound according to it's price. - for compoundId, price in pairs(compoundPrices) do + for _, compoundId, price in pairs(compoundPrices) do amountToEject = compoundAmountToDump * price / priceSum if amount > 0 then amountToEject = self:takeCompound(compoundId, amountToEject) end if amount > 0 then self:ejectCompound(compoundId, amountToEject) end @@ -1096,23 +1142,27 @@ function Microbe:respawn() self.rigidBody:setDynamicProperties( Vector3(0,0,0), -- Position - Quaternion(Radian(Degree(0)), Vector3(1, 0, 0)), -- Orientation + Quaternion.new(Radian.new(Degree(0)), Vector3(1, 0, 0)), -- Orientation Vector3(0, 0, 0), -- Linear velocity Vector3(0, 0, 0) -- Angular velocity ) - local sceneNode = self.entity:getComponent(OgreSceneNodeComponent.TYPE_ID) + local sceneNode = getComponent(self.entity, OgreSceneNodeComponent) sceneNode.visible = true sceneNode.transform.position = Vector3(0, 0, 0) sceneNode.transform:touch() self:storeCompound(CompoundRegistry.getCompoundId("atp"), 50, false) - setRandomBiome() + setRandomBiome(g_luaEngine.currentGameState) end -- Private function for initializing a microbe's components function Microbe:_initialize() - self.rigidBody.properties.shape:clear() + + -- TODO: cache for performance + local compoundShape = CompoundShape.castFrom(self.rigidBody.properties.shape) + assert(compoundShape ~= nil) + compoundShape:clear() self.rigidBody.properties.mass = 0.0 -- Organelles for s, organelle in pairs(self.microbe.organelles) do @@ -1162,8 +1212,9 @@ function Microbe:addComponent(component) self.entity:addComponent(component) end -function Microbe:getComponent(typeid) - return self.entity:getComponent(typeid) +function Microbe:getComponent(typeClass) + assert(type(typeClass) ~= "number", "using old syntax of Microbe:getComponent") + return getComponent(self.entity, typeClass) end @@ -1172,44 +1223,46 @@ end -- -- Updates microbes -------------------------------------------------------------------------------- - -class 'MicrobeSystem' (System) - -function MicrobeSystem:__init() - System.__init(self) - self.entities = EntityFilter( - { - CompoundAbsorberComponent, - MicrobeComponent, - OgreSceneNodeComponent, - RigidBodyComponent, - CollisionComponent - }, - true - ) - self.microbeCollisions = CollisionFilter( - "microbe", - "microbe" - ); - -- Temporary for 0.3.2, should be moved to separate system. - self.agentCollisions = CollisionFilter( - "microbe", - "agent" - ); - self.microbes = {} -end - +MicrobeSystem = class( + LuaSystem, + function(self) + + LuaSystem.create(self) + + self.entities = EntityFilter.new( + { + CompoundAbsorberComponent, + MicrobeComponent, + OgreSceneNodeComponent, + RigidBodyComponent, + CollisionComponent + }, + true + ) + self.microbeCollisions = CollisionFilter.new( + "microbe", + "microbe" + ); + -- Temporary for 0.3.2, should be moved to separate system. + self.agentCollisions = CollisionFilter.new( + "microbe", + "agent" + ); + self.microbes = {} + end +) function MicrobeSystem:init(gameState) - System.init(self, "MicrobeSystem", gameState) - self.entities:init(gameState) - self.microbeCollisions:init(gameState) + LuaSystem.init(self, "MicrobeSystem", gameState) + self.entities:init(gameState.wrapper) + self.microbeCollisions:init(gameState.wrapper) - self.agentCollisions:init(gameState) + self.agentCollisions:init(gameState.wrapper) end function MicrobeSystem:shutdown() + LuaSystem.shutdown(self) self.entities:shutdown() self.microbeCollisions:shutdown() @@ -1218,11 +1271,11 @@ end function MicrobeSystem:update(renderTime, logicTime) - for entityId in self.entities:removedEntities() do + for _, entityId in pairs(self.entities:removedEntities()) do self.microbes[entityId] = nil end - for entityId in self.entities:addedEntities() do - local microbe = Microbe(Entity(entityId)) + for _, entityId in pairs(self.entities:addedEntities()) do + local microbe = Microbe(Entity.new(entityId, self.gameState.wrapper)) self.microbes[entityId] = microbe end self.entities:clearChanges() @@ -1230,14 +1283,14 @@ function MicrobeSystem:update(renderTime, logicTime) microbe:update(logicTime) end -- Note that this triggers every frame there is a collision - for collision in self.microbeCollisions:collisions() do - local entity1 = Entity(collision.entityId1) - local entity2 = Entity(collision.entityId2) + for _, collision in pairs(self.microbeCollisions:collisions()) do + local entity1 = Entity.new(collision.entityId1, self.gameState.wrapper) + local entity2 = Entity.new(collision.entityId2, self.gameState.wrapper) if entity1:exists() and entity2:exists() then - local body1 = entity1:getComponent(RigidBodyComponent.TYPE_ID) - local body2 = entity2:getComponent(RigidBodyComponent.TYPE_ID) - local microbe1Comp = entity1:getComponent(MicrobeComponent.TYPE_ID) - local microbe2Comp = entity2:getComponent(MicrobeComponent.TYPE_ID) + local body1 = getComponent(entity1, RigidBodyComponent) + local body2 = getComponent(entity2, RigidBodyComponent) + local microbe1Comp = getComponent(entity1, MicrobeComponent) + local microbe2Comp = getComponent(entity2, MicrobeComponent) if body1~=nil and body2~=nil then -- Engulf initiation checkEngulfment(microbe1Comp, microbe2Comp, body1, entity1, entity2) @@ -1250,9 +1303,9 @@ function MicrobeSystem:update(renderTime, logicTime) -- TEMP, DELETE FOR 0.3.3!!!!!!!! - for collision in self.agentCollisions:collisions() do - local entity = Entity(collision.entityId1) - local agent = Entity(collision.entityId2) + for _, collision in pairs(self.agentCollisions:collisions()) do + local entity = Entity.new(collision.entityId1, self.gameState.wrapper) + local agent = Entity.new(collision.entityId2, self.gameState.wrapper) if entity:exists() and agent:exists() then Microbe(entity):damage(.5, "toxin") diff --git a/scripts/microbe_stage/microbe_ai.lua b/scripts/microbe_stage/microbe_ai.lua index 381efe7fe85..131e874c997 100644 --- a/scripts/microbe_stage/microbe_ai.lua +++ b/scripts/microbe_stage/microbe_ai.lua @@ -3,27 +3,29 @@ -- -- Component for identifying and determining AI controlled microbes. -------------------------------------------------------------------------------- -class 'MicrobeAIControllerComponent' (Component) OXYGEN_SEARCH_THRESHHOLD = 8 GLUCOSE_SEARCH_THRESHHOLD = 5 AI_MOVEMENT_SPEED = 0.5 +MicrobeAIControllerComponent = class( + function(self) -function MicrobeAIControllerComponent:__init() - Component.__init(self) - self.movementRadius = 20 - self.reevalutationInterval = 1000 - self.intervalRemaining = self.reevalutationInterval - self.direction = Vector3(0, 0, 0) - self.targetEmitterPosition = nil - self.searchedCompoundId = nil - self.prey = nil -end + self.movementRadius = 20 + self.reevalutationInterval = 1000 + self.intervalRemaining = self.reevalutationInterval + self.direction = Vector3(0, 0, 0) + self.targetEmitterPosition = nil + self.searchedCompoundId = nil + self.prey = nil + + end +) + +MicrobeAIControllerComponent.TYPE_NAME = "MicrobeAIControllerComponent" -function MicrobeAIControllerComponent:storage() - - local storage = Component.storage(self) +function MicrobeAIControllerComponent:storage(storage) + storage:set("movementRadius", self.movementRadius) storage:set("reevalutationInterval", self.reevalutationInterval) storage:set("intervalRemaining", self.intervalRemaining) @@ -38,11 +40,11 @@ function MicrobeAIControllerComponent:storage() else storage:set("searchedCompoundId", self.searchedCompoundId) end - return storage + end function MicrobeAIControllerComponent:load(storage) - Component.load(self, storage) + self.movementRadius = storage:get("movementRadius", 20) self.reevalutationInterval = storage:get("reevalutationInterval", 1000) self.intervalRemaining = storage:get("intervalRemaining", self.reevalutationInterval) @@ -68,56 +70,58 @@ REGISTER_COMPONENT("MicrobeAIControllerComponent", MicrobeAIControllerComponent) -- Updates AI controlled microbes -------------------------------------------------------------------------------- -class 'MicrobeAISystem' (System) - -function MicrobeAISystem:__init() - System.__init(self) - self.entities = EntityFilter( - { - MicrobeAIControllerComponent, - MicrobeComponent - }, - true - ) - self.emitters = EntityFilter( - { - CompoundEmitterComponent - }, - true - ) - self.microbes = {} - self.preyCandidates = {} - self.preyEntityToIndexMap = {} -- Used for removing from preyCandidates - self.currentPreyIndex = 0 - self.oxygenEmitters = {} - self.glucoseEmitters = {} -end - +MicrobeAISystem = class( + LuaSystem, + function(self) + + LuaSystem.create(self) + + self.entities = EntityFilter.new( + { + MicrobeAIControllerComponent, + MicrobeComponent + }, + true + ) + self.emitters = EntityFilter.new( + { + CompoundEmitterComponent + }, + true + ) + self.microbes = {} + self.preyCandidates = {} + self.preyEntityToIndexMap = {} -- Used for removing from preyCandidates + self.currentPreyIndex = 0 + self.oxygenEmitters = {} + self.glucoseEmitters = {} + + end +) function MicrobeAISystem:init(gameState) - System.init(self, "MicrobeAISystem", gameState) - self.entities:init(gameState) - self.emitters:init(gameState) + LuaSystem.init(self, "MicrobeAISystem", gameState) + self.entities:init(gameState.wrapper) + self.emitters:init(gameState.wrapper) end function MicrobeAISystem:shutdown() - System.shutdown(self) + LuaSystem.shutdown(self) self.entities:shutdown() self.emitters:shutdown() end - function MicrobeAISystem:update(renderTime, logicTime) - for entityId in self.entities:removedEntities() do + for _, entityId in pairs(self.entities:removedEntities()) do self.microbes[entityId] = nil if self.preyEntityToIndexMap[entityId] then self.preyCandidates[self.preyEntityToIndexMap[entityId]] = nil self.preyEntityToIndexMap[entityId] = nil end end - for entityId in self.entities:addedEntities() do - local microbe = Microbe(Entity(entityId)) + for _, entityId in pairs(self.entities:addedEntities()) do + local microbe = Microbe(Entity.new(entityId, self.gameState.wrapper)) self.microbes[entityId] = microbe -- This is a hack to remember up to 5 recent microbes as candidates for predators. @@ -128,12 +132,12 @@ function MicrobeAISystem:update(renderTime, logicTime) end - for entityId in self.emitters:removedEntities() do + for _, entityId in pairs(self.emitters:removedEntities()) do self.oxygenEmitters[entityId] = nil self.glucoseEmitters[entityId] = nil end - for entityId in self.emitters:addedEntities() do - local emitterComponent = Entity(entityId):getComponent(CompoundEmitterComponent.TYPE_ID) + for _, entityId in pairs(self.emitters:addedEntities()) do + local emitterComponent = getComponent(entityId, self.gameState, CompoundEmitterComponent) if emitterComponent ~= nil then -- TODO: Unsure why this is necessary if emitterComponent.compoundId == CompoundRegistry.getCompoundId("oxygen") then self.oxygenEmitters[entityId] = true @@ -145,7 +149,7 @@ function MicrobeAISystem:update(renderTime, logicTime) self.emitters:clearChanges() self.entities:clearChanges() for _, microbe in pairs(self.microbes) do - local aiComponent = microbe:getComponent(MicrobeAIControllerComponent.TYPE_ID) + local aiComponent = getComponent(microbe.entity, MicrobeAIControllerComponent) aiComponent.intervalRemaining = aiComponent.intervalRemaining + logicTime while aiComponent.intervalRemaining > aiComponent.reevalutationInterval do aiComponent.intervalRemaining = aiComponent.intervalRemaining - aiComponent.reevalutationInterval @@ -154,11 +158,12 @@ function MicrobeAISystem:update(renderTime, logicTime) local targetPosition = nil local agentVacuole = microbe.microbe.specialStorageOrganelles[compoundId] if agentVacuole ~= nil or microbe.microbe.maxHitpoints > 100 then - self.preyCandidates[6] = Microbe(Entity(PLAYER_NAME)) - self.preyEntityToIndexMap[Entity(PLAYER_NAME).id] = 6 + self.preyCandidates[6] = Microbe.new( + Entity.new(PLAYER_NAME, self.gameState.wrapper)) + self.preyEntityToIndexMap[Entity.new(PLAYER_NAME, self.gameState.wrapper).id] = 6 local attempts = 0 while (aiComponent.prey == nil or not aiComponent.prey:exists() or aiComponent.prey.microbe.dead or - (aiComponent.prey.microbe.speciesName == microbe.microbe.speciesName) or + (aiComponent.prey.microbe.speciesName == microbe.microbe.speciesName) or self.preyEntityToIndexMap[aiComponent.prey.entity.id] == nil) and attempts < 6 do aiComponent.prey = self.preyCandidates[rng:getInt(0, 6)] attempts = attempts + 1 @@ -190,8 +195,11 @@ function MicrobeAISystem:update(renderTime, logicTime) emitterArrayList[i] = emitterId end if i ~= 0 then - local emitterEntity = Entity(emitterArrayList[rng:getInt(1, i)]) - aiComponent.targetEmitterPosition = emitterEntity:getComponent(OgreSceneNodeComponent.TYPE_ID).transform.position + local emitterEntity = Entity.new( + emitterArrayList[rng:getInt(1, i)], self.gameState.wrapper) + + aiComponent.targetEmitterPosition = getComponent( + emitterEntity, OgreSceneNodeComponent).transform.position end end targetPosition = aiComponent.targetEmitterPosition @@ -201,7 +209,7 @@ function MicrobeAISystem:update(renderTime, logicTime) elseif microbe:getCompoundAmount(CompoundRegistry.getCompoundId("glucose")) <= GLUCOSE_SEARCH_THRESHHOLD then -- If we are NOT currenty heading towards an emitter if aiComponent.targetEmitterPosition == nil or aiComponent.searchedCompoundId ~= CompoundRegistry.getCompoundId("glucose") then - aiComponent.searchedCompoundId = CompoundRegistry.getCompoundId("glucose") + aiComponent.searchedCompoundId = CompoundRegistry.getCompoundId("glucose") local emitterArrayList = {} local i = 0 for emitterId, _ in pairs(self.glucoseEmitters) do @@ -209,8 +217,12 @@ function MicrobeAISystem:update(renderTime, logicTime) emitterArrayList[i] = emitterId end if i ~= 0 then - local emitterEntity = Entity(emitterArrayList[rng:getInt(1, i)]) - aiComponent.targetEmitterPosition = emitterEntity:getComponent(OgreSceneNodeComponent.TYPE_ID).transform.position + + local emitterEntity = Entity.new( + emitterArrayList[rng:getInt(1, i)], self.gameState.wrapper) + + aiComponent.targetEmitterPosition = getComponent( + emitterEntity, OgreSceneNodeComponent).transform.position end end targetPosition = aiComponent.targetEmitterPosition diff --git a/scripts/microbe_stage/microbe_control.lua b/scripts/microbe_stage/microbe_control.lua index 1311a36c598..34106c7ab65 100644 --- a/scripts/microbe_stage/microbe_control.lua +++ b/scripts/microbe_stage/microbe_control.lua @@ -1,21 +1,24 @@ -- System for processing player input in the microbe stage -class 'MicrobeControlSystem' (System) - -function MicrobeControlSystem:__init() - System.__init(self) -end +MicrobeControlSystem = class( + LuaSystem, + function(self) + + LuaSystem.create(self) + + end +) -function MicrobeControlSystem:init() - System.init(self, "MicrobeControlSystem", gameState) +function MicrobeControlSystem:init(gameState) + LuaSystem.init(self, "MicrobeControlSystem", gameState) end -- Computes the point the mouse cursor is at local function getTargetPoint() local mousePosition = Engine.mouse:normalizedPosition() - local playerCam = Entity(CAMERA_NAME) - local cameraComponent = playerCam:getComponent(OgreCameraComponent.TYPE_ID) + local playerCam = Entity.new(CAMERA_NAME, g_luaEngine.currentGameState.wrapper) + local cameraComponent = getComponent(playerCam, OgreCameraComponent) local ray = cameraComponent:getCameraToViewportRay(mousePosition.x, mousePosition.y) - local plane = Plane(Vector3(0, 0, 1), 0) + local plane = Plane.new(Vector3(0, 0, 1), 0) local intersects, t = ray:intersects(plane) return ray:getPoint(t) end @@ -24,16 +27,16 @@ end -- Sums up the directional input from the keyboard local function getMovementDirection() local direction = Vector3(0, 0, 0) - if (Engine.keyboard:isKeyDown(Keyboard.KC_W)) then + if (Engine.keyboard:isKeyDown(KEYCODE.KC_W)) then direction = direction + Vector3(0, 1, 0) end - if (Engine.keyboard:isKeyDown(Keyboard.KC_S)) then + if (Engine.keyboard:isKeyDown(KEYCODE.KC_S)) then direction = direction + Vector3(0, -1, 0) end - if (Engine.keyboard:isKeyDown(Keyboard.KC_A)) then + if (Engine.keyboard:isKeyDown(KEYCODE.KC_A)) then direction = direction + Vector3(-1, 0, 0) end - if (Engine.keyboard:isKeyDown(Keyboard.KC_D)) then + if (Engine.keyboard:isKeyDown(KEYCODE.KC_D)) then direction = direction + Vector3(1, 0, 0) end direction:normalise() @@ -42,8 +45,8 @@ end function MicrobeControlSystem:update(renderTime, logicTime) - local player = Entity("player") - local microbe = player:getComponent(MicrobeComponent.TYPE_ID) + local player = Entity.new("player", self.gameState.wrapper) + local microbe = getComponent(player, MicrobeComponent) if microbe and not microbe.dead then local targetPoint = getTargetPoint() local movementDirection = getMovementDirection() diff --git a/scripts/microbe_stage/microbe_replacement.lua b/scripts/microbe_stage/microbe_replacement.lua index 05aedf17a78..91b4334cb3b 100644 --- a/scripts/microbe_stage/microbe_replacement.lua +++ b/scripts/microbe_stage/microbe_replacement.lua @@ -1,22 +1,28 @@ -- Needs to be the first system -class 'MicrobeReplacementSystem' (System) +MicrobeReplacementSystem = class( + LuaSystem, + function(self) + + LuaSystem.create(self) + + --prefix,cofix,suffix list + self.speciesNamePrefix = {' Ce', ' Ar',' Sp', ' Th',' Co', ' So', ' Pu', ' Cr', ' Cy', + ' Gr', ' Re', ' Ty', ' Tr', ' Ac',' Pr' } + self.speciesNameCofix = { 'nan', 'mo', 'na', 'yt', 'yn', 'il', 'li','le', 'op', 'un', + 'rive','ec', 'ro','lar','im' } + self.speciesNameSuffix = { 'pien', 'olera', 'rius', 'nien', 'ster', 'ilia', 'canus', + 'tus', 'cys','ium','um'} + + end +) -- Global boolean for whether a new microbe is avaliable in the microbe editor. global_newEditorMicrobe = false --set it up so the game knows whether or not to replace the genus. global_genusPicked = false - -function MicrobeReplacementSystem:__init() - System.__init(self) - --prefix,cofix,suffix list - self.speciesNamePrefix = {' Ce', ' Ar',' Sp', ' Th',' Co', ' So', ' Pu', ' Cr', ' Cy', ' Gr', ' Re', ' Ty', ' Tr', ' Ac',' Pr' } - self.speciesNameCofix = { 'nan', 'mo', 'na', 'yt', 'yn', 'il', 'li','le', 'op', 'un', 'rive','ec', 'ro','lar','im' } - self.speciesNameSuffix = { 'pien', 'olera', 'rius', 'nien', 'ster', 'ilia', 'canus', 'tus', 'cys','ium','um'} -end - -function MicrobeReplacementSystem:init() - System.init(self, "MicrobeReplacementSystem", gameState) +function MicrobeReplacementSystem:init(gameState) + LuaSystem.init(self, "MicrobeReplacementSystem", gameState) end function MicrobeReplacementSystem:activate() @@ -24,8 +30,16 @@ function MicrobeReplacementSystem:activate() if Engine:playerData():isBoolSet("edited_microbe") then Engine:playerData():setBool("edited_microbe", false) + assert(self.gameState == g_luaEngine.currentGameState) + + -- This is ran in microbe gamestate + assert(self.gameState == GameState.MICROBE) + activeCreatureId = Engine:playerData():activeCreature() - local workingMicrobe = Microbe(Entity(activeCreatureId, GameState.MICROBE_EDITOR), true) + + -- This is the microbe entity in the editor gamestate + local workingMicrobe = Microbe.new( + Entity.new(activeCreatureId, GameState.MICROBE_EDITOR.wrapper), true) if not global_genusPicked then global_genusPicked = true; @@ -33,24 +47,41 @@ function MicrobeReplacementSystem:activate() end newSpeciesName = self:generateSpeciesName(); - local speciesEntity = Entity(newSpeciesName) - local species = SpeciesComponent(newSpeciesName) + local speciesEntity = Entity.new(newSpeciesName, self.gameState.wrapper) + local species = SpeciesComponent.new(newSpeciesName) speciesEntity:addComponent(species) SpeciesSystem.fromMicrobe(workingMicrobe, species) SpeciesSystem.initProcessorComponent(speciesEntity, species) - local newMicrobe = Microbe.createMicrobeEntity(nil, false, newSpeciesName) - newMicrobe:divide() - + local newMicrobe = Microbe.createMicrobeEntity(nil, false, newSpeciesName, + false, self.gameState) + newMicrobe:divide(self.gameState) + print(": "..newMicrobe.microbe.speciesName) newMicrobe.collisionHandler:addCollisionGroup("powerupable") - newMicrobeEntity = newMicrobe.entity:transfer(GameState.MICROBE) + + assert(GameState.MICROBE_EDITOR.entityManager) + assert(GameState.MICROBE) + + -- No clue why there was a transfer here before + -- newMicrobeEntity = Entity.new( + -- g_luaEngine:transferEntityGameState(newMicrobe.entity.id, + -- -- These game states are the same + -- self.gameState, + -- GameState.MICROBE), + -- GameState.MICROBE.wrapper) + + local newMicrobeEntity = newMicrobe.entity newMicrobeEntity:stealName(PLAYER_NAME) + + assert(self.gameState.entityManager:getNamedId(PLAYER_NAME, false) == + newMicrobeEntity.id) global_newEditorMicrobe = false - Engine:playerData():setActiveCreature(newMicrobeEntity.id, GameState.MICROBE) - + Engine:playerData():setActiveCreature(newMicrobeEntity.id, self.gameState.wrapper) + + -- Destroys the old entity inside the editor GameState workingMicrobe.entity:destroy() end end diff --git a/scripts/microbe_stage/microbe_stage_hud.lua b/scripts/microbe_stage/microbe_stage_hud.lua index 42af15c5c7b..7268cd096ee 100644 --- a/scripts/microbe_stage/microbe_stage_hud.lua +++ b/scripts/microbe_stage/microbe_stage_hud.lua @@ -1,24 +1,52 @@ +-- +-- TODO: merge the common things in microbe_stage_tutorial_hud +-- + -- Updates the hud with relevant information -class 'HudSystem' (System) - -function HudSystem:__init() - System.__init(self) - self.compoundListBox = nil - self.hitpointsCountLabel = nil - self.hitpointsMaxLabel = nil - self.hitpointsBar = nil - self.compoundListItems = {} - self.rootGuiWindow = nil - self.populationNumberLabel = nil - self.rootGUIWindow = nil - self.scrollChange = 0 + +HudSystem = class( + LuaSystem, + function(self) + + LuaSystem.create(self) + + self.compoundListBox = nil + self.hitpointsCountLabel = nil + self.hitpointsMaxLabel = nil + self.hitpointsBar = nil + self.compoundListItems = {} + self.rootGuiWindow = nil + self.populationNumberLabel = nil + self.rootGUIWindow = nil + self.scrollChange = 0 + + end +) + +function HudSystem:init(gameState) + LuaSystem.init(self, "HudSystem", gameState) +end + +function HudSystem:update(renderTime, logicTime) + -- TODO: use the QuickSaveSystem here? is this duplicated functionality? + local saveDown = Engine.keyboard:isKeyDown(KEYCODE.KC_F4) + local loadDown = Engine.keyboard:isKeyDown(KEYCODE.KC_F10) + if saveDown and not self.saveDown then + Engine:save("quick.sav") + end + if loadDown and not self.loadDown then + Engine:load("quick.sav") + end + self.saveDown = saveDown + self.loadDown = loadDown end global_if_already_displayed = false function HudSystem:activate() global_activeMicrobeStageHudSystem = self -- Global reference for event handlers + lockedMap = Engine:playerData():lockedMap() if lockedMap ~= nil and not lockedMap:isLocked("Toxin") and not ss and not global_if_already_displayed then showMessage("'E' Releases Toxin") @@ -32,7 +60,7 @@ function HudSystem:activate() end function HudSystem:init(gameState) - System.init(self, "MicrobeStageHudSystem", gameState) + LuaSystem.init(self, "MicrobeStageHudSystem", gameState) self.rootGUIWindow = gameState:rootGUIWindow() self.hitpointsBar = self.rootGUIWindow:getChild("HealthPanel"):getChild("LifeBar") self.hitpointsCountLabel = self.hitpointsBar:getChild("NumberLabel") @@ -112,8 +140,8 @@ end function HudSystem:update(renderTime) - local player = Entity("player") - local playerMicrobe = Microbe(player) + local player = Entity.new("player", self.gameState.wrapper) + local playerMicrobe = Microbe.new(player) self.hitpointsBar:progressbarSetProgress(playerMicrobe.microbe.hitpoints/playerMicrobe.microbe.maxHitpoints) self.hitpointsCountLabel:setText("".. math.floor(playerMicrobe.microbe.hitpoints)) @@ -182,11 +210,11 @@ function HudSystem:update(renderTime) if keyCombo(kmp.rightward) then playerMicrobe.soundSource:playSound("microbe-movement-1") end - if (Engine.keyboard:wasKeyPressed(Keyboard.KC_G)) then + if (Engine.keyboard:wasKeyPressed(KEYCODE.KC_G)) then playerMicrobe:toggleEngulfMode() end - local offset = Entity(CAMERA_NAME):getComponent(OgreCameraComponent.TYPE_ID).properties.offset + local offset = getComponent(CAMERA_NAME, self.gameState, OgreCameraComponent).properties.offset if Engine.mouse:scrollChange()/10 ~= 0 then self.scrollChange = self.scrollChange + Engine.mouse:scrollChange()/10 @@ -216,7 +244,12 @@ function HudSystem:update(renderTime) offset.z = newZVal end -function showReproductionDialog() global_activeMicrobeStageHudSystem:showReproductionDialog() end +function showReproductionDialog() + assert(global_activeMicrobeStageHudSystem ~= nil, + "no global active global_activeMicrobeStageHudSystem") + assert(global_activeMicrobeStageHudSystem.showReproductionDialog) + global_activeMicrobeStageHudSystem:showReproductionDialog() +end function HudSystem:showReproductionDialog() -- print("Reproduction Dialog called but currently disabled. Is it needed? Note that the editor button has been enabled") @@ -241,16 +274,14 @@ end --Event handlers function HudSystem:saveButtonClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") + getComponent("gui_sounds", self.gameState, SoundSourceComponent):playSound("button-hover-click") Engine:save("quick.sav") print("Game Saved"); --Because using update load button here doesn't seem to work unless you press save twice self.rootGUIWindow:getChild("PauseMenu"):getChild("LoadGameButton"):enable(); end function HudSystem:loadButtonClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") + getComponent("gui_sounds", self.gameState, SoundSourceComponent):playSound("button-hover-click") Engine:load("quick.sav") print("Game loaded"); self.rootGUIWindow:getChild("PauseMenu"):hide() @@ -258,8 +289,7 @@ function HudSystem:loadButtonClicked() end function HudSystem:menuButtonClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") + getComponent("gui_sounds", self.gameState, SoundSourceComponent):playSound("button-hover-click") print("played sound") self.rootGUIWindow:getChild("PauseMenu"):show() self.rootGUIWindow:getChild("PauseMenu"):moveToFront() @@ -269,8 +299,7 @@ function HudSystem:menuButtonClicked() end function HudSystem:resumeButtonClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") + getComponent("gui_sounds", self.gameState, SoundSourceComponent):playSound("button-hover-click") print("played sound") self.rootGUIWindow:getChild("PauseMenu"):hide() self:updateLoadButton(); @@ -280,8 +309,7 @@ end function HudSystem:toggleCompoundPanel() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") + getComponent("gui_sounds", self.gameState, SoundSourceComponent):playSound("button-hover-click") if self.compoundsOpen then self.rootGUIWindow:getChild("CompoundPanel"):hide() self.rootGUIWindow:getChild("CompoundExpandButton"):getChild("CompoundExpandIcon"):hide() @@ -296,8 +324,7 @@ function HudSystem:toggleCompoundPanel() end function HudSystem:helpButtonClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") + getComponent("gui_sounds", self.gameState, SoundSourceComponent):playSound("button-hover-click") self.rootGUIWindow:getChild("PauseMenu"):getChild("HelpPanel"):show() self.rootGUIWindow:getChild("PauseMenu"):getChild("CloseHelpButton"):show() self.rootGUIWindow:getChild("PauseMenu"):getChild("ResumeButton"):hide() @@ -313,8 +340,7 @@ function HudSystem:helpButtonClicked() end function HudSystem:closeHelpButtonClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") + getComponent("gui_sounds", self.gameState, SoundSourceComponent):playSound("button-hover-click") self.rootGUIWindow:getChild("PauseMenu"):getChild("HelpPanel"):hide() self.rootGUIWindow:getChild("PauseMenu"):getChild("CloseHelpButton"):hide() self.rootGUIWindow:getChild("PauseMenu"):getChild("ResumeButton"):show() @@ -330,28 +356,25 @@ function HudSystem:closeHelpButtonClicked() end function HudSystem:menuMainMenuClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") - Engine:setCurrentGameState(GameState.MAIN_MENU) + getComponent("gui_sounds", self.gameState, SoundSourceComponent):playSound("button-hover-click") + g_luaEngine:setCurrentGameState(GameState.MAIN_MENU) end function HudSystem:editorButtonClicked() - local player = Entity("player") - local playerMicrobe = Microbe(player) + local player = Entity.new("player", self.gameState.wrapper) + local playerMicrobe = Microbe.new(player) -- Return the first cell to its normal, non duplicated cell arangement. SpeciesSystem.restoreOrganelleLayout(playerMicrobe, playerMicrobe:getSpeciesComponent()) - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") + getComponent("gui_sounds", self.gameState, SoundSourceComponent):playSound("button-hover-click") self.editorButton:disable() - Engine:setCurrentGameState(GameState.MICROBE_EDITOR) + g_luaEngine:setCurrentGameState(GameState.MICROBE_EDITOR) end --[[ function HudSystem:returnButtonClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") + getComponent("gui_sounds", self.gameState, SoundSourceComponent):playSound("button-hover-click") --Engine:currentGameState():rootGUIWindow():getChild("MenuPanel"):hide() if Engine:currentGameState():name() == "microbe" then Engine:currentGameState():rootGUIWindow():getChild("HelpPanel"):hide() @@ -364,7 +387,8 @@ function HudSystem:returnButtonClicked() end --]] function quitButtonClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") + getComponent("gui_sounds", self.gameState, SoundSourceComponent):playSound("button-hover-click") Engine:quit() end + + diff --git a/scripts/microbe_stage/movement_organelle.lua b/scripts/microbe_stage/movement_organelle.lua index c69af371e84..dc3110fe733 100644 --- a/scripts/microbe_stage/movement_organelle.lua +++ b/scripts/microbe_stage/movement_organelle.lua @@ -1,5 +1,4 @@ -- Enables a microbe to move and turn -class 'MovementOrganelle' (OrganelleComponent) -- See organelle_component.lua for more information about the -- organelle component methods and the arguments they receive. @@ -18,31 +17,38 @@ local function calculateForce(q, r, momentum) end --- Constructor --- --- @param arguments.momentum --- The force this organelle can exert to move a microbe. --- --- @param arguments.torque --- The torque this organelle can exert to turn a microbe. -function MovementOrganelle:__init(arguments, data) - OrganelleComponent.__init(self, arguments, data) - - --making sure this doesn't run when load() is called - if arguments == nil and data == nil then - return +MovementOrganelle = class( + OrganelleComponent, + -- Constructor + -- + -- @param arguments.momentum + -- The force this organelle can exert to move a microbe. + -- + -- @param arguments.torque + -- The torque this organelle can exert to turn a microbe. + function(self, arguments, data) + + OrganelleComponent.create(self, arguments, data) + + --making sure this doesn't run when load() is called + if arguments == nil and data == nil then + return + end + + + self.energyMultiplier = 0.025 + self.force = calculateForce(data.q, data.r, arguments.momentum) + self.torque = arguments.torque + self.backwards_multiplier = 0 + self.x = 0 + self.y = 0 + self.angle = 0 + self.movingTail = false + end +) + - self.energyMultiplier = 0.025 - self.force = calculateForce(data.q, data.r, arguments.momentum) - self.torque = arguments.torque - self.backwards_multiplier = 0 - self.x = 0 - self.y = 0 - self.angle = 0 - self.movingTail = false - return self -end function MovementOrganelle:onAddedToMicrobe(microbe, q, r, rotation, organelle) local organelleX, organelleY = axialToCartesian(q, r) @@ -56,9 +62,22 @@ function MovementOrganelle:onAddedToMicrobe(microbe, q, r, rotation, organelle) angle = (angle * 180/math.pi + 180) % 360 self.sceneNode = organelle.sceneNode - self.sceneNode.transform.orientation = Quaternion(Radian(Degree(angle)), Vector3(0, 0, 1)) + self.sceneNode.transform.orientation = Quaternion.new(Radian.new(Degree(angle)), Vector3(0, 0, 1)) + self.sceneNode.transform.position = organelle.position.cartesian + self.sceneNode.transform.scale = Vector3(HEX_SIZE, HEX_SIZE, HEX_SIZE) + self.sceneNode.transform:touch() + self.sceneNode.parent = microbe.entity + -- self.sceneNode is a nullptr because it is already added to an entity + --organelle.organelleEntity:addComponent(self.sceneNode) + self.sceneNode:playAnimation("Move", true) self.sceneNode:setAnimationSpeed(0.25) + + --Adding a mesh to the organelle. + local mesh = organelleTable[organelle.name].mesh + if mesh ~= nil then + self.sceneNode.meshName = mesh + end end function MovementOrganelle:load(storage) @@ -69,7 +88,7 @@ function MovementOrganelle:load(storage) end function MovementOrganelle:storage() - local storage = StorageContainer() + local storage = StorageContainer.new() storage:set("energyMultiplier", self.energyMultiplier) storage:set("force", self.force) storage:set("torque", self.torque) @@ -97,6 +116,7 @@ function MovementOrganelle:_moveMicrobe(microbe, milliseconds) self.sceneNode:setAnimationSpeed(0.25) end local impulseMagnitude = microbe.microbe.movementFactor * milliseconds * forceMagnitude / 1000 + local impulse = impulseMagnitude * direction local a = microbe.sceneNode.transform.orientation * impulse microbe.rigidBody:applyCentralImpulse( diff --git a/scripts/microbe_stage/nucleus_organelle.lua b/scripts/microbe_stage/nucleus_organelle.lua index 2b8db2f41d0..742aabd012e 100644 --- a/scripts/microbe_stage/nucleus_organelle.lua +++ b/scripts/microbe_stage/nucleus_organelle.lua @@ -1,50 +1,59 @@ -------------------------------------------------------------------------------- -- Class for the single core organelle of any microbe -------------------------------------------------------------------------------- -class 'NucleusOrganelle' (OrganelleComponent) +NucleusOrganelle = class( + OrganelleComponent, + -- Constructor + function(self, arguments, data) --- See organelle_component.lua for more information about the --- organelle component methods and the arguments they receive. + OrganelleComponent.create(self, arguments, data) --- Constructor -function NucleusOrganelle:__init(arguments, data) - OrganelleComponent.__init(self, arguments, data) + --making sure this doesn't run when load() is called + if arguments == nil and data == nil then + return + end + + self.numProteinLeft = 2 + self.numNucleicAcidsLeft = 2 + self.nucleusCost = self.numProteinLeft + self.numNucleicAcidsLeft - --making sure this doesn't run when load() is called - if arguments == nil and data == nil then - return + self.golgi = Entity.new(g_luaEngine.currentGameState.wrapper) + self.ER = Entity.new(g_luaEngine.currentGameState.wrapper) + end +) + +-- See organelle_component.lua for more information about the +-- organelle component methods and the arguments they receive. - self.golgi = Entity() - self.ER = Entity() - return self -end -- Overridded from Organelle:onAddedToMicrobe function NucleusOrganelle:onAddedToMicrobe(microbe, q, r, rotation, organelle) local x, y = axialToCartesian(q-1, r-1) - local sceneNode1 = OgreSceneNodeComponent() + local sceneNode1 = OgreSceneNodeComponent.new() sceneNode1.meshName = "golgi.mesh" sceneNode1.transform.position = Vector3(x,y,0) sceneNode1.transform.scale = Vector3(HEX_SIZE, HEX_SIZE, HEX_SIZE) - sceneNode1.transform.orientation = Quaternion(Radian(Degree(rotation)), Vector3(0, 0, 1)) + sceneNode1.transform.orientation = Quaternion.new(Radian.new(Degree(rotation)), + Vector3(0, 0, 1)) sceneNode1.transform:touch() sceneNode1.parent = microbe.entity microbe.entity:addChild(self.golgi) self.golgi:addComponent(sceneNode1) - self.golgi.sceneNode = sceneNode1 + self.golgi_sceneNode = sceneNode1 self.golgi:setVolatile(true) - local sceneNode2 = OgreSceneNodeComponent() + local sceneNode2 = OgreSceneNodeComponent.new() sceneNode2.meshName = "ER.mesh" sceneNode2.transform.position = Vector3(0,0,0) sceneNode2.transform.scale = Vector3(HEX_SIZE, HEX_SIZE, HEX_SIZE) - sceneNode2.transform.orientation = Quaternion(Radian(Degree(rotation+10)), Vector3(0, 0, 1)) + sceneNode2.transform.orientation = Quaternion.new(Radian.new(Degree(rotation+10)), + Vector3(0, 0, 1)) sceneNode2.transform:touch() sceneNode2.parent = microbe.entity microbe.entity:addChild(self.ER) self.ER:addComponent(sceneNode2) - self.ER.sceneNode = sceneNode2 + self.ER_sceneNode = sceneNode2 self.ER:setVolatile(true) self.sceneNode = organelle.sceneNode @@ -54,6 +63,8 @@ function NucleusOrganelle:onAddedToMicrobe(microbe, q, r, rotation, organelle) local speciesColour = microbe:getSpeciesComponent().colour self.colourSuffix = "" .. math.floor(speciesColour.x * 256) .. math.floor(speciesColour.y * 256) .. math.floor(speciesColour.z * 256) end + + self._needsColourUpdate = true end function NucleusOrganelle:onRemovedFromMicrobe(microbe, q, r) @@ -61,9 +72,15 @@ function NucleusOrganelle:onRemovedFromMicrobe(microbe, q, r) self.ER:destroy() end +function NucleusOrganelle:storage() + + return StorageContainer.new() + +end + function NucleusOrganelle:load(storage) - self.golgi = Entity() - self.ER = Entity() + self.golgi = Entity.new(g_luaEngine.currentGameState.wrapper) + self.ER = Entity.new(g_luaEngine.currentGameState.wrapper) end function NucleusOrganelle:updateColour(organelle) @@ -82,3 +99,71 @@ function NucleusOrganelle:updateColour(organelle) organelle._needsColourUpdate = false end]] end + +-- Makes nucleus larger +function NucleusOrganelle:grow(compoundBagComponent) + -- Finds the total number of needed compounds. + local sum = 0 + + -- Finds which compounds the cell currently has. + if compoundBagComponent:aboveLowThreshold(CompoundRegistry.getCompoundId("aminoacids")) >= 1 then + sum = sum + self.numProteinLeft + end + if compoundBagComponent:aboveLowThreshold(CompoundRegistry.getCompoundId("aminoacids")) >= 1 then + sum = sum + self.numNucleicAcidsLeft + end + + -- If sum is 0, we either have no compounds, in which case we cannot grow the organelle, or the + -- DNA duplication is done (i.e. compoundBin = 2), in which case we wait for the microbe to + -- handle the split. + if sum == 0 then return end + + -- Randomly choose which of the three compounds: glucose, amino acids, and fatty acids + -- that are used in reproductions. + local id = math.random()*sum + + -- The random number is a protein, so attempt to take it. + if id <= self.numProteinLeft then + compoundBagComponent:takeCompound(CompoundRegistry.getCompoundId("aminoacids"), 1) + self.numProteinLeft = self.numProteinLeft - 1 + -- The random number is a nucleic acid. + else + compoundBagComponent:takeCompound(CompoundRegistry.getCompoundId("aminoacids"), 1) + self.numNucleicAcidsLeft = self.numNucleicAcidsLeft - 1 + end + + -- Calculate the new growth growth + self:recalculateBin() +end + +function NucleusOrganelle:damage(amount) + -- Calculate the total number of compounds we need to divide now, so that we can keep this ratio. + local totalLeft = self.numProteinLeft + self.numNucleicAcidsLeft + + -- Calculate how much compounds the organelle needs to have to result in a health equal to compoundBin - amount. + local damageFactor = (2.0 - self.compoundBin + amount) * self.nucleusCost / totalLeft + self.numProteinLeft = self.numProteinLeft * damageFactor + self.numNucleicAcidsLeft = self.numNucleicAcidsLeft * damageFactor + -- Calculate the new growth value. + self:recalculateBin() +end + +function NucleusOrganelle:recalculateBin() + -- Calculate the new growth growth + self.compoundBin = 2.0 - (self.numProteinLeft + self.numNucleicAcidsLeft)/self.nucleusCost + + -- If the organelle is damaged... + if self.compoundBin < 1.0 then + -- Make the nucleus smaller. + self.sceneNode.transform.scale = Vector3((1.0 + self.compoundBin)/2, (1.0 + self.compoundBin)/2, (1.0 + self.compoundBin)/2)*HEX_SIZE + self.sceneNode.transform:touch() + + if self.sceneNode.entity ~= nil then + self.sceneNode.entity:tintColour("nucleus" .. self.colourSuffix, ColourValue((1.0 + self.compoundBin)/2, self.compoundBin, self.compoundBin, 1.0)) + end + else + -- Darken the nucleus as more DNA is made. + self.sceneNode.entity:tintColour("nucleus" .. self.colourSuffix, ColourValue(2-self.compoundBin, 2-self.compoundBin, 2-self.compoundBin, 1.0)) + end +end + diff --git a/scripts/microbe_stage/organelle.lua b/scripts/microbe_stage/organelle.lua index 3732754446c..7e17d894b45 100644 --- a/scripts/microbe_stage/organelle.lua +++ b/scripts/microbe_stage/organelle.lua @@ -1,6 +1,3 @@ --- Container for organelle components for all the organelle components -class 'Organelle' - -- How fast organelles grow. GROWTH_SPEED_MULTILPIER = 0.5 / 1000 @@ -8,6 +5,61 @@ GROWTH_SPEED_MULTILPIER = 0.5 / 1000 -- upon death (between 0.0 and 1.0). COMPOUND_RELEASE_PERCENTAGE = 0.3 +-- Container for organelle components for all the organelle components +Organelle = class( + -- Constructor + function(self, mass, name) + + self.collisionShape = CompoundShape.new() + self.mass = mass + self.components = {} + self._hexes = {} + self.position = { + q = 0, + r = 0 + } + self.rotation = nil + + --Naming the organelle. + if name == nil then + self.name = "" + else + self.name = name + end + + -- The deviation of the organelle color from the species color + self._needsColourUpdate = true + + -- Whether or not this organelle has already divided. + self.split = false + -- If this organelle is a duplicate of another organelle caused by splitting. + self.isDuplicate = false + + -- The "Health Bar" of the organelle constrained to [0,2] + -- 0 means the organelle is dead, 1 means its normal, and 2 means + -- its ready to divide. + self.compoundBin = 1.0 + + -- The compounds left to divide this organelle. + -- Decreases every time a required compound is absorbed. + self.compoundsLeft = {} + + -- The compounds that make up this organelle. They get reduced each time + -- the organelle gets damaged. + self.composition = {} + + -- The total number of compounds we need before we can split. + self.organelleCost = 0 + + for compoundName, amount in pairs(organelleTable[name].composition) do + self.compoundsLeft[compoundName] = amount + self.composition[compoundName] = amount + self.organelleCost = self.organelleCost + amount + end + + end +) + -- Factory function for organelles function Organelle.loadOrganelle(storage) local name = storage:get("name", "") @@ -17,58 +69,6 @@ function Organelle.loadOrganelle(storage) return organelle end - --- Constructor -function Organelle:__init(mass, name) - self.collisionShape = CompoundShape() - self.mass = mass - self.components = {} - self._hexes = {} - self.position = { - q = 0, - r = 0 - } - self.rotation = nil - - --Naming the organelle. - if name == nil then - self.name = "" - else - self.name = name - end - - -- The deviation of the organelle color from the species color - self._needsColourUpdate = true - - -- Whether or not this organelle has already divided. - self.split = false - -- If this organelle is a duplicate of another organelle caused by splitting. - self.isDuplicate = false - - -- The "Health Bar" of the organelle constrained to [0,2] - -- 0 means the organelle is dead, 1 means its normal, and 2 means - -- its ready to divide. - self.compoundBin = 1.0 - - -- The compounds left to divide this organelle. - -- Decreases every time a required compound is absorbed. - self.compoundsLeft = {} - - -- The compounds that make up this organelle. They get reduced each time - -- the organelle gets damaged. - self.composition = {} - - -- The total number of compounds we need before we can split. - self.organelleCost = 0 - - for compoundName, amount in pairs(organelleTable[name].composition) do - self.compoundsLeft[compoundName] = amount - self.composition[compoundName] = amount - self.organelleCost = self.organelleCost + amount - end -end - - -- Adds a hex to this organelle -- -- @param q, r @@ -85,7 +85,7 @@ function Organelle:addHex(q, r) local hex = { q = q, r = r, - collisionShape = SphereShape(2) + collisionShape = SphereShape.new(2) } local x, y = axialToCartesian(q, r) local translation = Vector3(x, y, 0) @@ -93,7 +93,7 @@ function Organelle:addHex(q, r) -- Collision shape self.collisionShape:addChildShape( translation, - Quaternion(Radian(0), Vector3(1,0,0)), + Quaternion.new(Radian(0), Vector3(1,0,0)), hex.collisionShape ) self._hexes[s] = hex @@ -153,7 +153,7 @@ function Organelle:onAddedToMicrobe(microbe, q, r, rotation) self.position.cartesian = Vector3(x,y,0) self.rotation = rotation - self.organelleEntity = Entity() + self.organelleEntity = Entity.new(g_luaEngine.currentGameState.wrapper) self.organelleEntity:setVolatile(true) microbe.entity:addChild(self.organelleEntity) @@ -176,8 +176,9 @@ function Organelle:onAddedToMicrobe(microbe, q, r, rotation) end offset = offset / count - self.sceneNode = OgreSceneNodeComponent() - self.sceneNode.transform.orientation = Quaternion(Radian(Degree(self.rotation)), Vector3(0, 0, 1)) + self.sceneNode = OgreSceneNodeComponent.new() + self.sceneNode.transform.orientation = Quaternion.new(Radian.new(Degree(self.rotation)), + Vector3(0, 0, 1)) self.sceneNode.transform.position = offset + self.position.cartesian self.sceneNode.transform.scale = Vector3(HEX_SIZE, HEX_SIZE, HEX_SIZE) self.sceneNode.transform:touch() @@ -238,10 +239,10 @@ function Organelle:flashOrganelle(duration, colour) end function Organelle:storage() - local storage = StorageContainer() - local hexes = StorageList() + local storage = StorageContainer.new() + local hexes = StorageList.new() for _, hex in pairs(self._hexes) do - hexStorage = StorageContainer() + hexStorage = StorageContainer.new() hexStorage:set("q", hex.q) hexStorage:set("r", hex.r) hexes:append(hexStorage) @@ -257,7 +258,10 @@ function Organelle:storage() --iterating on each OrganelleComponent for componentName, component in pairs(self.components) do - storage:set(componentName, component:storage()) + local s = component:storage() + assert(isNotEmpty, componentName) + assert(s) + storage:set(componentName, s) end return storage @@ -298,7 +302,7 @@ function Organelle:update(microbe, logicTime) end -- Update each OrganelleComponent - for componentName, component in pairs(self.components) do + for _, component in pairs(self.components) do component:update(microbe, self, logicTime) end end @@ -447,7 +451,11 @@ function Organelle:removePhysics() end -- The basic organelle maker -class 'OrganelleFactory' +OrganelleFactory = class( + function(self) + + end +) -- Sets the color of the organelle (used in editor for valid/nonvalid placement) function OrganelleFactory.setColour(sceneNode, colour) @@ -465,7 +473,7 @@ function OrganelleFactory.makeOrganelle(data) --adding all of the components. for componentName, arguments in pairs(organelleInfo.components) do local componentType = _G[componentName] - organelle.components[componentName] = componentType(arguments, data) + organelle.components[componentName] = componentType.new(arguments, data) end --getting the hex table of the organelle rotated by the angle @@ -502,7 +510,8 @@ function OrganelleFactory.renderOrganelles(data) local y = organelleY + hexY local translation = Vector3(-x, -y, 0) data.sceneNode[i].transform.position = translation - data.sceneNode[i].transform.orientation = Quaternion(Radian(Degree(data.rotation)), Vector3(0, 0, 1)) + data.sceneNode[i].transform.orientation = Quaternion.new( + Radian.new(Degree(data.rotation)), Vector3(0, 0, 1)) xSum = xSum + x ySum = ySum + y i = i + 1 @@ -517,7 +526,8 @@ function OrganelleFactory.renderOrganelles(data) if(mesh ~= nil) then data.sceneNode[1].meshName = mesh data.sceneNode[1].transform.position = Vector3(-xAverage, -yAverage, 0) - data.sceneNode[1].transform.orientation = Quaternion(Radian(Degree(data.rotation)), Vector3(0, 0, 1)) + data.sceneNode[1].transform.orientation = Quaternion.new( + Radian.new(Degree(data.rotation)), Vector3(0, 0, 1)) end end end diff --git a/scripts/microbe_stage/organelle_component.lua b/scripts/microbe_stage/organelle_component.lua index a0c5dc99154..a7b44eeb1a3 100644 --- a/scripts/microbe_stage/organelle_component.lua +++ b/scripts/microbe_stage/organelle_component.lua @@ -1,18 +1,39 @@ --Base class for organelle components. -class "OrganelleComponent" +OrganelleComponent = class( + -- Constructor. + -- + -- @param arguments + -- The parameters of the constructor, defined in organelle_table.lua. + -- + -- @param data + -- The organelle data taken from the make function in organelle.lua. + -- + -- The return value should be the organelle component itself (A.K.A. self) + function(self, arguments, data) --- Constructor. --- --- @param arguments --- The parameters of the constructor, defined in organelle_table.lua. --- --- @param data --- The organelle data taken from the make function in organelle.lua. --- --- The return value should be the organelle component itself (A.K.A. self) -function OrganelleComponent:__init(arguments, data) - return self -end + -- TODO: All organelles except the nucleus use the following compound + -- amounts to reproduce. This should be changed to use getter/setters + -- as well as unique compound amounts for each component types. + + + -- The "Health Bar" of the organelle constrained to [0,2] + -- 0 means the organelle is dead, 1 means its normal, and 2 means + -- its ready to divide. + self.compoundBin = 1.0 + -- The compounds left to divide this organelle. + -- Decreases every time one compound is absorbed. + self.numGlucose = 2 + self.numAminoAcids = 3 + self.numFattyAcids = 0 + -- The compounds that make up this organelle. + self.numGlucoseLeft = self.numGlucose + self.numAminoAcidsLeft = self.numAminoAcids + self.numFattyAcidsLeft = self.numFattyAcids + -- The total number of compounds we need before we can split. + self.organelleCost = self.numGlucose + self.numAminoAcids + self.numFattyAcids + + end +) -- Event handler for an organelle added to a microbe. -- @@ -74,7 +95,7 @@ end -- The return value should be a new StorageContainer object -- filled with the data to save. function OrganelleComponent:storage() - return StorageContainer() + return StorageContainer.new() end -- Function for loading organelle information. diff --git a/scripts/microbe_stage/patch_system.lua b/scripts/microbe_stage/patch_system.lua index 388861a41a1..2e75301795f 100644 --- a/scripts/microbe_stage/patch_system.lua +++ b/scripts/microbe_stage/patch_system.lua @@ -4,13 +4,14 @@ -- Controls population management within a certain region of space -------------------------------------------------------------------------------- -class "PatchComponent" (Component) +PatchComponent = class( + function(self) + -- map species to populations + -- model environment + end +) -function PatchComponent:__init() - Component.__init(self) - -- map species to populations - -- model environment -end +PatchComponent.TYPE_NAME = "PatchComponent" --[[ We need a bunch of stuff handled here: @@ -40,13 +41,13 @@ REGISTER_COMPONENT("PatchComponent", PatchComponent) -- -- Holds information about a specific population (species \intersect patch) -------------------------------------------------------------------------------- -class 'Population' - -function Population:__init(species) - self.species = species - self.heldCompounds = {} -- compounds that are available for intracellular processes - self.lockedCompounds = {} -- compounds that aren't, but will be released on deaths -end +Population = class( + function(self, species) + self.species = species + self.heldCompounds = {} -- compounds that are available for intracellular processes + self.lockedCompounds = {} -- compounds that aren't, but will be released on deaths + end +) --[[ Whatever population calculations the patch does that would be useful to factor out will go here @@ -64,33 +65,35 @@ Getting the effective population number from the lockedCompounds pool is a bit c -- System for simulating populations of species and their spatial distributions -------------------------------------------------------------------------------- -class "PatchSystem" (System) +PatchSystem = class( + LuaSystem, + function(self) -PATCH_SIM_INTERVAL = 1200 + LuaSystem.create(self) -function PatchSystem:__init() - System.__init(self) + self.entities = EntityFilter.new( + { + PatchComponent + }, + true + ) + self.timeSinceLastCycle = 0 - self.entities = EntityFilter( - { - PatchComponent - }, - true - ) - self.timeSinceLastCycle = 0 -end + end +) +PATCH_SIM_INTERVAL = 1200 -- Override from System function PatchSystem:init(gameState) - System.init(self, "PatchSystem", gameState) - self.entities:init(gameState) + LuaSystem.init(self, "PatchSystem", gameState) + self.entities:init(gameState.wrapper) end -- Override from System function PatchSystem:shutdown() self.entities:shutdown() - System.shutdown(self) + LuaSystem.shutdown(self) end -- Override from System diff --git a/scripts/microbe_stage/process_organelle.lua b/scripts/microbe_stage/process_organelle.lua index b61a8e87f9b..c2b76569c91 100644 --- a/scripts/microbe_stage/process_organelle.lua +++ b/scripts/microbe_stage/process_organelle.lua @@ -1,28 +1,30 @@ -------------------------------------------------------------------------------- -- Class for Organelles capable of producing compounds -------------------------------------------------------------------------------- -class 'ProcessOrganelle' (OrganelleComponent) +ProcessOrganelle = class( + OrganelleComponent, + -- Constructor + -- + -- @param arguments.colourChangeFactor + -- I got absolutely no idea + -- what this does :P. Also it doesn't seem to be used anymore + function(self, arguments, data) + + OrganelleComponent.create(self, arguments, data) + + --making sure this doesn't run when load() is called + if arguments == nil and data == nil then + return + end + + end +) -- See organelle_component.lua for more information about the -- organelle component methods and the arguments they receive. PROCESS_CAPACITY_UPDATE_INTERVAL = 1000 --- Constructor --- --- @param arguments.colourChangeFactor --- I got absolutely no idea what this does :P. -function ProcessOrganelle:__init(arguments, data) - OrganelleComponent.__init(self, arguments, data) - - --making sure this doesn't run when load() is called - if arguments == nil and data == nil then - return - end - - return self -end - -- Adds a process to the processing organelle -- The organelle will distribute its capacity between processes -- @@ -38,8 +40,8 @@ function ProcessOrganelle:onAddedToMicrobe(microbe, q, r, rotation, organelle) OrganelleComponent.onAddedToMicrobe(self, microbe, q, r, rotation, organelle) end -function ProcessOrganelle:storage(storage) - local storage = StorageContainer() +function ProcessOrganelle:storage() + local storage = StorageContainer.new() return storage end diff --git a/scripts/microbe_stage/setup.lua b/scripts/microbe_stage/setup.lua index 71e038ac930..a4a7ba0565e 100644 --- a/scripts/microbe_stage/setup.lua +++ b/scripts/microbe_stage/setup.lua @@ -1,30 +1,30 @@ CLOUD_SPAWN_RADIUS = 50 CLOUD_SPAWN_DENSITY = 1/5000 -local function setupBackground() - setRandomBiome() +local function setupBackground(gameState) + setRandomBiome(gameState) end -local function setupCamera() - local entity = Entity(CAMERA_NAME) +local function setupCamera(gameState) + local entity = Entity.new(CAMERA_NAME, gameState.wrapper) -- Camera - local camera = OgreCameraComponent("camera") + local camera = OgreCameraComponent.new("camera") camera.properties.nearClipDistance = 5 - camera.offset = Vector3(0, 0, 30) + camera.properties.offset = Vector3(0, 0, 30) camera.properties:touch() entity:addComponent(camera) -- Scene node - local sceneNode = OgreSceneNodeComponent() + local sceneNode = OgreSceneNodeComponent.new() sceneNode.transform.position.z = 30 sceneNode.transform:touch() entity:addComponent(sceneNode) -- Light - local light = OgreLightComponent() + local light = OgreLightComponent.new() light:setRange(200) entity:addComponent(light) -- Workspace - local workspaceEntity = Entity() - local workspaceComponent = OgreWorkspaceComponent("thrive_default") + local workspaceEntity = Entity.new(gameState.wrapper) + local workspaceComponent = OgreWorkspaceComponent.new("thrive_default") workspaceComponent.properties.cameraEntity = entity workspaceComponent.properties.position = 0 workspaceComponent.properties:touch() @@ -47,12 +47,12 @@ local function setupCompounds() CompoundRegistry.loadFromLua({}, agents) end -local function setupCompoundClouds() +local function setupCompoundClouds(gameState) for compoundName, compoundInfo in pairs(compoundTable) do if compoundInfo.isCloud then local compoundId = CompoundRegistry.getCompoundId(compoundName) - local entity = Entity("compound_cloud_" .. compoundName) - local compoundCloud = CompoundCloudComponent() + local entity = Entity.new("compound_cloud_" .. compoundName, gameState.wrapper) + local compoundCloud = CompoundCloudComponent.new() local colour = compoundInfo.colour compoundCloud:initialize(compoundId, colour.r, colour.g, colour.b) entity:addComponent(compoundCloud) @@ -61,10 +61,11 @@ local function setupCompoundClouds() end local function setupProcesses() + assert(processes) BioProcessRegistry.loadFromLua(processes) end -function setupSpecies() +function setupSpecies(gameState) --[[ This function should be the entry point for all initial-species generation For now, it can go through the XML and instantiate all the species, but later this @@ -73,8 +74,8 @@ function setupSpecies() ]] for name, data in pairs(starter_microbes) do - speciesEntity = Entity(name) - speciesComponent = SpeciesComponent(name) + speciesEntity = Entity.new(name, gameState.wrapper) + speciesComponent = SpeciesComponent.new(name) speciesEntity:addComponent(speciesComponent) for i, organelle in pairs(data.organelles) do local org = {} @@ -84,12 +85,12 @@ function setupSpecies() org.rotation = organelle.rotation speciesComponent.organelles[i] = org end - processorComponent = ProcessorComponent() + processorComponent = ProcessorComponent.new() speciesEntity:addComponent(processorComponent) speciesComponent.colour = Vector3(data.colour.r, data.colour.g, data.colour.b) -- iterates over all compounds, and sets amounts and priorities - for compoundID in CompoundRegistry.getCompoundList() do + for _, compoundID in pairs(CompoundRegistry.getCompoundList()) do compound = CompoundRegistry.getCompoundInternalName(compoundID) compoundData = data.compounds[compound] if compoundData ~= nil then @@ -113,7 +114,7 @@ function setupSpecies() end end end - for bioProcessId in BioProcessRegistry.getList() do + for _, bioProcessId in pairs(BioProcessRegistry.getList()) do local name = BioProcessRegistry.getInternalName(bioProcessId) if capacities[name] ~= nil then processorComponent:setCapacity(bioProcessId, capacities[name]) @@ -125,12 +126,16 @@ function setupSpecies() end -- speciesName decides the template to use, while individualName is used for referencing the instance -function microbeSpawnFunctionGeneric(pos, speciesName, aiControlled, individualName) - local microbe = Microbe.createMicrobeEntity(individualName, aiControlled, speciesName) +function microbeSpawnFunctionGeneric(pos, speciesName, aiControlled, individualName, gameState) + + assert(gameState ~= nil) + + local microbe = Microbe.createMicrobeEntity(individualName, aiControlled, speciesName, + false, gameState) if pos ~= nil then microbe.rigidBody:setDynamicProperties( pos, -- Position - Quaternion(Radian(Degree(0)), Vector3(1, 0, 0)), -- Orientation + Quaternion.new(Radian.new(Degree(0)), Vector3(1, 0, 0)), -- Orientation Vector3(0, 0, 0), -- Linear velocity Vector3(0, 0, 0) -- Angular velocity ) @@ -140,21 +145,21 @@ end local function setSpawnablePhysics(entity, pos, mesh, scale, collisionShape) -- Rigid body - local rigidBody = RigidBodyComponent() + local rigidBody = RigidBodyComponent.new() rigidBody.properties.friction = 0.2 rigidBody.properties.linearDamping = 0.8 rigidBody.properties.shape = collisionShape rigidBody:setDynamicProperties( pos, - Quaternion(Radian(Degree(math.random()*360)), Vector3(0, 0, 1)), + Quaternion.new(Radian.new(Degree(math.random()*360)), Vector3(0, 0, 1)), Vector3(0, 0, 0), Vector3(0, 0, 0) ) rigidBody.properties:touch() entity:addComponent(rigidBody) -- Scene node - local sceneNode = OgreSceneNodeComponent() + local sceneNode = OgreSceneNodeComponent.new() sceneNode.meshName = mesh sceneNode.transform.scale = Vector3(scale, scale, scale) entity:addComponent(sceneNode) @@ -166,61 +171,49 @@ function createCompoundCloud(compoundName, x, y, amount) if amount == nil then amount = 0 end if compoundTable[compoundName] and compoundTable[compoundName].isCloud then - Entity("compound_cloud_" .. compoundName):getComponent(CompoundCloudComponent.TYPE_ID):addCloud(amount, x, y) + -- addCloud requires integer arguments + x = math.floor(x) + y = math.floor(y) + getComponent("compound_cloud_" .. compoundName, + g_luaEngine.currentGameState, CompoundCloudComponent + ):addCloud(amount, x, y) end end -function createAgentCloud(compoundId, x, y, direction, amount) - -- local entity = Entity() - -- local sceneNode = OgreSceneNodeComponent() - -- sceneNode.meshName = "oxytoxy.mesh" - -- sceneNode.transform.position = Vector3(x + direction.x/2, y + direction.y/2, 0) - -- sceneNode.transform:touch() - -- local agent = AgentCloudComponent() - -- agent:initialize(compoundId, 255, 0, 255) - -- agent.direction = direction*2 - -- agent.potency = amount - -- entity:addComponent(sceneNode) - -- entity:addComponent(agent) - +function createAgentCloud(compoundId, x, y, direction, amount) - local agentEntity = Entity() + local agentEntity = Entity.new(g_luaEngine.currentGameState.wrapper) - local reactionHandler = CollisionComponent() + local reactionHandler = CollisionComponent.new() reactionHandler:addCollisionGroup("agent") agentEntity:addComponent(reactionHandler) - local rigidBody = RigidBodyComponent() + local rigidBody = RigidBodyComponent.new() rigidBody.properties.mass = 0.001 rigidBody.properties.friction = 0.4 rigidBody.properties.linearDamping = 0.4 - rigidBody.properties.shape = SphereShape(HEX_SIZE) + rigidBody.properties.shape = SphereShape.new(HEX_SIZE) rigidBody:setDynamicProperties( Vector3(x,y,0) + direction, - Quaternion(Radian(Degree(math.random()*360)), Vector3(0, 0, 1)), + Quaternion.new(Radian.new(Degree(math.random()*360)), Vector3(0, 0, 1)), direction * 3, Vector3(0, 0, 0) ) rigidBody.properties:touch() agentEntity:addComponent(rigidBody) - local sceneNode = OgreSceneNodeComponent() + local sceneNode = OgreSceneNodeComponent.new() sceneNode.meshName = "oxytoxy.mesh" agentEntity:addComponent(sceneNode) - local timedLifeComponent = TimedLifeComponent() + local timedLifeComponent = TimedLifeComponent.new() timedLifeComponent.timeToLive = 2000 agentEntity:addComponent(timedLifeComponent) end --- Copy paste for quick debugging. Prints the line of the print statement. -function printLine() - print(debug.getinfo(1).currentline) -end - local function addEmitter2Entity(entity, compound) - local compoundEmitter = CompoundEmitterComponent() + local compoundEmitter = CompoundEmitterComponent.new() entity:addComponent(compoundEmitter) compoundEmitter.emissionRadius = 1 compoundEmitter.maxInitialSpeed = 10 @@ -228,7 +221,7 @@ local function addEmitter2Entity(entity, compound) compoundEmitter.minEmissionAngle = Degree(0) compoundEmitter.maxEmissionAngle = Degree(360) compoundEmitter.particleLifeTime = 5000 - local timedEmitter = TimedCompoundEmitterComponent() + local timedEmitter = TimedCompoundEmitterComponent.new() timedEmitter.compoundId = CompoundRegistry.getCompoundId(compound) timedEmitter.particlesPerEmission = 1 timedEmitter.potencyPerParticle = 2.0 @@ -237,31 +230,33 @@ local function addEmitter2Entity(entity, compound) end local function createSpawnSystem() - local spawnSystem = SpawnSystem() + local spawnSystem = SpawnSystem.new() local toxinOrganelleSpawnFunction = function(pos) - powerupEntity = Entity() - setSpawnablePhysics(powerupEntity, pos, "AgentVacuole.mesh", 0.9, SphereShape(HEX_SIZE)) + powerupEntity = Entity.new(g_luaEngine.currentGameState.wrapper) + setSpawnablePhysics(powerupEntity, pos, "AgentVacuole.mesh", 0.9, + SphereShape.new(HEX_SIZE)) - local reactionHandler = CollisionComponent() + local reactionHandler = CollisionComponent.new() reactionHandler:addCollisionGroup("powerup") powerupEntity:addComponent(reactionHandler) - local powerupComponent = PowerupComponent() + local powerupComponent = PowerupComponent.new() -- Function name must be in configs.lua powerupComponent:setEffect("toxinEffect") powerupEntity:addComponent(powerupComponent) return powerupEntity end local ChloroplastOrganelleSpawnFunction = function(pos) - powerupEntity = Entity() - setSpawnablePhysics(powerupEntity, pos, "chloroplast.mesh", 0.9, SphereShape(HEX_SIZE)) + powerupEntity = Entity.new(g_luaEngine.currentGameState.wrapper) + setSpawnablePhysics(powerupEntity, pos, "chloroplast.mesh", 0.9, + SphereShape.new(HEX_SIZE)) - local reactionHandler = CollisionComponent() + local reactionHandler = CollisionComponent.new() reactionHandler:addCollisionGroup("powerup") powerupEntity:addComponent(reactionHandler) - local powerupComponent = PowerupComponent() + local powerupComponent = PowerupComponent.new() -- Function name must be in configs.lua powerupComponent:setEffect("chloroplastEffect") powerupEntity:addComponent(powerupComponent) @@ -284,24 +279,32 @@ local function createSpawnSystem() for name, species in pairs(starter_microbes) do spawnSystem:addSpawnType( function(pos) - return microbeSpawnFunctionGeneric(pos, name, true, nil) + return microbeSpawnFunctionGeneric(pos, name, true, nil, + g_luaEngine.currentGameState) end, species.spawnDensity, 60) end return spawnSystem end -local function setupPlayer() - local microbe = microbeSpawnFunctionGeneric(nil, "Default", false, PLAYER_NAME) +local function setupPlayer(gameState) + + assert(GameState.MICROBE == gameState) + assert(gameState ~= nil) + + local microbe = microbeSpawnFunctionGeneric(nil, "Default", false, PLAYER_NAME, gameState) microbe.collisionHandler:addCollisionGroup("powerupable") Engine:playerData():lockedMap():addLock("Toxin") Engine:playerData():lockedMap():addLock("chloroplast") - Engine:playerData():setActiveCreature(microbe.entity.id, GameState.MICROBE) + Engine:playerData():setActiveCreature(microbe.entity.id, gameState.wrapper) + + -- Give some atp + microbe:storeCompound(CompoundRegistry.getCompoundId("atp"), 50, false) end -local function setupSound() - local ambientEntity = Entity("ambience") - local soundSource = SoundSourceComponent() +local function setupSound(gameState) + local ambientEntity = Entity.new("ambience", gameState.wrapper) + local soundSource = SoundSourceComponent.new() soundSource.ambientSoundSource = true soundSource.autoLoop = true soundSource.volumeMultiplier = 0.3 @@ -313,16 +316,16 @@ local function setupSound() soundSource:addSound("microbe-theme-5", "microbe-theme-5.ogg") soundSource:addSound("microbe-theme-6", "microbe-theme-6.ogg") soundSource:addSound("microbe-theme-7", "microbe-theme-7.ogg") - local ambientEntity2 = Entity("ambience2") - local soundSource = SoundSourceComponent() + local ambientEntity2 = Entity.new("ambience2", gameState.wrapper) + local soundSource = SoundSourceComponent.new() soundSource.volumeMultiplier = 0.1 soundSource.ambientSoundSource = true ambientSound = soundSource:addSound("microbe-ambient", "soundeffects/microbe-ambience.ogg") soundSource.autoLoop = true ambientEntity2:addComponent(soundSource) -- Gui effects - local guiSoundEntity = Entity("gui_sounds") - soundSource = SoundSourceComponent() + local guiSoundEntity = Entity.new("gui_sounds", gameState.wrapper) + soundSource = SoundSourceComponent.new() soundSource.ambientSoundSource = true soundSource.autoLoop = false soundSource.volumeMultiplier = 1.0 @@ -330,8 +333,8 @@ local function setupSound() -- Sound soundSource:addSound("button-hover-click", "soundeffects/gui/button-hover-click.ogg") soundSource:addSound("microbe-pickup-organelle", "soundeffects/microbe-pickup-organelle.ogg") - local listener = Entity("soundListener") - local sceneNode = OgreSceneNodeComponent() + local listener = Entity.new("soundListener", gameState.wrapper) + local sceneNode = OgreSceneNodeComponent.new() listener:addComponent(sceneNode) end @@ -340,59 +343,60 @@ setupProcesses() local function createMicrobeStage(name) return - Engine:createGameState( + g_luaEngine:createGameState( name, { - MicrobeReplacementSystem(), - -- SwitchGameStateSystem(), - QuickSaveSystem(), + MicrobeReplacementSystem.new(), + -- SwitchGameStateSystem.new(), + QuickSaveSystem.new(), -- Microbe specific - MicrobeSystem(), - MicrobeCameraSystem(), - MicrobeAISystem(), - MicrobeControlSystem(), - HudSystem(), - TimedLifeSystem(), - CompoundMovementSystem(), - CompoundAbsorberSystem(), - ProcessSystem(), - --PopulationSystem(), - PatchSystem(), - SpeciesSystem(), + MicrobeSystem.new(), + MicrobeCameraSystem.new(), + MicrobeAISystem.new(), + MicrobeControlSystem.new(), + HudSystem.new(), + TimedLifeSystem.new(), + CompoundMovementSystem.new(), + CompoundAbsorberSystem.new(), + ProcessSystem.new(), + --PopulationSystem.new(), + PatchSystem.new(), + SpeciesSystem.new(), -- Physics - RigidBodyInputSystem(), - UpdatePhysicsSystem(), - RigidBodyOutputSystem(), - BulletToOgreSystem(), - CollisionSystem(), + RigidBodyInputSystem.new(), + UpdatePhysicsSystem.new(), + RigidBodyOutputSystem.new(), + BulletToOgreSystem.new(), + CollisionSystem.new(), -- Microbe Specific again (order sensitive) createSpawnSystem(), -- Graphics - OgreAddSceneNodeSystem(), - OgreUpdateSceneNodeSystem(), - OgreCameraSystem(), - OgreLightSystem(), - SkySystem(), - OgreWorkspaceSystem(), - OgreRemoveSceneNodeSystem(), - RenderSystem(), - MembraneSystem(), - CompoundCloudSystem(), - --AgentCloudSystem(), + OgreAddSceneNodeSystem.new(), + OgreUpdateSceneNodeSystem.new(), + OgreCameraSystem.new(), + OgreLightSystem.new(), + SkySystem.new(), + OgreWorkspaceSystem.new(), + OgreRemoveSceneNodeSystem.new(), + RenderSystem.new(), + MembraneSystem.new(), + CompoundCloudSystem.new(), + --AgentCloudSystem.new(), -- Other - SoundSourceSystem(), - PowerupSystem(), - CompoundEmitterSystem(), -- Keep this after any logic that might eject compounds such that any entites that are queued for destruction will be destroyed after emitting. + SoundSourceSystem.new(), + PowerupSystem.new(), + CompoundEmitterSystem.new(), -- Keep this after any logic that might eject compounds such that any entites that are queued for destruction will be destroyed after emitting. }, - function() - setupBackground() - setupCamera() - setupCompoundClouds() - setupSpecies() - setupPlayer() - setupSound() - end, - "MicrobeStage" + true, + "MicrobeStage", + function(gameState) + setupBackground(gameState) + setupCamera(gameState) + setupCompoundClouds(gameState) + setupSpecies(gameState) + setupPlayer(gameState) + setupSound(gameState) + end ) end diff --git a/scripts/microbe_stage/spawn_system.lua b/scripts/microbe_stage/spawn_system.lua index 3338bf940e7..4ea95714617 100644 --- a/scripts/microbe_stage/spawn_system.lua +++ b/scripts/microbe_stage/spawn_system.lua @@ -4,25 +4,27 @@ -- -- Holds information about an entity spawned by spawnComponent -------------------------------------------------------------------------------- -class 'SpawnedComponent' (Component) +SpawnedComponent = class( + function(self) -SPAWN_INTERVAL = 100 --Time between spawn cycles + self.spawnRadiusSqr = 1000 + end +) -function SpawnedComponent:__init() - Component.__init(self) - self.spawnRadiusSqr = 1000 -end +SpawnedComponent.TYPE_NAME = "SpawnedComponent" + +SPAWN_INTERVAL = 100 --Time between spawn cycles function SpawnedComponent:load(storage) - Component.load(self, storage) + self.spawnRadiusSqr = storage:get("spawnRadius", 1000) end -function SpawnedComponent:storage() - local storage = Component.storage(self) +function SpawnedComponent:storage(storage) + storage:set("spawnRadius", self.spawnRadiusSqr) - return storage + end REGISTER_COMPONENT("SpawnedComponent", SpawnedComponent) @@ -33,38 +35,41 @@ REGISTER_COMPONENT("SpawnedComponent", SpawnedComponent) -- -- System for spawning and despawning entities -------------------------------------------------------------------------------- -class 'SpawnSystem' (System) +SpawnSystem = class( + LuaSystem, + function(self) -currentSpawnSystem = nil + LuaSystem.create(self) + + self.entities = EntityFilter.new( + { + SpawnedComponent + } + ) + self.nextId = 1 + self.spawnTypes = {} --Keeps track of factory functions. + + self.playerPosPrev = nil --A Vector3 that remembers the player's position in the last spawn cycle + + self.timeSinceLastCycle = 0 --Stores how much time has passed since the last spawn cycle + + currentSpawnSystem = self + + end +) -function SpawnSystem:__init() - System.__init(self) - - self.entities = EntityFilter( - { - SpawnedComponent - } - ) - self.nextId = 1 - self.spawnTypes = {} --Keeps track of factory functions. - - self.playerPosPrev = nil --A Vector3 that remembers the player's position in the last spawn cycle - - self.timeSinceLastCycle = 0 --Stores how much time has passed since the last spawn cycle - - currentSpawnSystem = self -end +currentSpawnSystem = nil -- Override from System function SpawnSystem:init(gameState) - System.init(self, "SpawnSystem", gameState) - self.entities:init(gameState) + LuaSystem.init(self, "SpawnSystem", gameState) + self.entities:init(gameState.wrapper) end -- Override from System function SpawnSystem:shutdown() self.entities:shutdown() - System.shutdown(self) + LuaSystem.shutdown(self) end -- Adds a new type of entity to spawn in the SpawnSystem @@ -109,9 +114,9 @@ end -- radius of the player at its current location but outside of the spawn radius of the player -- at its location during the previous spawn cycle. function SpawnSystem:_doSpawnCycle() - local player = Entity(PLAYER_NAME) + local player = Entity.new(PLAYER_NAME, self.gameState.wrapper) - local playerNode = player:getComponent(OgreSceneNodeComponent.TYPE_ID) + local playerNode = getComponent(player, OgreSceneNodeComponent) local playerPos = playerNode.transform.position --Initialize previous player position if necessary @@ -119,20 +124,20 @@ function SpawnSystem:_doSpawnCycle() self.playerPosPrev = Vector3(playerPos.x, playerPos.y, playerPos.z) end - for entity in self.entities:removedEntities() do + for _, entity in pairs(self.entities:removedEntities()) do self.microbes[entityId] = nil end - for entityId in self.entities:addedEntities() do - local microbe = Microbe(Entity(entityId)) + for _, entityId in pairs(self.entities:addedEntities()) do + local microbe = Microbe.new(Entity.new(entityId, self.gameState.wrapper)) self.microbes[entityId] = microbe end self.entities:clearChanges() --Despawn entities - for entityId in self.entities:entities() do - entity = Entity(entityId) - local spawnComponent = entity:getComponent(SpawnedComponent.TYPE_ID) - local sceneNode = entity:getComponent(OgreSceneNodeComponent.TYPE_ID) + for _, entityId in pairs(self.entities:entities()) do + entity = Entity.new(entityId, self.gameState.wrapper) + local spawnComponent = getComponent(entity, SpawnedComponent) + local sceneNode = getComponent(entity, OgreSceneNodeComponent) local entityPos = sceneNode.transform.position local distSqr = playerPos:squaredDistance(entityPos) @@ -140,7 +145,7 @@ function SpawnSystem:_doSpawnCycle() if distSqr >= spawnComponent.spawnRadiusSqr then entity:destroy() elseif entityPos.z ~= 0 then - local rigidBody = entity:getComponent(RigidBodyComponent.TYPE_ID) + local rigidBody = getComponent(entity, RigidBodyComponent) rigidBody.dynamicProperties.position.z = 0 rigidBody.dynamicProperties:touch() end @@ -184,7 +189,7 @@ function SpawnSystem:_doSpawnCycle() --Second condition passed. Spawn the entity. local entity = spawnType.factoryFunction(playerPos + displacement) if entity then - local spawnComponent = SpawnedComponent() + local spawnComponent = SpawnedComponent.new() spawnComponent.spawnRadiusSqr = spawnType.spawnRadiusSqr entity:addComponent(spawnComponent) end diff --git a/scripts/microbe_stage/species_system.lua b/scripts/microbe_stage/species_system.lua index a16411d51a4..187e1ff3730 100644 --- a/scripts/microbe_stage/species_system.lua +++ b/scripts/microbe_stage/species_system.lua @@ -3,8 +3,6 @@ -- -- Class for representing an individual species -------------------------------------------------------------------------------- -class 'Species' - --limits the size of the initial stringCodes local MIN_INITIAL_LENGTH = 5 local MAX_INITIAL_LENGTH = 15 @@ -19,6 +17,8 @@ local MAX_COLOR = 1.0 local MUTATION_CREATION_RATE = 0.1 local MUTATION_DELETION_RATE = 0.1 +-- Why is the latest created species system accessible globally here? +-- this will cause problems in the future local gSpeciesSystem = nil local function randomColour() @@ -26,20 +26,46 @@ local function randomColour() end local DEFAULT_INITIAL_COMPOUNDS = -{ - atp = {priority=10,amount=40}, - glucose = {amount = 10}, - reproductase = {priority = 8}, - oxygen = {amount = 10}, - oxytoxy = {amount = 1} -} + { + atp = {priority=10,amount=40}, + glucose = {amount = 10}, + reproductase = {priority = 8}, + oxygen = {amount = 10}, + oxytoxy = {amount = 1} + } + +Species = class( + function(self) + + self.population = INITIAL_POPULATION + self.name = "Species_" .. tostring(math.random()) --gotta use the latin names + + local stringSize = math.random(MIN_INITIAL_LENGTH, MAX_INITIAL_LENGTH) + self.stringCode = organelleTable.nucleus.gene .. organelleTable.cytoplasm.gene --it should always have a nucleus and a cytoplasm. + for i = 1, stringSize do + self.stringCode = self.stringCode .. getRandomLetter() + end + + local organelles = positionOrganelles(self.stringCode) + + self.colour = { + r = randomColour(), + g = randomColour(), + b = randomColour() + } + + self.template = createSpeciesTemplate(self.name, organelles, self.colour, DEFAULT_INITIAL_COMPOUNDS, nil) + self:setupSpawn() + + end +) --sets up the spawn of the species function Species:setupSpawn() - self.id = currentSpawnSystem:addSpawnType - ( + self.id = currentSpawnSystem:addSpawnType( function(pos) - return microbeSpawnFunctionGeneric(pos, self.name, true, nil) + return microbeSpawnFunctionGeneric(pos, self.name, true, nil, + g_luaEngine.currentGameState) end, DEFAULT_SPAWN_DENSITY, --spawnDensity should depend on population DEFAULT_SPAWN_RADIUS @@ -48,8 +74,8 @@ end --copy-pasted from setupSpecies in setup.lua function createSpeciesTemplate(name, organelles, colour, compounds, speciesThresholds) - speciesEntity = Entity(name) - speciesComponent = SpeciesComponent(name) + speciesEntity = Entity.new(name, g_luaEngine.currentGameState.wrapper) + speciesComponent = SpeciesComponent.new(name) speciesEntity:addComponent(speciesComponent) for i, organelle in pairs(organelles) do local org = {} @@ -59,11 +85,11 @@ function createSpeciesTemplate(name, organelles, colour, compounds, speciesThres org.rotation = organelle.rotation speciesComponent.organelles[i] = org end - processorComponent = ProcessorComponent() + processorComponent = ProcessorComponent.new() speciesEntity:addComponent(processorComponent) speciesComponent.colour = Vector3(colour.r, colour.g, colour.b) -- iterates over all compounds, and sets amounts and priorities - for compoundID in CompoundRegistry.getCompoundList() do + for _, compoundID in pairs(CompoundRegistry.getCompoundList()) do compound = CompoundRegistry.getCompoundInternalName(compoundID) compoundData = compounds[compound] @@ -88,7 +114,7 @@ function createSpeciesTemplate(name, organelles, colour, compounds, speciesThres end end end - for bioProcessId in BioProcessRegistry.getList() do + for _, bioProcessId in pairs(BioProcessRegistry.getList()) do local name = BioProcessRegistry.getInternalName(bioProcessId) if capacities[name] ~= nil then processorComponent:setCapacity(bioProcessId, capacities[name]) @@ -99,29 +125,6 @@ function createSpeciesTemplate(name, organelles, colour, compounds, speciesThres return speciesEntity end -function Species:__init() - self.population = INITIAL_POPULATION - self.name = "Species_" .. tostring(math.random()) --gotta use the latin names - - local stringSize = math.random(MIN_INITIAL_LENGTH, MAX_INITIAL_LENGTH) - self.stringCode = organelleTable.nucleus.gene .. organelleTable.cytoplasm.gene --it should always have a nucleus and a cytoplasm. - for i = 1, stringSize do - self.stringCode = self.stringCode .. getRandomLetter() - end - - local organelles = positionOrganelles(self.stringCode) - - self.colour = { - r = randomColour(), - g = randomColour(), - b = randomColour() - } - - self.template = createSpeciesTemplate(self.name, organelles, self.colour, DEFAULT_INITIAL_COMPOUNDS, nil) - self:setupSpawn() - return self -end - --updates the population count of the species function Species:updatePopulation() --TODO: @@ -217,21 +220,26 @@ MAX_SPECIES = 15 --if there are less species than this create new ones. MIN_SPECIES = 3 -class 'SpeciesSystem' (System) -function SpeciesSystem:__init(spawnSystem) - gSpawnSystem = spawnSystem - System.__init(self) - - self.entities = EntityFilter( - { - SpeciesComponent, - ProcessorComponent, - }, - true - ) - self.timeSinceLastCycle = 0 -end +SpeciesSystem = class( + LuaSystem, + function(self) + + LuaSystem.create(self) + + gSpawnSystem = self + + self.entities = EntityFilter.new( + { + SpeciesComponent, + ProcessorComponent, + }, + true + ) + self.timeSinceLastCycle = 0 + + end +) function resetAutoEvo() if gSpeciesSystem.species ~= nil then @@ -246,8 +254,8 @@ end -- Override from System function SpeciesSystem:init(gameState) - System.init(self, "SpeciesSystem", gameState) - self.entities:init(gameState) + LuaSystem.init(self, "SpeciesSystem", gameState) + self.entities:init(gameState.wrapper) self.species = {} self.number_of_species = 0 @@ -268,7 +276,7 @@ end -- Override from System function SpeciesSystem:shutdown() self.entities:shutdown() - System.shutdown(self) + LuaSystem.shutdown(self) end -- Override from System @@ -340,14 +348,14 @@ function SpeciesSystem:update(_, milliseconds) end function SpeciesSystem.initProcessorComponent(entity, speciesComponent) - local sc = entity:getComponent(SpeciesComponent.TYPE_ID) + local sc = getComponent(entity, SpeciesComponent) if sc == nil then entity:addComponent(speciesComponent) end - local pc = entity:getComponent(ProcessorComponent.TYPE_ID) + local pc = getComponent(entity, ProcessorComponent) if pc == nil then - pc = ProcessorComponent() + pc = ProcessorComponent.new() entity:addComponent(pc) end @@ -364,7 +372,7 @@ function SpeciesSystem.initProcessorComponent(entity, speciesComponent) end end end - for bioProcessID in BioProcessRegistry.getList() do + for _, bioProcessID in pairs(BioProcessRegistry.getList()) do local name = BioProcessRegistry.getInternalName(bioProcessID) if capacities[name] ~= nil then pc:setCapacity(bioProcessID, capacities[name]) @@ -408,7 +416,7 @@ end function SpeciesSystem.fromMicrobe(microbe, species) local microbe_ = microbe.microbe -- shouldn't break, I think -- self.name = microbe_.speciesName - species.colour = microbe:getComponent(MembraneComponent.TYPE_ID):getColour() + species.colour = microbe:getComponent(MembraneComponent):getColour() -- Create species' organelle data for i, organelle in pairs(microbe_.organelles) do local data = {} @@ -420,7 +428,7 @@ function SpeciesSystem.fromMicrobe(microbe, species) end -- This microbes compound amounts will be the new population average. species.avgCompoundAmounts = {} - for compoundID in CompoundRegistry.getCompoundList() do + for _, compoundID in pairs(CompoundRegistry.getCompoundList()) do local amount = microbe:getCompoundAmount(compoundID) species.avgCompoundAmounts["" .. compoundID] = amount/2 end diff --git a/scripts/microbe_stage/storage_organelle.lua b/scripts/microbe_stage/storage_organelle.lua index e9baae03ecd..845ed206bca 100644 --- a/scripts/microbe_stage/storage_organelle.lua +++ b/scripts/microbe_stage/storage_organelle.lua @@ -1,34 +1,37 @@ -------------------------------------------------------------------------------- -- A storage organelle class -------------------------------------------------------------------------------- -class 'StorageOrganelle' (OrganelleComponent) +StorageOrganelle = class( + OrganelleComponent, + -- Constructor + -- + -- @param arguments.capacity + -- The maximum stored amount + function(self, arguments, data) + + OrganelleComponent.create(self, arguments, data) + + --making sure this doesn't run when load() is called + if arguments == nil and data == nil then + return + end + + self.capacity = arguments.capacity + self.parentIndex = 0 + return self + end +) -- See organelle_component.lua for more information about the -- organelle component methods and the arguments they receive. --- Constructor --- --- @param arguments.capacity --- The maximum stored amount -function StorageOrganelle:__init(arguments, data) - OrganelleComponent.__init(self, arguments, data) - - --making sure this doesn't run when load() is called - if arguments == nil and data == nil then - return - end - - self.capacity = arguments.capacity - self.parentIndex = 0 - return self -end function StorageOrganelle:load(storage) self.capacity = storage:get("capacity", 100) end -function StorageOrganelle:storage(storage) - local storage = StorageContainer() +function StorageOrganelle:storage() + local storage = StorageContainer.new() storage:set("capacity", self.capacity) return storage end diff --git a/scripts/microbe_stage/switch_game_state_system.lua b/scripts/microbe_stage/switch_game_state_system.lua index f72afc1c4a8..f1b54f4c67e 100644 --- a/scripts/microbe_stage/switch_game_state_system.lua +++ b/scripts/microbe_stage/switch_game_state_system.lua @@ -1,11 +1,14 @@ -class 'SwitchGameStateSystem' (System) +SwitchGameStateSystem = class( + LuaSystem, + function(self) + + LuaSystem.create(self) -function SwitchGameStateSystem:__init() - System.__init(self) -end + end +) function SwitchGameStateSystem:init() - System.init(self, "SwitchGameStateSystem", gameState) + LuaSystem.init(self, "SwitchGameStateSystem", gameState) end function SwitchGameStateSystem:update(renderTime, logicTime) diff --git a/scripts/microbe_stage_tutorial/microbe_stage_tutorial_hud.lua b/scripts/microbe_stage_tutorial/microbe_stage_tutorial_hud.lua index 67603dac4f1..a5d0941265f 100644 --- a/scripts/microbe_stage_tutorial/microbe_stage_tutorial_hud.lua +++ b/scripts/microbe_stage_tutorial/microbe_stage_tutorial_hud.lua @@ -1,19 +1,21 @@ -- Updates the hud with relevant information -class 'MicrobeStageTutorialHudSystem' (System) - -function MicrobeStageTutorialHudSystem:__init() - System.__init(self) - self.compoundListBox = nil - self.hitpointsCountLabel = nil - self.hitpointsBar = nil - self.compoundListItems = {} - self.rootGuiWindow = nil - self.populationNumberLabel = nil - self.rootGUIWindow = nil - self.tutorialStep = 0 - self.scrollChange = 0 -end +MicrobeStageTutorialHudSystem = class( + LuaSystem, + function(self) + + LuaSystem.create(self) + self.compoundListBox = nil + self.hitpointsCountLabel = nil + self.hitpointsBar = nil + self.compoundListItems = {} + self.rootGuiWindow = nil + self.populationNumberLabel = nil + self.rootGUIWindow = nil + self.tutorialStep = 0 + self.scrollChange = 0 + end +) function MicrobeStageTutorialHudSystem:activate() global_activeMicrobeStageHudSystem = self -- Global reference for event handlers @@ -21,14 +23,14 @@ function MicrobeStageTutorialHudSystem:activate() end function MicrobeStageTutorialHudSystem:init(gameState) - System.init(self, "MicrobeStageTutorialHudSystem", gameState) + LuaSystem.init(self, "MicrobeStageTutorialHudSystem", gameState) self.rootGUIWindow = gameState:rootGUIWindow() self.rootGUIWindow:getChild("PauseMenu"):getChild("MainMenuButton"):registerEventHandler("Clicked", function() self:menuMainMenuClicked() end) local quitButton = self.rootGUIWindow:getChild("PauseMenu"):getChild("QuitButton") quitButton:registerEventHandler("Clicked", quitButtonClicked) self.rootGUIWindow:getChild("TutorialPanel"):registerEventHandler("Clicked", function() self.tutorialStep = self.tutorialStep + 1 end) - local editorButton = self.rootGUIWindow:getChild("EditorButton") - editorButton:registerEventHandler("Clicked", function() self:editorButtonClicked() end) + self.editorButton = self.rootGUIWindow:getChild("EditorButton") + self.editorButton:registerEventHandler("Clicked", function() self:editorButtonClicked() end) self.hitpointsBar = self.rootGUIWindow:getChild("HealthPanel"):getChild("LifeBar") self.hitpointsCountLabel = self.hitpointsBar:getChild("NumberLabel") @@ -87,12 +89,18 @@ function MicrobeStageTutorialHudSystem:update(renderTime) if self.tutorialStep > 2 then--where the player microbe is created. -- Updating the ATP label. local atpID = CompoundRegistry.getCompoundId("atp") - local atpString = string.format("%d", math.floor(Microbe(Entity(PLAYER_NAME)):getCompoundAmount(atpID))) + local atpString = string.format( + "%d", math.floor(Microbe( + Entity.new(PLAYER_NAME, self.gameState.wrapper) + ):getCompoundAmount(atpID))) self.atpCountLabel2:setText(atpString) -- Updating the compound panel. local glucoseID = CompoundRegistry.getCompoundId("glucose") - local glucoseString = string.format("%d", math.floor(Microbe(Entity(PLAYER_NAME)):getCompoundAmount(glucoseID))) + local glucoseString = string.format( + "%d", math.floor(Microbe( + Entity.new(PLAYER_NAME, self.gameState.wrapper) + ):getCompoundAmount(glucoseID))) self.atpCountLabel:setText(atpString) self.glucoseCountLabel:setText(glucoseString) @@ -113,7 +121,7 @@ function MicrobeStageTutorialHudSystem:update(renderTime) if Engine.mouse:wasButtonPressed(Mouse.MB_Left) and self.tutorialStep ~= 3 and self.tutorialStep ~= 8 and self.tutorialStep ~= 11 then self.tutorialStep = self.tutorialStep + 1 - elseif Engine.keyboard:wasKeyPressed(Keyboard.KC_ESCAPE) and self.tutorialStep <= 2 then + elseif Engine.keyboard:wasKeyPressed(KEYCODE.KC_ESCAPE) and self.tutorialStep <= 2 then self.tutorialStep = -1 end @@ -157,9 +165,15 @@ Click to continue or press escape to skip the tutorial.]]) [[Your cell is shown below. Click anywhere to continue...]]) - if Entity(PLAYER_NAME):getComponent(MicrobeComponent.TYPE_ID) == nil then - local microbe = microbeSpawnFunctionGeneric(nil, "Default", false, PLAYER_NAME) - Engine:playerData():setActiveCreature(microbe.entity.id, GameState.MICROBE_TUTORIAL) + if getComponent(PLAYER_NAME, self.gameState, MicrobeComponent) == nil then + print("trying to spawn player") + local microbe = microbeSpawnFunctionGeneric(nil, "Default", false, + PLAYER_NAME, self.gameState) + Engine:playerData():setActiveCreature(microbe.entity.id, + GameState.MICROBE_TUTORIAL.wrapper) + + -- Make sure player doesn't run out of ATP immediately + microbe:storeCompound(CompoundRegistry.getCompoundId("atp"), 50, false) end @@ -174,7 +188,7 @@ mouse, and use WASD to move around. Give it a try! Swim for a while in any direction to continue...]]) - local pos = Entity(PLAYER_NAME):getComponent(OgreSceneNodeComponent.TYPE_ID).transform.position + local pos = getComponent(PLAYER_NAME, self.gameState, OgreSceneNodeComponent).transform.position if math.sqrt(pos.x*pos.x + pos.y*pos.y) > 30 then self.tutorialStep = self.tutorialStep + 1; end @@ -212,7 +226,9 @@ Click anywhere to continue...]]) [[You can keep track of your ATP by looking at the compounds panel shown below. -You currently have only ]] .. math.floor(Microbe(Entity(PLAYER_NAME)):getCompoundAmount(atpID)) .. [[ ATP. Let's make some more! +You currently have only ]] .. math.floor(Microbe( + Entity.new(PLAYER_NAME, self.gameState.wrapper) + ):getCompoundAmount(atpID)) .. [[ ATP. Let's make some more! Click anywhere to continue...]]) @@ -230,10 +246,10 @@ Click anywhere to continue...]]) elseif self.tutorialStep == 8 then - local player = Entity(PLAYER_NAME) - local playerPos = player:getComponent(OgreSceneNodeComponent.TYPE_ID).transform.position + local player = Entity.new(PLAYER_NAME, self.gameState.wrapper) + local playerPos = getComponent(player, OgreSceneNodeComponent).transform.position - local offset = Entity(CAMERA_NAME):getComponent(OgreCameraComponent.TYPE_ID).properties.offset + local offset = getComponent(CAMERA_NAME, self.gameState, OgreCameraComponent).properties.offset if offset.z < 70 then offset.z = offset.z + 1 end @@ -298,13 +314,18 @@ Click anywhere to continue...]]) Press the button on the top right corner to enter the editor.]]) else - Engine:playerData():setActiveCreature(Entity(PLAYER_NAME).id, GameState.MICROBE) - Engine:setCurrentGameState(GameState.MICROBE) + Engine:playerData():setActiveCreature(Entity.new(PLAYER_NAME, self.gameState.wrapper). + id, GameState.MICROBE.wrapper) + g_luaEngine:setCurrentGameState(GameState.MICROBE) end if self.tutorialStep >= 6 then - for compoundID in CompoundRegistry.getCompoundList() do - local compoundsString = string.format("%s - %d", CompoundRegistry.getCompoundDisplayName(compoundID), Microbe(Entity(PLAYER_NAME)):getCompoundAmount(compoundID)) + for _, compoundID in pairs(CompoundRegistry.getCompoundList()) do + local compoundsString = string.format( + "%s - %d", + CompoundRegistry.getCompoundDisplayName(compoundID), + Microbe.new(Entity.new(PLAYER_NAME, g_luaEngine.currentGameState.wrapper) + ):getCompoundAmount(compoundID)) if self.compoundListItems[compoundID] ~= nil then self.compoundListBox:listWidgetUpdateItem(self.compoundListItems[compoundID], "[colour='FF004400']" .. compoundsString) end @@ -316,7 +337,8 @@ the editor.]]) end -- Change zoom. - local offset = Entity(CAMERA_NAME):getComponent(OgreCameraComponent.TYPE_ID).properties.offset + local offset = getComponent(CAMERA_NAME, self.gameState, OgreCameraComponent + ).properties.offset if Engine.mouse:scrollChange()/10 ~= 0 then self.scrollChange = self.scrollChange + Engine.mouse:scrollChange()/10 @@ -342,9 +364,9 @@ the editor.]]) offset.z = newZVal end -function HudSystem:toggleCompoundPanel() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") +function MicrobeStageTutorialHudSystem:toggleCompoundPanel() + getComponent("gui_sounds", g_luaEngine.currentGameState, SoundSourceComponent + ):playSound("button-hover-click") if self.compoundsOpen then self.rootGUIWindow:getChild("CompoundPanel"):hide() self.rootGUIWindow:getChild("CompoundExpandButton"):getChild("CompoundExpandIcon"):hide() @@ -358,21 +380,29 @@ function HudSystem:toggleCompoundPanel() end end +function MicrobeStageTutorialHudSystem:showReproductionDialog() + -- print("Reproduction Dialog called but currently disabled. Is it needed? Note that the editor button has been enabled") + --global_activeMicrobeStageHudSystem.rootGUIWindow:getChild("ReproductionPanel"):show() + self.editorButton:enable() +end + function MicrobeStageTutorialHudSystem:closeCompoundPanel() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") + getComponent("gui_sounds", g_luaEngine.currentGameState, SoundSourceComponent + ):playSound("button-hover-click") self.rootGUIWindow:getChild("CompoundsOpen"):hide() self.rootGUIWindow:getChild("CompoundsClosed"):show() end function MicrobeStageTutorialHudSystem:editorButtonClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") - Engine:setCurrentGameState(GameState.MICROBE_EDITOR) + getComponent("gui_sounds", g_luaEngine.currentGameState, SoundSourceComponent + ):playSound("button-hover-click") + g_luaEngine:setCurrentGameState(GameState.MICROBE_EDITOR) end function quitButtonClicked() - local guiSoundEntity = Entity("gui_sounds") - guiSoundEntity:getComponent(SoundSourceComponent.TYPE_ID):playSound("button-hover-click") + + getComponent("gui_sounds", g_luaEngine.currentGameState, SoundSourceComponent + ):playSound("button-hover-click") + Engine:quit() end diff --git a/scripts/microbe_stage_tutorial/setup.lua b/scripts/microbe_stage_tutorial/setup.lua index 00744a84a38..078cc0e6770 100644 --- a/scripts/microbe_stage_tutorial/setup.lua +++ b/scripts/microbe_stage_tutorial/setup.lua @@ -1,11 +1,11 @@ --The biome in which the tutorial is played. TUTORIAL_BIOME = "default" -local function setupBackground() +local function setupBackground(gameState) --Actually changing the biome makes the biome after the tutorial be default --but with a different background. - local entity = Entity("background") - local skyplane = SkyPlaneComponent() + local entity = Entity.new("background", gameState.wrapper) + local skyplane = SkyPlaneComponent.new() skyplane.properties.plane.normal = Vector3(0, 0, 2000) skyplane.properties.materialName = biomeTable[TUTORIAL_BIOME].background skyplane.properties.scale = 200 @@ -13,38 +13,38 @@ local function setupBackground() entity:addComponent(skyplane) end -local function setupCamera() - local entity = Entity(CAMERA_NAME) +local function setupCamera(gameState) + local entity = Entity.new(CAMERA_NAME, gameState.wrapper) -- Camera - local camera = OgreCameraComponent("camera") + local camera = OgreCameraComponent.new("camera") camera.properties.nearClipDistance = 5 - camera.offset = Vector3(0, 0, 30) + camera.properties.offset = Vector3(0, 0, 30) camera.properties:touch() entity:addComponent(camera) -- Scene node - local sceneNode = OgreSceneNodeComponent() + local sceneNode = OgreSceneNodeComponent.new() sceneNode.transform.position.z = 30 sceneNode.transform:touch() entity:addComponent(sceneNode) -- Light - local light = OgreLightComponent() + local light = OgreLightComponent.new() light:setRange(200) entity:addComponent(light) -- Workspace - local workspaceEntity = Entity() - local workspaceComponent = OgreWorkspaceComponent("thrive_default") + local workspaceEntity = Entity.new(gameState.wrapper) + local workspaceComponent = OgreWorkspaceComponent.new("thrive_default") workspaceComponent.properties.cameraEntity = entity workspaceComponent.properties.position = 0 workspaceComponent.properties:touch() workspaceEntity:addComponent(workspaceComponent) end -local function setupCompoundClouds() +local function setupCompoundClouds(gameState) for compoundName, compoundInfo in pairs(compoundTable) do if compoundInfo.isCloud then local compoundId = CompoundRegistry.getCompoundId(compoundName) - local entity = Entity("compound_cloud_" .. compoundName) - local compoundCloud = CompoundCloudComponent() + local entity = Entity.new("compound_cloud_" .. compoundName, gameState.wrapper) + local compoundCloud = CompoundCloudComponent.new() local colour = compoundInfo.colour compoundCloud:initialize(compoundId, colour.r, colour.g, colour.b) entity:addComponent(compoundCloud) @@ -52,13 +52,13 @@ local function setupCompoundClouds() end end -local function setupPlayer() - local entity = Entity(PLAYER_NAME) - local sceneNode = OgreSceneNodeComponent() +local function setupPlayer(gameState) + local entity = Entity.new(PLAYER_NAME, gameState.wrapper) + local sceneNode = OgreSceneNodeComponent.new() entity:addComponent(sceneNode) - Engine:playerData():setActiveCreature(entity.id, GameState.MICROBE_TUTORIAL) + Engine:playerData():setActiveCreature(entity.id, GameState.MICROBE_TUTORIAL.wrapper) -- local microbe = Microbe.createMicrobeEntity(PLAYER_NAME, false) - -- Entity("Default"):getComponent(SpeciesComponent.TYPE_ID):template(microbe) + -- getComponent(Entity("Default"), SpeciesComponent):template(microbe) -- microbe.collisionHandler:addCollisionGroup("powerupable") -- Engine:playerData():lockedMap():addLock("Toxin") -- Engine:playerData():lockedMap():addLock("chloroplast") @@ -71,9 +71,9 @@ local function setupPlayer() end -local function setupSound() - local ambientEntity = Entity("ambience") - local soundSource = SoundSourceComponent() +local function setupSound(gameState) + local ambientEntity = Entity.new("ambience", gameState.wrapper) + local soundSource = SoundSourceComponent.new() soundSource.ambientSoundSource = true soundSource.autoLoop = true soundSource.volumeMultiplier = 0.5 @@ -85,16 +85,16 @@ local function setupSound() soundSource:addSound("microbe-theme-5", "microbe-theme-5.ogg") soundSource:addSound("microbe-theme-6", "microbe-theme-6.ogg") soundSource:addSound("microbe-theme-7", "microbe-theme-7.ogg") - local ambientEntity2 = Entity("ambience2") - local soundSource = SoundSourceComponent() + local ambientEntity2 = Entity.new("ambience2", gameState.wrapper) + local soundSource = SoundSourceComponent.new() soundSource.volumeMultiplier = 0.3 soundSource.ambientSoundSource = true ambientSound = soundSource:addSound("microbe-ambient", "soundeffects/microbe-ambience.ogg") soundSource.autoLoop = true - ambientEntity2:addComponent(soundSource) + ambientEntity2:addComponent(soundSource) -- Gui effects - local guiSoundEntity = Entity("gui_sounds") - soundSource = SoundSourceComponent() + local guiSoundEntity = Entity.new("gui_sounds", gameState.wrapper) + soundSource = SoundSourceComponent.new() soundSource.ambientSoundSource = true soundSource.autoLoop = false soundSource.volumeMultiplier = 1.0 @@ -102,60 +102,61 @@ local function setupSound() -- Sound soundSource:addSound("button-hover-click", "soundeffects/gui/button-hover-click.ogg") soundSource:addSound("microbe-pickup-organelle", "soundeffects/microbe-pickup-organelle.ogg") - local listener = Entity("soundListener") - local sceneNode = OgreSceneNodeComponent() + local listener = Entity.new("soundListener", gameState.wrapper) + local sceneNode = OgreSceneNodeComponent.new() listener:addComponent(sceneNode) end local function createMicrobeStageTutorial(name) return - Engine:createGameState( + g_luaEngine:createGameState( name, { - QuickSaveSystem(), + QuickSaveSystem.new(), -- Microbe specific - MicrobeSystem(), - MicrobeCameraSystem(), - MicrobeAISystem(), - MicrobeControlSystem(), - MicrobeStageTutorialHudSystem(), - TimedLifeSystem(), - CompoundMovementSystem(), - CompoundAbsorberSystem(), - --PopulationSystem(), - PatchSystem(), - SpeciesSystem(), + MicrobeSystem.new(), + MicrobeCameraSystem.new(), + MicrobeAISystem.new(), + MicrobeControlSystem.new(), + MicrobeStageTutorialHudSystem.new(), + TimedLifeSystem.new(), + CompoundMovementSystem.new(), + CompoundAbsorberSystem.new(), + --PopulationSystem.new(), + PatchSystem.new(), + SpeciesSystem.new(), -- Physics - RigidBodyInputSystem(), - UpdatePhysicsSystem(), - RigidBodyOutputSystem(), - BulletToOgreSystem(), - CollisionSystem(), + RigidBodyInputSystem.new(), + UpdatePhysicsSystem.new(), + RigidBodyOutputSystem.new(), + BulletToOgreSystem.new(), + CollisionSystem.new(), -- Graphics - OgreAddSceneNodeSystem(), - OgreUpdateSceneNodeSystem(), - OgreCameraSystem(), - OgreLightSystem(), - SkySystem(), - OgreWorkspaceSystem(), - OgreRemoveSceneNodeSystem(), - RenderSystem(), - MembraneSystem(), - CompoundCloudSystem(), + OgreAddSceneNodeSystem.new(), + OgreUpdateSceneNodeSystem.new(), + OgreCameraSystem.new(), + OgreLightSystem.new(), + SkySystem.new(), + OgreWorkspaceSystem.new(), + OgreRemoveSceneNodeSystem.new(), + RenderSystem.new(), + MembraneSystem.new(), + CompoundCloudSystem.new(), -- Other - SoundSourceSystem(), - PowerupSystem(), - CompoundEmitterSystem(), -- Keep this after any logic that might eject compounds such that any entites that are queued for destruction will be destroyed after emitting. + SoundSourceSystem.new(), + PowerupSystem.new(), + CompoundEmitterSystem.new(), -- Keep this after any logic that might eject compounds such that any entites that are queued for destruction will be destroyed after emitting. }, - function() - setupBackground() - setupCamera() - setupCompoundClouds() - setupSpecies() - setupPlayer() - setupSound() - end, - "MicrobeStageTutorial" + true, + "MicrobeStageTutorial", + function(gameState) + setupBackground(gameState) + setupCamera(gameState) + setupCompoundClouds(gameState) + setupSpecies(gameState) + setupPlayer(gameState) + setupSound(gameState) + end ) end diff --git a/scripts/quick_save.lua b/scripts/quick_save.lua index 4f12b036a83..cabe22be001 100644 --- a/scripts/quick_save.lua +++ b/scripts/quick_save.lua @@ -1,25 +1,36 @@ -class 'QuickSaveSystem' (System) +-- QuickSaveSystem -function QuickSaveSystem:__init() - System.__init(self) - self.saveDown = false - self.loadDown = false -end +QuickSaveSystem = class( + LuaSystem, + function(self) + + LuaSystem.create(self) + + end +) + +function QuickSaveSystem:init(gameState) + + LuaSystem.init(self, "QuickSaveSystem", gameState) + + self.saveDown = false + self.loadDown = false -function QuickSaveSystem:init() - System.init(self, "QuickSaveSystem", gameState) end function QuickSaveSystem:update(renderTime, logicTime) - local saveDown = Engine.keyboard:isKeyDown(Keyboard.KC_F4) - local loadDown = Engine.keyboard:isKeyDown(Keyboard.KC_F10) - if saveDown and not self.saveDown then - Engine:save("quick.sav") - end - if loadDown and not self.loadDown then - Engine:load("quick.sav") - end - self.saveDown = saveDown - self.loadDown = loadDown + local saveDown = Engine.keyboard:isKeyDown(KEYCODE.KC_F4) + local loadDown = Engine.keyboard:isKeyDown(KEYCODE.KC_F10) + if saveDown and not self.saveDown then + Engine:save("quick.sav") + end + if loadDown and not self.loadDown then + Engine:load("quick.sav") + end + self.saveDown = saveDown + self.loadDown = loadDown end + + + diff --git a/scripts/sandbox/game_state.lua b/scripts/sandbox/game_state.lua deleted file mode 100644 index 79a64b7672c..00000000000 --- a/scripts/sandbox/game_state.lua +++ /dev/null @@ -1,22 +0,0 @@ -class 'TestSystem' (System) - -function TestSystem:__init(string) - System.__init(self) - self.string = string -end - -function TestSystem:update(milliseconds) - print(self.string .. tostring(milliseconds)) -end - - -Engine:addGameState( - "test", - { - TestSystem("A: "), - TestSystem("B: "), - TestSystem("C: ") - } -) - -Engine:setCurrentGameState("test") diff --git a/scripts/util.lua b/scripts/util.lua index 163a43cbad8..6cc0a7b2a20 100644 --- a/scripts/util.lua +++ b/scripts/util.lua @@ -18,20 +18,68 @@ function REGISTER_COMPONENT(name, cls) end --- Gets a component from an entity, creating the component if it's not present --- --- @param componentCls --- The class object of the component type -function Entity:getOrCreate(componentCls) - component = self:getComponent(componentCls.TYPE_ID) - if component == nil then - component = componentCls() - self:addComponent(component) +--! @brief Returns a component from an entity +--! +--! Two alternative signatures: +--! getComponent(string entityname, GameState gameState, Component componentClass) +--! getComponent(Entity entity, Component componentClass) +function getComponent(entityNameOrEntity, gameStateOrClass, componentClass) + + local componentObj + + -- Detect which signature + local param1Type = type(entityNameOrEntity) + if(param1Type == "string" or param1Type == "number") then + + -- First signature + componentObj = Entity.new(entityNameOrEntity, + gameStateOrClass.wrapper):getComponent( + componentClass.TYPE_ID) + + else + + -- Second signature + componentClass = gameStateOrClass + + componentObj = entityNameOrEntity:getComponent(componentClass.TYPE_ID) + end + + if componentObj == nil then + -- No such component + return nil + end + + if componentClass.castFrom then + + return componentClass.castFrom(componentObj) + + else + -- Unwrap ComponentWrapper + + -- We do an unsafe cast for performance reasons + return ComponentWrapper.castFromUnsafe(componentObj).luaObj end - return component end +--! Unwraps a ComponentWrapper from component and returns the lua +--! object +--! @return Unwrapped lua object. Or nil if wrapped wasn't a +--! valid wrapper +--! @note This is a safe but slow way to unwrap. See +--! getComponent for a faster way, but one that isn't safe it isn't +--! certain that wrapped is actually a ComponentWrapper +function unwrapWrappedComponent(wrapped) + + -- Cast to ComponentWrapper + if wrapped.luaObj == nil then + + wrapped = ComponentWrapper.castFrom(wrapped) + end + + return wrapped.luaObj +end + -- Computes a number's sign -- -- @param x @@ -159,3 +207,43 @@ function print_r (t, indent) -- alt version, abuse to http://richard.warburton.i else io.write(' = ',tostring(value),'\n') end end end + +--! Prints a value along with it's type +function print_t(val, name) + + if name == nil or type(name) ~= "string" then + + name = debug.getinfo(2).short_src .. ":" .. debug.getinfo(2).currentline + + end + + print("debug print " .. name .. ":") + + local printVal = "" + if type(val) ~= "userdata" then + + printVal = tostring(val) + + end + + print("type: " .. type(val) .. " value: " .. printVal) + + if type(val) == "table" then + print_r(val) + end + + print("end print") + +end + +--! @brief Returns true if s is not an empty string +function isNotEmpty(s) + return not (s == nil or s == '') +end + + +-- Call for quick debugging. Prints the line of the function calling this +function printLine() + print(debug.getinfo(2).currentline) +end + diff --git a/src/bullet/CMakeLists.txt b/src/bullet/CMakeLists.txt index c2c45b4449b..bca099b7a7d 100644 --- a/src/bullet/CMakeLists.txt +++ b/src/bullet/CMakeLists.txt @@ -8,13 +8,13 @@ add_sources( "${CMAKE_CURRENT_SOURCE_DIR}/debug_drawing.h" "${CMAKE_CURRENT_SOURCE_DIR}/rigid_body_system.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/rigid_body_system.h" - "${CMAKE_CURRENT_SOURCE_DIR}/script_bindings.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/script_bindings.h" "${CMAKE_CURRENT_SOURCE_DIR}/update_physics_system.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/update_physics_system.h" "${CMAKE_CURRENT_SOURCE_DIR}/collision_system.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/collision_system.h" "${CMAKE_CURRENT_SOURCE_DIR}/collision_filter.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/collision_filter.h" + "${CMAKE_CURRENT_SOURCE_DIR}/physical_world.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/physical_world.h" ) diff --git a/src/bullet/bullet_to_ogre_system.cpp b/src/bullet/bullet_to_ogre_system.cpp index 73d9206f914..8222f15d1b2 100644 --- a/src/bullet/bullet_to_ogre_system.cpp +++ b/src/bullet/bullet_to_ogre_system.cpp @@ -4,19 +4,22 @@ #include "engine/game_state.h" #include "engine/entity_filter.h" #include "ogre/scene_node_system.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" using namespace thrive; +void BulletToOgreSystem::luaBindings( + sol::state &lua +){ + lua.new_usertype( "BulletToOgreSystem", + + sol::constructors>(), -luabind::scope -BulletToOgreSystem::luaBindings() { - using namespace luabind; - return class_("BulletToOgreSystem") - .def(constructor<>()) - ; -} + sol::base_classes, sol::bases(), + "init", &BulletToOgreSystem::init + ); +} struct BulletToOgreSystem::Implementation { @@ -38,10 +41,10 @@ BulletToOgreSystem::~BulletToOgreSystem() {} void BulletToOgreSystem::init( - GameState* gameState + GameStateData* gameState ) { System::initNamed("BulletToOgreSystem", gameState); - m_impl->m_entities.setEntityManager(&gameState->entityManager()); + m_impl->m_entities.setEntityManager(gameState->entityManager()); } diff --git a/src/bullet/bullet_to_ogre_system.h b/src/bullet/bullet_to_ogre_system.h index e5a4900b426..388ad40a3f1 100644 --- a/src/bullet/bullet_to_ogre_system.h +++ b/src/bullet/bullet_to_ogre_system.h @@ -2,8 +2,8 @@ #include "engine/system.h" -namespace luabind { - class scope; +namespace sol { +class state; } namespace thrive { @@ -24,8 +24,7 @@ class BulletToOgreSystem : public System { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -43,7 +42,7 @@ class BulletToOgreSystem : public System { */ void init( - GameState* gameState + GameStateData* gameState ) override; /** diff --git a/src/bullet/collision_filter.cpp b/src/bullet/collision_filter.cpp index 1d93a938033..d92c19e3e11 100644 --- a/src/bullet/collision_filter.cpp +++ b/src/bullet/collision_filter.cpp @@ -1,7 +1,6 @@ #include "collision_filter.h" -#include #include "engine/game_state.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" @@ -24,20 +23,30 @@ struct CollisionFilter::Implementation { }; +void CollisionFilter::luaBindings( + sol::state &lua +){ + // lua.new_usertype("CollisionIterator", -luabind::scope -CollisionFilter::luaBindings() { - using namespace luabind; - return class_("CollisionFilter") - .def(constructor()) - .def("init", &CollisionFilter::init) - .def("shutdown", &CollisionFilter::shutdown) - .def("collisions", &CollisionFilter::collisions, return_stl_iterator) - .def("clearCollisions", &CollisionFilter::clearCollisions) - .def("removeCollision", &CollisionFilter::removeCollision) - ; -} + + // ); + + lua.new_usertype("CollisionFilter", + + sol::constructors>(), + + "init", &CollisionFilter::init, + "shutdown", &CollisionFilter::shutdown, + "collisions", [](CollisionFilter &us, sol::this_state s){ + + THRIVE_BIND_ITERATOR_TO_TABLE(us.collisions()); + }, + + "clearCollisions", &CollisionFilter::clearCollisions, + "removeCollision", &CollisionFilter::removeCollision + ); +} CollisionFilter::CollisionFilter( const std::string& collisionGroup1, @@ -50,7 +59,7 @@ CollisionFilter::~CollisionFilter(){} void CollisionFilter::init( - GameState* gameState + GameStateData* gameState ) { m_impl->m_collisionSystem = gameState->findSystem(); m_impl->m_collisionSystem->registerCollisionFilter(*this); @@ -74,7 +83,8 @@ CollisionFilter::addCollision( ) { CollisionMap::iterator foundCollision = m_impl->m_collisions.find(CollisionId(collision.entityId1, collision.entityId2)); if (foundCollision != m_impl->m_collisions.end()) - foundCollision->second.addedCollisionDuration += collision.addedCollisionDuration; //Add collision time. + foundCollision->second.addedCollisionDuration += + collision.addedCollisionDuration; //Add collision time. else { CollisionId key(collision.entityId1, collision.entityId2); diff --git a/src/bullet/collision_filter.h b/src/bullet/collision_filter.h index b726808423a..09a62eeb81a 100644 --- a/src/bullet/collision_filter.h +++ b/src/bullet/collision_filter.h @@ -11,8 +11,8 @@ #include -namespace luabind { -class scope; +namespace sol { +class state; } namespace thrive { @@ -53,7 +53,7 @@ class CollisionFilter { using CollisionMap = std::unordered_map; using CollisionIterator = boost::range_detail::select_second_mutable_range; - + /** * @brief Constructor * @@ -82,7 +82,7 @@ class CollisionFilter { */ void init( - GameState* gameState + GameStateData* gameState ); /** @@ -102,8 +102,7 @@ class CollisionFilter { * - CollisionFilter::clearCollisions() * - CollisionFilter::removeCollision */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Returns the collisions that has occoured diff --git a/src/bullet/collision_shape.cpp b/src/bullet/collision_shape.cpp index 75393b7b2f8..3f1dd16af6f 100644 --- a/src/bullet/collision_shape.cpp +++ b/src/bullet/collision_shape.cpp @@ -2,9 +2,11 @@ #include "bullet/bullet_ogre_conversion.h" #include "engine/serialization.h" -#include "scripting/luabind.h" #include "util/make_unique.h" +// TODO: remove +#include + using namespace thrive; //////////////////////////////////////////////////////////////////////////////// @@ -36,17 +38,18 @@ CollisionShape::load( } } +void CollisionShape::luaBindings( + sol::state &lua +){ + lua.new_usertype("CollisionShape" + + ); -luabind::scope -CollisionShape::luaBindings() { - using namespace luabind; - return class_>("CollisionShape") - .enum_("Axis") [ - value("AXIS_X", CollisionShape::AXIS_X), - value("AXIS_Y", CollisionShape::AXIS_Y), - value("AXIS_Z", CollisionShape::AXIS_Z) - ] - ; + lua.new_enum("SHAPE_AXIS", + "X", CollisionShape::AXIS_X, + "Y", CollisionShape::AXIS_Y, + "Z", CollisionShape::AXIS_Z + ); } @@ -92,15 +95,21 @@ BoxShape::load( * * @return */ -luabind::scope -BoxShape::luaBindings() { - using namespace luabind; - return class_>("BoxShape") - .def(constructor()) - ; +void BoxShape::luaBindings( + sol::state &lua +){ + lua.new_usertype("BoxShape", + + "new", sol::factories([](const Ogre::Vector3 &extents){ + return std::make_shared(extents); + }), + + sol::base_classes, sol::bases(), + + LUA_CAST_FROM(BoxShape, CollisionShape) + ); } - BoxShape::BoxShape( const Ogre::Vector3& extents ) : m_bulletShape(new btBoxShape(ogreToBullet(extents))), @@ -157,15 +166,24 @@ CapsuleShape::load( * * @return */ -luabind::scope -CapsuleShape::luaBindings() { - using namespace luabind; - return class_>("CapsuleShape") - .def(constructor()) - ; +void CapsuleShape::luaBindings( + sol::state &lua +){ + lua.new_usertype("CapsuleShape", + + "new", sol::factories([](CollisionShape::Axis axis, + // I have no idea if these are the right names for these + btScalar extent1, btScalar extent2) + { + return std::make_shared(axis, extent1, extent2); + }), + + sol::base_classes, sol::bases(), + + LUA_CAST_FROM(CapsuleShape, CollisionShape) + ); } - CapsuleShape::CapsuleShape( CollisionShape::Axis axis, btScalar radius, @@ -251,18 +269,25 @@ CompoundShape::load( * * @return */ -luabind::scope -CompoundShape::luaBindings() { - using namespace luabind; - return class_>("CompoundShape") - .def(constructor<>()) - .def("addChildShape", &CompoundShape::addChildShape) - .def("clear", &CompoundShape::clear) - .def("removeChildShape", &CompoundShape::removeChildShape) - ; +void CompoundShape::luaBindings( + sol::state &lua +){ + lua.new_usertype("CompoundShape", + + "new", sol::factories([](){ + return std::make_shared(); + }), + + sol::base_classes, sol::bases(), + + LUA_CAST_FROM(CompoundShape, CollisionShape), + + "addChildShape", &CompoundShape::addChildShape, + "clear", &CompoundShape::clear, + "removeChildShape", &CompoundShape::removeChildShape + ); } - CompoundShape::CompoundShape() : m_bulletShape(new btCompoundShape()) { @@ -379,14 +404,23 @@ ConeShape::load( * * @return */ -luabind::scope -ConeShape::luaBindings() { - using namespace luabind; - return class_>("ConeShape") - .def(constructor()) - ; -} +void ConeShape::luaBindings( + sol::state &lua +){ + lua.new_usertype("ConeShape", + "new", sol::factories([](CollisionShape::Axis axis, + // I have no idea if these are the right names for these + btScalar extent1, btScalar extent2) + { + return std::make_shared(axis, extent1, extent2); + }), + + sol::base_classes, sol::bases(), + + LUA_CAST_FROM(ConeShape, CollisionShape) + ); +} ConeShape::ConeShape( CollisionShape::Axis axis, @@ -461,14 +495,23 @@ CylinderShape::load( * * @return */ -luabind::scope -CylinderShape::luaBindings() { - using namespace luabind; - return class_>("CylinderShape") - .def(constructor()) - ; -} +void CylinderShape::luaBindings( + sol::state &lua +){ + lua.new_usertype("CylinderShape", + "new", sol::factories([](CollisionShape::Axis axis, + // I have no idea if these are the right names for these + btScalar extent1, btScalar extent2) + { + return std::make_shared(axis, extent1, extent2); + }), + + sol::base_classes, sol::bases(), + + LUA_CAST_FROM(CylinderShape, CollisionShape) + ); +} CylinderShape::CylinderShape( CollisionShape::Axis axis, @@ -539,14 +582,22 @@ EmptyShape::load( * * @return */ -luabind::scope -EmptyShape::luaBindings() { - using namespace luabind; - return class_>("EmptyShape") - .def(constructor<>()) - ; -} +void EmptyShape::luaBindings( + sol::state &lua +){ + lua.new_usertype("EmptyShape", + "new", sol::factories([]() + { + return std::make_shared(); + }), + + sol::base_classes, sol::bases() + + // This probably won't need a casting function + //LUA_CAST_FROM(, CollisionShape) + ); +} EmptyShape::EmptyShape() : m_bulletShape(new btEmptyShape()) @@ -593,15 +644,22 @@ SphereShape::load( * * @return */ -luabind::scope -SphereShape::luaBindings() { - using namespace luabind; - return class_>("SphereShape") - .def(constructor()) - ; +void SphereShape::luaBindings( + sol::state &lua +){ + lua.new_usertype("SphereShape", + + "new", sol::factories([](btScalar radius) + { + return std::make_shared(radius); + }), + + sol::base_classes, sol::bases(), + + LUA_CAST_FROM(SphereShape, CollisionShape) + ); } - SphereShape::SphereShape( btScalar radius ) : m_bulletShape(new btSphereShape(radius)), diff --git a/src/bullet/collision_shape.h b/src/bullet/collision_shape.h index d14340caefc..eaad33f169e 100644 --- a/src/bullet/collision_shape.h +++ b/src/bullet/collision_shape.h @@ -6,8 +6,8 @@ #include #include -namespace luabind { - class scope; +namespace sol { +class state; } namespace thrive { @@ -77,8 +77,7 @@ class CollisionShape { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Destructor @@ -122,38 +121,34 @@ class CollisionShape { * The name of the wrapped Bullet shape class * */ -#define SHAPE_CLASS(cls, type, bulletShapeClass) \ - public: \ - \ - /** - * @brief The ShapeType associated with this class - */ \ - static const ShapeType SHAPE_TYPE = type; \ - \ - static std::unique_ptr \ - load( \ - const StorageContainer& storage \ - ); \ - \ - static luabind::scope \ - luaBindings(); \ - \ - btCollisionShape* \ - bulletShape() const override { \ - return m_bulletShape.get(); \ - } \ - \ - ShapeType \ - shapeType() const override { \ - return SHAPE_TYPE; \ - } \ - \ - StorageContainer \ - storage() const override; \ - \ - private: \ - \ - std::unique_ptr m_bulletShape; +#define SHAPE_CLASS(cls, type, bulletShapeClass) \ +public: \ + \ + static const ShapeType SHAPE_TYPE = type; \ + \ + static std::unique_ptr \ + load( \ + const StorageContainer& storage \ + ); \ + \ + static void luaBindings(sol::state &lua); \ + \ + btCollisionShape* \ + bulletShape() const override { \ + return m_bulletShape.get(); \ + } \ + \ + ShapeType \ + shapeType() const override { \ + return SHAPE_TYPE; \ + } \ + \ + StorageContainer \ + storage() const override; \ + \ +private: \ + \ + std::unique_ptr m_bulletShape; //////////////////////////////////////////////////////////////////////////////// diff --git a/src/bullet/collision_system.cpp b/src/bullet/collision_system.cpp index f9ba3cf60ca..dc531fa68da 100644 --- a/src/bullet/collision_system.cpp +++ b/src/bullet/collision_system.cpp @@ -1,8 +1,9 @@ #include "bullet/collision_system.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include "bullet/collision_filter.h" +#include "bullet/physical_world.h" #include "engine/component_factory.h" #include "engine/engine.h" #include "engine/entity.h" @@ -29,20 +30,19 @@ CollisionComponent::CollisionComponent( { } -luabind::scope -CollisionComponent::luaBindings() { - using namespace luabind; - return class_("CollisionComponent") - .enum_("ID") [ - value("TYPE_ID", CollisionComponent::TYPE_ID) - ] - .scope [ - def("TYPE_NAME", &CollisionComponent::TYPE_NAME) - ] - .def(constructor<>()) - .def(constructor()) - .def("addCollisionGroup", &CollisionComponent::addCollisionGroup) - ; +void CollisionComponent::luaBindings( + sol::state &lua +){ + lua.new_usertype("CollisionComponent", + + "new", sol::factories([](){ + return std::make_unique(); + }), + + COMPONENT_BINDINGS(CollisionComponent), + + "addCollisionGroup", &CollisionComponent::addCollisionGroup + ); } void @@ -110,15 +110,17 @@ Collision::Collision( { } -luabind::scope -Collision::luaBindings() { - using namespace luabind; - return class_("Collision") - .def(constructor()) - .def_readonly("entityId1", &Collision::entityId1) - .def_readonly("entityId2", &Collision::entityId2) - .def_readonly("addedCollisionDuration", &Collision::addedCollisionDuration) - ; +void Collision::luaBindings( + sol::state &lua +){ + lua.new_usertype("Collision", + + sol::constructors>(), + + "entityId1", sol::readonly(&Collision::entityId1), + "entityId2", sol::readonly(&Collision::entityId2), + "addedCollisionDuration", sol::readonly(&Collision::addedCollisionDuration) + ); } @@ -144,22 +146,25 @@ CollisionSystem::CollisionSystem() CollisionSystem::~CollisionSystem() {} +void CollisionSystem::luaBindings( + sol::state &lua +){ + lua.new_usertype("CollisionSystem", -luabind::scope -CollisionSystem::luaBindings() { - using namespace luabind; - return class_("CollisionSystem") - .def(constructor<>()) - ; -} + sol::constructors>(), + + sol::base_classes, sol::bases(), + "init", &CollisionSystem::init + ); +} void CollisionSystem::init( - GameState* gameState + GameStateData* gameState ) { System::initNamed("CollisionSystem", gameState); - m_impl->m_world = gameState->physicsWorld(); + m_impl->m_world = gameState->physicalWorld()->physicsWorld(); } @@ -186,10 +191,10 @@ CollisionSystem::update( EntityId entityId1 = (reinterpret_cast(objectA->getUserPointer())); EntityId entityId2 = (reinterpret_cast(objectB->getUserPointer())); CollisionComponent* collisionComponent1 = static_cast( - System::gameState()->entityManager().getComponent(entityId1, CollisionComponent::TYPE_ID) + System::gameState()->entityManager()->getComponent(entityId1, CollisionComponent::TYPE_ID) ); CollisionComponent* collisionComponent2 = static_cast( - System::gameState()->entityManager().getComponent(entityId2, CollisionComponent::TYPE_ID) + System::gameState()->entityManager()->getComponent(entityId2, CollisionComponent::TYPE_ID) ); if (collisionComponent1 && collisionComponent2) { diff --git a/src/bullet/collision_system.h b/src/bullet/collision_system.h index 4a277ce854c..0bc49a6c417 100644 --- a/src/bullet/collision_system.h +++ b/src/bullet/collision_system.h @@ -8,8 +8,8 @@ #include #include -namespace luabind { -class scope; +namespace sol { +class state; } namespace thrive { @@ -51,8 +51,7 @@ class CollisionComponent : public Component { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Add a collision group @@ -128,8 +127,7 @@ struct Collision { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief First collided entity @@ -203,8 +201,7 @@ class CollisionSystem : public System { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Initializes the engine @@ -212,7 +209,7 @@ class CollisionSystem : public System { * @param engine */ void init( - GameState* gameState + GameStateData* gameState ) override; /** diff --git a/src/bullet/debug_drawing.cpp b/src/bullet/debug_drawing.cpp index ac8e0a761f4..b90e0f1fd8a 100644 --- a/src/bullet/debug_drawing.cpp +++ b/src/bullet/debug_drawing.cpp @@ -1,8 +1,10 @@ #include "bullet/debug_drawing.h" #include "bullet/bullet_ogre_conversion.h" +#include "bullet/physical_world.h" #include "engine/game_state.h" -#include "scripting/luabind.h" + +#include "scripting/luajit.h" #include #include @@ -278,14 +280,14 @@ BulletDebugDrawer::getDebugMode() const // BulletDebugDrawSystem //////////////////////////////////////////////////////////////////////////////// -luabind::scope -BulletDebugDrawSystem::luaBindings() { - using namespace luabind; - return class_("BulletDebugDrawSystem") - .def(constructor<>()) - ; -} +void BulletDebugDrawSystem::luaBindings( + sol::state &lua +){ + lua.new_usertype("BulletDebugDrawSystem", + sol::constructors>() + ); +} struct BulletDebugDrawSystem::Implementation { @@ -307,14 +309,14 @@ BulletDebugDrawSystem::~BulletDebugDrawSystem() {} void BulletDebugDrawSystem::init( - GameState* gameState + GameStateData* gameState ) { System::initNamed("BulletDebugDrawSystem", gameState); assert(m_impl->m_physicsWorld == nullptr && "Double init of system"); m_impl->m_debugDrawer.reset(new BulletDebugDrawer( gameState->sceneManager() )); - m_impl->m_physicsWorld = gameState->physicsWorld(); + m_impl->m_physicsWorld = gameState->physicalWorld()->physicsWorld(); m_impl->m_physicsWorld->setDebugDrawer( m_impl->m_debugDrawer.get() ); diff --git a/src/bullet/debug_drawing.h b/src/bullet/debug_drawing.h index 01bafee55e8..e7249d80fcb 100644 --- a/src/bullet/debug_drawing.h +++ b/src/bullet/debug_drawing.h @@ -186,8 +186,7 @@ class BulletDebugDrawSystem : public System { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -203,7 +202,7 @@ class BulletDebugDrawSystem : public System { * @brief Initializes the system * */ - void init(GameState* gameState) override; + void init(GameStateData* gameState) override; /** * @brief Shuts the system down diff --git a/src/bullet/physical_world.cpp b/src/bullet/physical_world.cpp new file mode 100644 index 00000000000..5c49de21fde --- /dev/null +++ b/src/bullet/physical_world.cpp @@ -0,0 +1,59 @@ +#include "physical_world.h" + +#include "scripting/luajit.h" + +#include + +using namespace thrive; + + +void PhysicalWorld::luaBindings(sol::state &lua){ + + lua.new_usertype("PhysicalWorld", + + sol::constructors>() + ); + +} + + +struct PhysicalWorld::PhysicsConfiguration{ + + std::unique_ptr broadphase; + + std::unique_ptr collisionConfiguration; + + std::unique_ptr dispatcher; + + std::unique_ptr solver; + + std::unique_ptr world; +}; + +PhysicalWorld::PhysicalWorld(){ + + m_physics = std::make_unique(); + + m_physics->collisionConfiguration.reset(new btDefaultCollisionConfiguration()); + m_physics->dispatcher.reset(new btCollisionDispatcher( + m_physics->collisionConfiguration.get() + )); + m_physics->broadphase.reset(new btDbvtBroadphase()); + m_physics->solver.reset(new btSequentialImpulseConstraintSolver()); + m_physics->world.reset(new btDiscreteDynamicsWorld( + m_physics->dispatcher.get(), + m_physics->broadphase.get(), + m_physics->solver.get(), + m_physics->collisionConfiguration.get() + )); + m_physics->world->setGravity(btVector3(0,0,0)); +} + + +btDiscreteDynamicsWorld* +PhysicalWorld::physicsWorld(){ + + return m_physics->world.get(); +} + + diff --git a/src/bullet/physical_world.h b/src/bullet/physical_world.h new file mode 100644 index 00000000000..5dd0bf5198a --- /dev/null +++ b/src/bullet/physical_world.h @@ -0,0 +1,46 @@ +#pragma once + +#include + +struct btDiscreteDynamicsWorld; + +namespace sol{ + +class state; +} + +namespace thrive{ + +//! \brief Wrapper for holding a Bullet configuration in lua +class PhysicalWorld{ + + struct PhysicsConfiguration; + +public: + + /** + * @brief Lua bindings + * + * Exposes: + * - PhysicalWorld() + * + * @return + */ + static void luaBindings(sol::state &lua); + + + //! \brief Creates and sets up all the physics objects + PhysicalWorld(); + + + btDiscreteDynamicsWorld* + physicsWorld(); + + +private: + + std::unique_ptr m_physics; +}; + + +} diff --git a/src/bullet/rigid_body_system.cpp b/src/bullet/rigid_body_system.cpp index 1c4826accc0..e40132155b0 100644 --- a/src/bullet/rigid_body_system.cpp +++ b/src/bullet/rigid_body_system.cpp @@ -1,10 +1,11 @@ #include "bullet/rigid_body_system.h" #include "bullet/bullet_ogre_conversion.h" +#include "bullet/physical_world.h" #include "engine/component_factory.h" #include "engine/game_state.h" #include "engine/entity_filter.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include "engine/serialization.h" #include @@ -12,7 +13,7 @@ using namespace thrive; -const int PI = 3.1416f; +const auto PI = 3.1416f; const float PUSHBACK_DIST = 2.2f; //Used for incrementally pushing emissions out of the emitters body //////////////////////////////////////////////////////////////////////////////// @@ -78,48 +79,64 @@ RigidBodyComponent::reenableAllCollisions() { m_shouldReenableAllCollisions = true; } -luabind::scope -RigidBodyComponent::luaBindings() { - using namespace luabind; - return class_("RigidBodyComponent") - .enum_("ID") [ - value("TYPE_ID", RigidBodyComponent::TYPE_ID) - ] - .scope [ - def("TYPE_NAME", &RigidBodyComponent::TYPE_NAME), - class_("DynamicProperties") - .def_readwrite("position", &DynamicProperties::position) - .def_readwrite("rotation", &DynamicProperties::rotation) - .def_readwrite("linearVelocity", &DynamicProperties::linearVelocity) - .def_readwrite("angularVelocity", &DynamicProperties::angularVelocity), - class_("Properties") - .def_readwrite("shape", &Properties::shape) - .def_readwrite("restitution", &Properties::restitution) - .def_readwrite("linearFactor", &Properties::linearFactor) - .def_readwrite("angularFactor", &Properties::angularFactor) - .def_readwrite("linearDamping", &Properties::linearDamping) - .def_readwrite("angularDamping", &Properties::angularDamping) - .def_readwrite("mass", &Properties::mass) - .def_readwrite("friction", &Properties::friction) - .def_readwrite("rollingFriction", &Properties::rollingFriction) - .def_readwrite("hasContactResponse", &Properties::hasContactResponse) - .def_readwrite("kinematic", &Properties::kinematic) - ] - .def(constructor<>()) - .def("setDynamicProperties", &RigidBodyComponent::setDynamicProperties) - .def("applyImpulse", &RigidBodyComponent::applyImpulse) - .def("applyCentralImpulse", &RigidBodyComponent::applyCentralImpulse) - .def("applyTorque", &RigidBodyComponent::applyTorque) - .def("clearForces", &RigidBodyComponent::clearForces) - .def("disableCollisionsWith", &RigidBodyComponent::disableCollisionsWith) - .def("reenableAllCollisions", &RigidBodyComponent::reenableAllCollisions) - .def_readonly("properties", &RigidBodyComponent::m_properties) - .def_readonly("dynamicProperties", &RigidBodyComponent::m_dynamicProperties) - .def_readwrite("pushbackEntity", &RigidBodyComponent::m_pushbackEntity) - .def_readwrite("m_pushbackAngle", &RigidBodyComponent::m_pushbackAngle) - ; -} +void RigidBodyComponent::luaBindings( + sol::state &lua +){ + // DynamicProperties + lua.new_usertype("RigidBodyComponent.DynamicProperties", + + "new", sol::no_constructor, + + sol::base_classes, sol::bases(), + + "position", &DynamicProperties::position, + "rotation", &DynamicProperties::rotation, + "linearVelocity", &DynamicProperties::linearVelocity, + "angularVelocity", &DynamicProperties::angularVelocity + ); + // Properties + lua.new_usertype("RigidBodyComponent.Properties", + + "new", sol::no_constructor, + + sol::base_classes, sol::bases(), + + "shape", &Properties::shape, + "restitution", &Properties::restitution, + "linearFactor", &Properties::linearFactor, + "angularFactor", &Properties::angularFactor, + "linearDamping", &Properties::linearDamping, + "angularDamping", &Properties::angularDamping, + "mass", &Properties::mass, + "friction", &Properties::friction, + "rollingFriction", &Properties::rollingFriction, + "hasContactResponse", &Properties::hasContactResponse, + "kinematic", &Properties::kinematic + ); + + lua.new_usertype("RigidBodyComponent", + + "new", sol::factories([](){ + return std::make_unique(); + }), + + COMPONENT_BINDINGS(RigidBodyComponent), + + "setDynamicProperties", &RigidBodyComponent::setDynamicProperties, + "applyImpulse", &RigidBodyComponent::applyImpulse, + "applyCentralImpulse", &RigidBodyComponent::applyCentralImpulse, + "applyTorque", &RigidBodyComponent::applyTorque, + "clearForces", &RigidBodyComponent::clearForces, + "disableCollisionsWith", &RigidBodyComponent::disableCollisionsWith, + "reenableAllCollisions", &RigidBodyComponent::reenableAllCollisions, + + "properties", sol::readonly(&RigidBodyComponent::m_properties), + "dynamicProperties", sol::readonly(&RigidBodyComponent::m_dynamicProperties), + "pushbackEntity", &RigidBodyComponent::m_pushbackEntity, + "m_pushbackAngle", &RigidBodyComponent::m_pushbackAngle + ); +} void RigidBodyComponent::getWorldTransform( @@ -199,14 +216,18 @@ REGISTER_COMPONENT(RigidBodyComponent) // RigidBodyInputSystem //////////////////////////////////////////////////////////////////////////////// -luabind::scope -RigidBodyInputSystem::luaBindings() { - using namespace luabind; - return class_("RigidBodyInputSystem") - .def(constructor<>()) - ; -} +void RigidBodyInputSystem::luaBindings( + sol::state &lua +){ + lua.new_usertype("RigidBodyInputSystem", + sol::constructors>(), + + sol::base_classes, sol::bases(), + + "init", &RigidBodyInputSystem::init + ); +} struct RigidBodyInputSystem::Implementation { @@ -231,12 +252,12 @@ RigidBodyInputSystem::~RigidBodyInputSystem() {} void RigidBodyInputSystem::init( - GameState* gameState + GameStateData* gameState ) { System::initNamed("RigidBodyInputSystem", gameState); assert(m_impl->m_world == nullptr && "Double init of system"); - m_impl->m_world = gameState->physicsWorld(); - m_impl->m_entities.setEntityManager(&gameState->entityManager()); + m_impl->m_world = gameState->physicalWorld()->physicsWorld(); + m_impl->m_entities.setEntityManager(gameState->entityManager()); } @@ -455,14 +476,18 @@ RigidBodyInputSystem::update(int, int logicTime) { // RigidBodyOutputSystem //////////////////////////////////////////////////////////////////////////////// -luabind::scope -RigidBodyOutputSystem::luaBindings() { - using namespace luabind; - return class_("RigidBodyOutputSystem") - .def(constructor<>()) - ; -} +void RigidBodyOutputSystem::luaBindings( + sol::state &lua +){ + lua.new_usertype("RigidBodyOutputSystem", + sol::constructors>(), + + sol::base_classes, sol::bases(), + + "init", &RigidBodyOutputSystem::init + ); +} struct RigidBodyOutputSystem::Implementation { @@ -483,10 +508,10 @@ RigidBodyOutputSystem::~RigidBodyOutputSystem() {} void RigidBodyOutputSystem::init( - GameState* gameState + GameStateData* gameState ) { System::initNamed("RigidBodyOutputSystem", gameState); - m_impl->m_entities.setEntityManager(&gameState->entityManager()); + m_impl->m_entities.setEntityManager(gameState->entityManager()); } diff --git a/src/bullet/rigid_body_system.h b/src/bullet/rigid_body_system.h index a69f990130d..22df2f513e8 100644 --- a/src/bullet/rigid_body_system.h +++ b/src/bullet/rigid_body_system.h @@ -13,8 +13,8 @@ #include -namespace luabind { -class scope; +namespace sol { +class state; } namespace thrive { @@ -155,8 +155,7 @@ class RigidBodyComponent : public Component, public btMotionState { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -365,8 +364,7 @@ class RigidBodyInputSystem : public System { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -382,7 +380,7 @@ class RigidBodyInputSystem : public System { * @brief Initializes the system * */ - void init(GameState* gameState) override; + void init(GameStateData* gameState) override; /** * @brief Shuts the system down @@ -424,8 +422,7 @@ class RigidBodyOutputSystem : public System { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -441,7 +438,7 @@ class RigidBodyOutputSystem : public System { * @brief Initializes the engine * */ - void init(GameState* gameState) override; + void init(GameStateData* gameState) override; /** * @brief Shuts the system down diff --git a/src/bullet/script_bindings.cpp b/src/bullet/script_bindings.cpp deleted file mode 100644 index e67bbc8d577..00000000000 --- a/src/bullet/script_bindings.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "bullet/script_bindings.h" - -#include "bullet/bullet_ogre_conversion.h" -#include "bullet/bullet_to_ogre_system.h" -#include "bullet/collision_filter.h" -#include "bullet/collision_shape.h" -#include "bullet/collision_system.h" -#include "bullet/debug_drawing.h" -#include "bullet/rigid_body_system.h" -#include "bullet/update_physics_system.h" -#include "scripting/luabind.h" - -#include -#include -#include -#include - -using namespace luabind; -using namespace thrive; - - -luabind::scope -thrive::BulletBindings::luaBindings() { - return ( - // Shapes - CollisionShape::luaBindings(), - BoxShape::luaBindings(), - CapsuleShape::luaBindings(), - CompoundShape::luaBindings(), - ConeShape::luaBindings(), - CylinderShape::luaBindings(), - EmptyShape::luaBindings(), - SphereShape::luaBindings(), - // Components - RigidBodyComponent::luaBindings(), - CollisionComponent::luaBindings(), - // Systems - BulletToOgreSystem::luaBindings(), - RigidBodyInputSystem::luaBindings(), - RigidBodyOutputSystem::luaBindings(), - BulletDebugDrawSystem::luaBindings(), - UpdatePhysicsSystem::luaBindings(), - CollisionSystem::luaBindings(), - // Other - CollisionFilter::luaBindings(), - Collision::luaBindings() - ); -} diff --git a/src/bullet/script_bindings.h b/src/bullet/script_bindings.h deleted file mode 100644 index abb8094f87e..00000000000 --- a/src/bullet/script_bindings.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -namespace luabind { -class scope; -} - -namespace thrive { - -/** -* @brief Helper for Bullet script bindings -*/ -struct BulletBindings { - - /** - * @brief Lua bindings for physics systems - * - * @return - */ - static luabind::scope - luaBindings(); - -}; - -} - diff --git a/src/bullet/update_physics_system.cpp b/src/bullet/update_physics_system.cpp index da9fc0a571f..3b1335b09b2 100644 --- a/src/bullet/update_physics_system.cpp +++ b/src/bullet/update_physics_system.cpp @@ -1,7 +1,9 @@ #include "bullet/update_physics_system.h" + +#include "bullet/physical_world.h" #include "engine/game_state.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include #include @@ -9,14 +11,18 @@ using namespace thrive; -luabind::scope -UpdatePhysicsSystem::luaBindings() { - using namespace luabind; - return class_("UpdatePhysicsSystem") - .def(constructor<>()) - ; -} +void UpdatePhysicsSystem::luaBindings( + sol::state &lua +){ + lua.new_usertype("UpdatePhysicsSystem", + sol::constructors>(), + + sol::base_classes, sol::bases(), + + "init", &UpdatePhysicsSystem::init + ); +} struct UpdatePhysicsSystem::Implementation { @@ -36,10 +42,10 @@ UpdatePhysicsSystem::~UpdatePhysicsSystem() {} void UpdatePhysicsSystem::init( - GameState* gameState + GameStateData* gameState ) { System::initNamed("UpdatePhysicsSystem", gameState); - m_impl->m_world = gameState->physicsWorld(); + m_impl->m_world = gameState->physicalWorld()->physicsWorld(); assert(m_impl->m_world != nullptr && "World object is null. Initialize the Engine first."); } diff --git a/src/bullet/update_physics_system.h b/src/bullet/update_physics_system.h index 659e5061174..8938b6d6a56 100644 --- a/src/bullet/update_physics_system.h +++ b/src/bullet/update_physics_system.h @@ -21,8 +21,7 @@ class UpdatePhysicsSystem : public System { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -40,7 +39,7 @@ class UpdatePhysicsSystem : public System { */ void init( - GameState* gameState + GameStateData* gameState ) override; /** diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt index aa5bb5e9390..2619b7fa7ab 100644 --- a/src/engine/CMakeLists.txt +++ b/src/engine/CMakeLists.txt @@ -21,8 +21,6 @@ add_sources( "${CMAKE_CURRENT_SOURCE_DIR}/rng.h" "${CMAKE_CURRENT_SOURCE_DIR}/rolling_grid.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/rolling_grid.h" - "${CMAKE_CURRENT_SOURCE_DIR}/script_bindings.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/script_bindings.h" "${CMAKE_CURRENT_SOURCE_DIR}/serialization.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/serialization.h" "${CMAKE_CURRENT_SOURCE_DIR}/system.cpp" diff --git a/src/engine/component.cpp b/src/engine/component.cpp index a96689e1308..1a9c56ff760 100644 --- a/src/engine/component.cpp +++ b/src/engine/component.cpp @@ -4,101 +4,27 @@ #include "engine/engine.h" #include "engine/serialization.h" #include "game.h" -#include "scripting/luabind.h" - -#include +#include "scripting/luajit.h" using namespace thrive; -template -static std::string -getLuaClassName( - lua_State* L, - T* obj -) { - luabind::object(L, obj).push(L); - luabind::argument argument(luabind::from_stack(L, lua_gettop(L))); - luabind::class_info info = luabind::get_class_info(argument); - std::string name = info.name; - lua_pop(L, 1); - return name; -} - -/** -* @brief Wrapper class to enable subclassing Component in Lua -* -* \cond -*/ -struct ComponentWrapper : Component, luabind::wrap_base { - - ComponentWrapper( - lua_State* L - ) : m_luaState(L) - { - } - - void - load( - const StorageContainer& storage - ) override { - call("load", storage); - } - - static void default_load( - Component* self, - const StorageContainer& storage - ) { - self->Component::load(storage); - } - - ComponentTypeId - typeId() const override { - return Game::instance().engine().componentFactory().getTypeId( - this->typeName() - ); - } - - std::string - typeName() const override { - return getLuaClassName(m_luaState, this); - } - - StorageContainer - storage() const override { - return call("storage"); - } - - static StorageContainer - default_storage( - Component* self - ) { - return self->Component::storage(); - } - - lua_State* m_luaState = nullptr; - -}; - -/** - * \endcond - */ - -luabind::scope -Component::luaBindings() { - using namespace luabind; - return class_("Component") - .def(constructor()) - .def("isVolatile", &Component::isVolatile) - .def("load", &Component::load, &ComponentWrapper::default_load) - .def("setVolatile", &Component::setVolatile) - .def("storage", &Component::storage, &ComponentWrapper::default_storage) - .def("typeId", &Component::typeId) - .def("typeName", &Component::typeName) - .def("owner", &Component::owner) - ; +void Component::luaBindings( + sol::state &lua +){ + lua.new_usertype("Component", + + "new", sol::no_constructor, + + "isVolatile", &Component::isVolatile, + "load", &Component::load, + "setVolatile", &Component::setVolatile, + "storage", &Component::storage, + "typeId", &Component::typeId, + "typeName", &Component::typeName, + "owner", &Component::owner + ); } - Component::~Component() {} diff --git a/src/engine/component.h b/src/engine/component.h index 1b1c3ecd771..bfa26a09010 100644 --- a/src/engine/component.h +++ b/src/engine/component.h @@ -9,8 +9,8 @@ #include #include -namespace luabind { -class scope; +namespace sol { +class state; } namespace thrive { @@ -43,8 +43,7 @@ class Component { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Destructor @@ -187,3 +186,18 @@ class Component { private: \ +/** +* @brief Fills in common Lua bindings for derived Components +* +* Uses a faster way to cast than dynamic_cast +*/ +#define COMPONENT_BINDINGS(name) \ +sol::base_classes, sol::bases(), \ +"castFrom", [](Component* baseptr){ \ + if(baseptr->typeId() != name::TYPE_ID) \ + return static_cast(nullptr); \ + return static_cast(baseptr); \ +}, \ +"TYPE_ID", sol::var(name::TYPE_ID), \ +"TYPE_NAME", &name::TYPE_NAME \ + diff --git a/src/engine/component_factory.cpp b/src/engine/component_factory.cpp index 67e329a6ba8..588df04d925 100644 --- a/src/engine/component_factory.cpp +++ b/src/engine/component_factory.cpp @@ -1,9 +1,8 @@ #include "engine/component_factory.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" -#include -#include +#include "scripting/wrapper_classes.h" using namespace thrive; @@ -38,42 +37,59 @@ static ComponentTypeId ComponentFactory_registerComponentType( ComponentFactory* self, const std::string& name, - luabind::object cls + sol::table cls ) { - lua_State* L = cls.interpreter(); - auto type = luabind::type(cls); - if (type != LUA_TUSERDATA) { - std::string typeName( - lua_typename(L, type) - ); - throw std::runtime_error("Argument 2 must be class object, but is: " + typeName); + + auto type = cls.get_type(); + + if (type != sol::type::table) { + + std::string typeName(lua_typename(cls.lua_state(), static_cast(type))); + + throw std::runtime_error("Argument 2 must be table (class) object, but is: " + + typeName); } + + // Check 'new' function exists + auto factoryFunc = cls.get>("new"); + + if(!factoryFunc) + throw std::runtime_error("Lua component type is missing 'new' function"); + ComponentTypeId typeId = self->registerComponentType( name, [cls] (const StorageContainer& storage) { - luabind::object classTable = cls; - luabind::object obj = classTable(); + const auto result = cls.get("new")(); + + if(!result.valid()) + throw std::runtime_error("ComponentFactory failed to call 'new' " + "on Lua component type"); + + sol::table obj = result.get(); + auto component = std::unique_ptr( - luabind::object_cast(obj, luabind::adopt(luabind::result)) + new ComponentWrapper(obj) ); + component->load(storage); return component; } ); + cls["TYPE_ID"] = typeId; return typeId; } +void ComponentFactory::luaBindings( + sol::state &lua +){ + lua.new_usertype("ComponentFactory", -luabind::scope -ComponentFactory::luaBindings() { - using namespace luabind; - return class_("ComponentFactory") - .def("registerComponentType", &ComponentFactory_registerComponentType) - ; + "new", sol::no_constructor, + "registerComponentType", &ComponentFactory_registerComponentType + ); } - ComponentTypeId ComponentFactory::registerGlobalComponentType( const std::string& name, diff --git a/src/engine/component_factory.h b/src/engine/component_factory.h index 9f3714563b8..8236924d5c0 100644 --- a/src/engine/component_factory.h +++ b/src/engine/component_factory.h @@ -3,8 +3,8 @@ #include "engine/component.h" #include "util/make_unique.h" -namespace luabind { - class scope; +namespace sol { +class state; } namespace thrive { @@ -36,8 +36,7 @@ class ComponentFactory { * - ComponentFactory::registerComponentType * */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 4234cb8d1e2..675b3d42edb 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -37,9 +37,8 @@ #include "gui/VideoPlayer.h" // Scripting -#include -#include "scripting/luabind.h" -#include "scripting/lua_state.h" +#include "luajit/src/lua.hpp" +#include "scripting/luajit.h" #include "scripting/script_initializer.h" // Microbe @@ -59,11 +58,12 @@ #include #include #include -#include #include #include #include #include +#include +#include #include #include #include @@ -77,6 +77,8 @@ #include #include "sound/sound_manager.h" +#include + using namespace thrive; static const char* RESOURCES_CFG = "resources.cfg"; @@ -92,33 +94,18 @@ struct Engine::Implementation : public Ogre::WindowEventListener { Engine& engine ) : m_engine(engine), m_rng(), - m_playerData("player"), - m_nextShutdownSystems(new std::map), - m_prevShutdownSystems(new std::map) + m_playerData("player") { } ~Implementation() { + Ogre::WindowEventUtilities::removeWindowEventListener( m_graphics.renderWindow, this ); } - void - activateGameState( - GameState* gameState - ) { - if (m_currentGameState) { - m_currentGameState->deactivate(); - } - m_currentGameState = gameState; - if (gameState) { - gameState->activate(); - gameState->rootGUIWindow().addChild(m_consoleGUIWindow); - luabind::call_member(m_console, "registerEvents", gameState); - } - } void loadSavegame() { @@ -137,42 +124,16 @@ struct Engine::Implementation : public Ogre::WindowEventListener { std::cerr << "Error loading file: " << e.what() << std::endl; throw; } + // Load game states - GameState* previousGameState = m_currentGameState; - this->activateGameState(nullptr); - StorageContainer gameStates = savegame.get("gameStates"); - for (const auto& pair : m_gameStates) { - if (gameStates.contains(pair.first)) { - // In case anything relies on the current game state - // during loading, temporarily switch it - m_currentGameState = pair.second.get(); - pair.second->load( - gameStates.get(pair.first) - ); - } - else { - pair.second->entityManager().clear(); - } - } - for (auto& kv : *m_prevShutdownSystems) { - kv.first->deactivate(); - } - for (auto& kv : *m_nextShutdownSystems) { - kv.first->deactivate(); - } - m_prevShutdownSystems->clear(); - m_nextShutdownSystems->clear(); - m_currentGameState = nullptr; - // Switch gamestate - std::string gameStateName = savegame.get("currentGameState"); - auto iter = m_gameStates.find(gameStateName); - if (iter != m_gameStates.end()) { - this->activateGameState(iter->second.get()); - } - else { - this->activateGameState(previousGameState); - // TODO: Log error + sol::protected_function luaMethod = m_luaState["g_luaEngine"] + ["loadSavegameGameStates"]; + + if(!luaMethod(m_luaState["g_luaEngine"], &savegame).valid()){ + + throw std::runtime_error("LuaEngine failed to load saved game states"); } + m_playerData.load(savegame.get("playerData")); } @@ -205,7 +166,13 @@ struct Engine::Implementation : public Ogre::WindowEventListener { } } - void + /** + * @brief Loads lua scripts from folder. + * + * Looks for a "manifest.txt" to determine which files to load + * @returns True on success, false on failure + */ + bool loadScripts( const boost::filesystem::path& directory ) { @@ -213,7 +180,7 @@ struct Engine::Implementation : public Ogre::WindowEventListener { fs::path manifestPath = directory / "manifest.txt"; if (not fs::exists(manifestPath)) { throw std::runtime_error("Missing manifest file: " + manifestPath.string()); - return; + return false; } std::ifstream manifest(manifestPath.string()); if (not manifest.is_open()) { @@ -232,34 +199,49 @@ struct Engine::Implementation : public Ogre::WindowEventListener { continue; } else if (fs::is_directory(manifestEntryPath)) { - this->loadScripts(manifestEntryPath); + bool success = this->loadScripts(manifestEntryPath); + + if(!success) + return false; } else { - int error = 0; - error = luaL_loadfile( - m_luaState, - manifestEntryPath.string().c_str() - ); - error = error or luabind::detail::pcall(m_luaState, 0, LUA_MULTRET); - if (error) { - std::string errorMessage = lua_tostring(m_luaState, -1); - lua_pop(m_luaState, 1); - std::cerr << errorMessage << std::endl; + + sol::protected_function fileFunc = + m_luaState.load_file(manifestEntryPath.string().c_str()); + + auto runResult = fileFunc(); + + if(runResult.status() != sol::call_status::ok){ + + std::cerr << "Failed to run Lua file: " << manifestEntryPath.string() << + std::endl << " error: " << runResult.get() << + std::endl; + + return false; } + + //std::cout << "Loaded Lua file: " << manifestEntryPath.string() << std::endl; } } + + return true; } void saveSavegame() { StorageContainer savegame; - savegame.set("currentGameState", m_currentGameState->name()); - savegame.set("playerData", m_playerData.storage()); - StorageContainer gameStates; - for (const auto& pair : m_gameStates) { - gameStates.set(pair.first, pair.second->storage()); + + // Load game states + sol::protected_function luaMethod = m_luaState["g_luaEngine"] + ["saveCurrentStates"]; + + if(!luaMethod(m_luaState["g_luaEngine"], &savegame).valid()){ + + throw std::runtime_error("LuaEngine failed to save game states"); } - savegame.set("gameStates", std::move(gameStates)); + + savegame.set("playerData", m_playerData.storage()); + savegame.set("thriveversion", m_thriveVersion); std::ofstream stream( m_serialization.saveFile, @@ -338,7 +320,7 @@ struct Engine::Implementation : public Ogre::WindowEventListener { // Load gui Images needed by AlphaHitWindow // // This loads this image before continuing. Could be in a background thread m_guiHelper.getTexture("ThriveGeneric.png"); - + CEGUI::WindowFactoryManager::addFactory >(); CEGUI::OgreRenderer::bootstrapSystem(); @@ -351,9 +333,9 @@ struct Engine::Implementation : public Ogre::WindowEventListener { CEGUI::System::getSingleton().getDefaultGUIContext().getCursor().setDefaultImage( "ThriveGeneric/MouseArrow"); - m_aggregator = std::move(std::unique_ptr( + m_aggregator = std::unique_ptr( new CEGUI::InputAggregator(&CEGUI::System::getSingleton() - .getDefaultGUIContext()))); + .getDefaultGUIContext())); // Using the handling on keydown mode to detect when inputs are consumed m_aggregator->initialise(false); @@ -385,14 +367,11 @@ struct Engine::Implementation : public Ogre::WindowEventListener { CEGUI::ImageManager::getSingleton().loadImageset("DriveIcons.imageset"); CEGUI::ImageManager::getSingleton().loadImageset("HUDDemo.imageset"); - - m_consoleGUIWindow = new CEGUIWindow("Console"); } void setupLog() { - static Ogre::LogManager logManager; - logManager.createLog("ogre.log", true, false, false); + m_graphics.logManager.createLog("ogre.log", true, false, false); } void @@ -404,7 +383,7 @@ struct Engine::Implementation : public Ogre::WindowEventListener { setupSoundManager() { static const std::string DEVICE_NAME = ""; - m_soundManager = std::move(std::unique_ptr(new SoundManager())); + m_soundManager = std::unique_ptr(new SoundManager()); m_soundManager->init(DEVICE_NAME); //soundManager.setDistanceModel(AL_LINEAR_DISTANCE); @@ -412,16 +391,43 @@ struct Engine::Implementation : public Ogre::WindowEventListener { void loadVersionNumber() { - std::ifstream versionFile ("thriveversion.ver"); - if (versionFile.is_open()) { - std::getline(versionFile, m_thriveVersion); + + if(!readVersionFile("thriveversion.ver")){ + + // Backup location // + if(!readVersionFile("../thriveversion.ver")){ + + // Unable to find version // + m_thriveVersion = "unknown"; + } } - else { - m_thriveVersion = "unknown"; + } + + /** + * @brief Helper for loadVersionNumber + * @returns True if file was valid + */ + bool + readVersionFile( + const std::string &file + ) { + std::ifstream versionFile (file); + + if(versionFile.is_open()){ + + std::getline(versionFile, m_thriveVersion); + + // Check for successfull read // + if(m_thriveVersion.empty()) + return false; + + return true; } - versionFile.close(); + + return false; } + void shutdownInputManager() { if (not m_input.inputManager) { @@ -454,23 +460,29 @@ struct Engine::Implementation : public Ogre::WindowEventListener { CEGUI::System::getSingleton().getRenderer()->setDisplaySize(CEGUI::Sizef(window->getWidth(), window->getHeight())); } - // Lua state must be one of the last to be destroyed, so keep it at top. - // The reason for that is that some components keep luabind::object - // instances around that rely on the lua state to still exist when they - // are destroyed. Since those components are destroyed with the entity - // manager, the lua state has to live longer than the manager. - LuaState m_luaState; + // This actually needs to be the last thing destroyed as bunch of Lua owned + // objects keep Ogre::SceneManagers and other things alive + struct Graphics { - GameState* m_currentGameState = nullptr; - CEGUIWindow* m_consoleGUIWindow = nullptr; + Ogre::LogManager logManager; - ComponentFactory m_componentFactory; + std::unique_ptr root; - Engine& m_engine; + Ogre::RenderWindow* renderWindow = nullptr; - std::map> m_gameStates; + } m_graphics; - std::list> m_entitiesToTransferGameState; + // Lua state must be one of the last to be destroyed, so keep it + // at top. The reason for that is that some components keep + // sol::object instances around that rely on the lua state to + // still exist when they are destroyed. Since those components are + // destroyed with the entity manager, the lua state has to live + // longer than the manager. + sol::state m_luaState; + + ComponentFactory m_componentFactory; + + Engine& m_engine; RNG m_rng; @@ -480,17 +492,6 @@ struct Engine::Implementation : public Ogre::WindowEventListener { bool m_paused = false; - std::map* m_nextShutdownSystems; - std::map* m_prevShutdownSystems; - - struct Graphics { - - std::unique_ptr root; - - Ogre::RenderWindow* renderWindow = nullptr; - - } m_graphics; - struct Input { OIS::InputManager* inputManager = nullptr; @@ -501,8 +502,6 @@ struct Engine::Implementation : public Ogre::WindowEventListener { } m_input; - GameState* m_nextGameState = nullptr; - std::string m_thriveVersion; struct Serialization { @@ -513,78 +512,48 @@ struct Engine::Implementation : public Ogre::WindowEventListener { } m_serialization; - luabind::object m_console; std::unique_ptr m_soundManager; std::unique_ptr m_aggregator; GUITextureHelper m_guiHelper; }; - -static GameState* -Engine_createGameState( - Engine* self, - std::string name, - luabind::object luaSystems, - luabind::object luaInitializer, - std::string guiLayoutName -) { - std::vector> systems; - for (luabind::iterator iter(luaSystems), end; iter != end; ++iter) { - System* system = luabind::object_cast( - *iter, - luabind::adopt(luabind::result) - ); - systems.emplace_back(system); - } - // We can't just capture the luaInitializer in the lambda here, because - // luabind::object's call operator is not const - auto initializer = std::bind( - [](luabind::object luaInitializer) { - luaInitializer(); - }, - luaInitializer - ); - return self->createGameState( - name, - std::move(systems), - initializer, - guiLayoutName +void Engine::luaBindings( + sol::state &lua +){ + lua.new_usertype("__Engine", + + "new", sol::no_constructor, + + "playerData", &Engine::playerData, + "load", &Engine::load, + "save", &Engine::save, + "fileExists", &Engine::fileExists, + "saveCreation", static_cast(&Engine::saveCreation), + "loadCreation", static_cast(&Engine::loadCreation), + "screenShot", &Engine::screenShot, + "getCreationFileList", &Engine::getCreationFileList, + "quit", &Engine::quit, + "thriveVersion", sol::property(&Engine::thriveVersion), + "update", &Engine::update, + "pauseGame", &Engine::pauseGame, + "resumeGame", &Engine::resumeGame, + "getResolutionHeight", &Engine::getResolutionHeight, + "getResolutionWidth", &Engine::getResolutionWidth, + "componentFactory", sol::property(&Engine::componentFactory), + "keyboard", sol::property(&Engine::keyboard), + "mouse", sol::property(&Engine::mouse), + "paused", sol::property([](Engine &self){ + return self.m_impl->m_paused; + }), + + "luaMemory", sol::property([](Engine &self){ + return self.m_impl->m_luaState.memory_used(); + }) ); } - -luabind::scope -Engine::luaBindings() { - using namespace luabind; - return class_("__Engine") - .def("createGameState", Engine_createGameState) - .def("currentGameState", &Engine::currentGameState) - .def("getGameState", &Engine::getGameState) - .def("setCurrentGameState", &Engine::setCurrentGameState) - .def("playerData", &Engine::playerData) - .def("load", &Engine::load) - .def("save", &Engine::save) - .def("fileExists", &Engine::fileExists) - .def("saveCreation", static_cast(&Engine::saveCreation)) - .def("loadCreation", static_cast(&Engine::loadCreation)) - .def("screenShot", &Engine::screenShot) - .def("getCreationFileList", &Engine::getCreationFileList) - .def("quit", &Engine::quit) - .def("timedSystemShutdown", &Engine::timedSystemShutdown) - .def("isSystemTimedShutdown", &Engine::isSystemTimedShutdown) - .def("thriveVersion", &Engine::thriveVersion) - .def("pauseGame", &Engine::pauseGame) - .def("resumeGame", &Engine::resumeGame) - .def("registerConsoleObject", &Engine::registerConsoleObject) - .def("getResolutionHeight", &Engine::getResolutionHeight) - .def("getResolutionWidth", &Engine::getResolutionWidth) - .property("componentFactory", &Engine::componentFactory) - .property("keyboard", &Engine::keyboard) - .property("mouse", &Engine::mouse) - ; -} - void Engine::pauseGame(){ m_impl->m_paused = true; @@ -609,79 +578,130 @@ Engine::componentFactory() { return m_impl->m_componentFactory; } - -GameState* -Engine::createGameState( - std::string name, - std::vector> systems, - GameState::Initializer initializer, - std::string guiLayoutName -) { - assert(m_impl->m_gameStates.find(name) == m_impl->m_gameStates.end() && "Duplicate GameState name"); - std::unique_ptr gameState(new GameState( - *this, - name, - std::move(systems), - initializer, - guiLayoutName - )); - GameState* rawGameState = gameState.get(); - m_impl->m_gameStates.insert(std::make_pair( - name, - std::move(gameState) - )); - return rawGameState; -} - - -GameState* -Engine::currentGameState() const { - return m_impl->m_currentGameState; -} - RNG& Engine::rng() { return m_impl->m_rng; } - -GameState* -Engine::getGameState( - const std::string& name -) const { - auto iter = m_impl->m_gameStates.find(name); - if (iter != m_impl->m_gameStates.end()) { - return iter->second.get(); - } - else { - return nullptr; - } -} - - void Engine::init() { - assert(m_impl->m_currentGameState == nullptr); std::srand(unsigned(time(0))); m_impl->setupLog(); m_impl->setupScripts(); + m_impl->loadVersionNumber(); + m_impl->setupGraphics(); m_impl->setupGUI(); + m_impl->setupInputManager(); - m_impl->loadScripts("../scripts"); - m_impl->loadVersionNumber(); - GameState* previousGameState = m_impl->m_currentGameState; - for (const auto& pair : m_impl->m_gameStates) { - const auto& gameState = pair.second; - m_impl->m_currentGameState = gameState.get(); - gameState->init(); + + // Install the Thrive error handler by default + sol::protected_function::set_default_handler(m_impl->m_luaState["thrivePanic"]); + + if(!m_impl->loadScripts("../scripts")){ + + throw std::runtime_error("Engine failed to load Lua scripts"); } + + + // Initialize lua engine side + sol::protected_function luaInit = m_impl->m_luaState["g_luaEngine"]["init"]; + + if(!luaInit(m_impl->m_luaState["g_luaEngine"], this).valid()){ + + throw std::runtime_error("Failed to initialize LuaEngine side"); + } + // OgreOggSoundManager must be initialized after at least one - // Ogre::SceneManager has been instantiated + // Ogre::SceneManager has been instantiated so we need to hope + // that the lua engine had a gamestate to initialize that uses + // Ogre m_impl->setupSoundManager(); - m_impl->m_currentGameState = previousGameState; + +} + +void +Engine::enterLuaMain( + Game* gameObj +) { + sol::protected_function luaMain = m_impl->m_luaState["enterLuaMain"]; + + luaMain(gameObj); +} + +EntityId +Engine::transferEntityGameState( + EntityId id, + EntityManager* entityManager, + GameStateData* targetState +) { + sol::protected_function luaMethod = m_impl->m_luaState["g_luaEngine"] + ["transferEntityGameState"]; + + auto result = luaMethod(m_impl->m_luaState["g_luaEngine"], + id, entityManager, targetState); + + if(!result.valid()) + { + throw std::runtime_error("Failed call LuaEngine:transferEntityGameState"); + } + + return result.get(); +} + +bool +Engine::isSystemTimedShutdown( + System* system +) { + sol::protected_function luaMethod = m_impl->m_luaState["g_luaEngine"] + ["isSystemTimedShutdown"]; + + auto result = luaMethod(m_impl->m_luaState["g_luaEngine"], + system); + + if(!result.valid()){ + + throw std::runtime_error("Failed call LuaEngine:isSystemTimedShutdown"); + } + + return result.get(); } +void +Engine::timedSystemShutdown( + System* system, + int timeInMS +) { + sol::protected_function luaMethod = m_impl->m_luaState["g_luaEngine"] + ["timedSystemShutdown"]; + + auto result = luaMethod(m_impl->m_luaState["g_luaEngine"], + system, timeInMS); + + if(!result.valid()){ + + throw std::runtime_error("Failed call LuaEngine:timedSystemShutdown"); + } +} + +GameStateData* +Engine::getCurrentGameStateFromLua( +) { + + sol::optional state = m_impl->m_luaState["g_luaEngine"]["currentGameState"] + ["wrapper"]; + + if(!state) + throw std::runtime_error("Engine: getCurrentGameStateFromLua failed to " + "get value (is state null?)"); + + GameStateData* statePtr = state.value(); + + if(!statePtr) + throw std::runtime_error("Engine: current GameStateData is nullptr"); + + return statePtr; +} OIS::InputManager* @@ -738,7 +758,7 @@ Engine::ogreRoot() const { GUITextureHelper& Engine::guiTextureHelper() const{ - + return m_impl->m_guiHelper; } @@ -762,7 +782,15 @@ Engine::saveCreation( std::string name, std::string type ) const { - saveCreation(entityId, this->currentGameState()->entityManager(), name, type); + + // Get current EntityManager + EntityManager* currentManager = m_impl->m_luaState["g_luaEngine"]["currentGameState"] + ["entityManager"]; + + if(currentManager == nullptr) + throw std::runtime_error("saveCreation got nullptr as current EntityManager"); + + saveCreation(entityId, *currentManager, name, type); } void @@ -808,7 +836,14 @@ EntityId Engine::loadCreation( std::string file ) { - return loadCreation(file, this->currentGameState()->entityManager()); + // Get current EntityManager + EntityManager* currentManager = m_impl->m_luaState["g_luaEngine"]["currentGameState"] + ["entityManager"]; + + if(currentManager == nullptr) + throw std::runtime_error("loadCreation got nullptr as current EntityManager"); + + return loadCreation(file, *currentManager); } EntityId @@ -860,21 +895,6 @@ Engine::getCreationFileList( return stringbuilder.str(); } -void -Engine::setCurrentGameState( - GameState* gameState -) { - assert(gameState != nullptr && "GameState must not be null"); - m_impl->m_nextGameState = gameState; - for (auto& pair : *m_impl->m_prevShutdownSystems){ - //Make sure systems are deactivated before any potential reactivations - pair.first->deactivate(); - } - m_impl->m_prevShutdownSystems = m_impl->m_nextShutdownSystems; - m_impl->m_nextShutdownSystems = m_impl->m_prevShutdownSystems; - m_impl->m_nextShutdownSystems->clear(); -} - PlayerData& Engine::playerData(){ return m_impl->m_playerData; @@ -882,10 +902,19 @@ Engine::playerData(){ void Engine::shutdown() { - for (const auto& pair : m_impl->m_gameStates) { - const auto& gameState = pair.second; - gameState->shutdown(); + + sol::protected_function luaShutdown = m_impl->m_luaState["g_luaEngine"]["shutdown"]; + + if(!luaShutdown(m_impl->m_luaState["g_luaEngine"]).valid()){ + + throw std::runtime_error("Failed to shutdown LuaEngine side"); } + + // This should release a bunch of objects // + // But apparently not enough. So Lua destructors need to check whether + // Ogre is still valid + m_impl->m_luaState.collect_garbage(); + m_impl->shutdownInputManager(); m_impl->m_graphics.renderWindow->destroy(); @@ -903,24 +932,6 @@ Engine::soundManager() const { return m_impl->m_soundManager.get(); } -EntityId -Engine::transferEntityGameState( - EntityId oldEntityId, - EntityManager* oldEntityManager, - GameState* newGameState -){ - EntityId newEntity; - const std::string* nameMapping = oldEntityManager->getNameMappingFor(oldEntityId); - if (nameMapping){ - newEntity = newGameState->entityManager().getNamedId(*nameMapping, true); - } - else{ - newEntity = newGameState->entityManager().generateNewId(); - } - oldEntityManager->transferEntity(oldEntityId, newEntity, newGameState->entityManager(), m_impl->m_componentFactory); - return newEntity; -} - void Engine::update( int milliseconds @@ -936,31 +947,9 @@ Engine::update( m_impl->m_input.keyboard.update(); m_impl->m_input.mouse.update(); - if (m_impl->m_nextGameState) { - m_impl->activateGameState(m_impl->m_nextGameState); - m_impl->m_nextGameState = nullptr; - } - assert(m_impl->m_currentGameState != nullptr); - m_impl->m_currentGameState->update(milliseconds, m_impl->m_paused ? 0 : milliseconds); - - luabind::call_member(m_impl->m_console, "update"); - CEGUI::System::getSingleton().injectTimePulse(milliseconds/1000.0f); CEGUI::System::getSingleton().getDefaultGUIContext().injectTimePulse(milliseconds/1000.0f); - // Update any timed shutdown systems - auto itr = m_impl->m_prevShutdownSystems->begin(); - while (itr != m_impl->m_prevShutdownSystems->end()) { - int updateTime = std::min(itr->second, milliseconds); - itr->first->update(updateTime, m_impl->m_paused ? 0 : updateTime); - itr->second = itr->second - updateTime; - if (itr->second == 0) { - // Remove systems that had timed out - itr->first->deactivate(); - m_impl->m_prevShutdownSystems->erase(itr++); - } else { - ++itr; - } - } + if (not m_impl->m_serialization.loadFile.empty()) { m_impl->loadSavegame(); } @@ -976,27 +965,8 @@ Engine::getResolutionHeight() const { return m_impl->m_graphics.renderWindow->getHeight(); } -void -Engine::timedSystemShutdown( - System& system, - int milliseconds -) { - (*m_impl->m_nextShutdownSystems)[&system] = milliseconds; -} - -bool -Engine::isSystemTimedShutdown( - System& system -) const { - return m_impl->m_prevShutdownSystems->find(&system) != m_impl->m_prevShutdownSystems->end(); -} - const std::string& Engine::thriveVersion() const { return m_impl->m_thriveVersion; } -void -Engine::registerConsoleObject(luabind::object consoleObject) { - m_impl->m_console = consoleObject; -} diff --git a/src/engine/engine.h b/src/engine/engine.h index fc6175864d7..d96b088fb51 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -7,13 +7,11 @@ #include #include -#include - class btDiscreteDynamicsWorld; class lua_State; -namespace luabind { - class scope; +namespace sol { +class state; } namespace Ogre { @@ -25,6 +23,7 @@ namespace Ogre { namespace thrive{ class SoundManager; + class Game; } namespace OIS { @@ -74,8 +73,6 @@ class Engine { * - Engine::quit() * - Engine::pauseGame() * - Engine::resumeGame() - * - Engine::timedSystemShutdown() - * - Engine::isSystemTimedShutdown() * - Engine::componentFactory() (as property) * - Engine::keyboard() (as property) * - Engine::mouse() (as property) @@ -84,8 +81,7 @@ class Engine { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -111,38 +107,6 @@ class Engine { ComponentFactory& componentFactory(); - /** - * @brief Creates a new game state - * - * @param name - * The game state's name - * - * @param systems - * The systems active in the game state - * - * @param initializer - * The initialization function for the game state - * - * @return - * The new game state. Will never be \c null. It is returned as a pointer - * as a convenience for Lua bindings, which don't handle references well. - */ - GameState* - createGameState( - std::string name, - std::vector> systems, - GameState::Initializer initializer, - std::string guiLayoutName - ); - - /** - * @brief Returns the currently active game state - * - * If no game state has been set yet, returns \c nullptr - * - */ - GameState* - currentGameState() const; /** * @brief Object holding generic player data @@ -157,20 +121,6 @@ class Engine { RNG& rng(); - /** - * @brief Retrieves a game state - * - * @param name - * The game state's name - * - * @return - * The game state with \a name or \c nullptr if no game state with - * this name exists. - */ - GameState* - getGameState( - const std::string& name - ) const; /** * @brief Initializes the engine @@ -182,6 +132,15 @@ class Engine { void init(); + /** + * @brief Enters the main loop in lua + */ + void + enterLuaMain( + Game* gameObj + ); + + /** * @brief The engine's input manager */ @@ -337,21 +296,6 @@ class Engine { std::string stage ) const; - /** - * @brief Sets the current game state - * - * The game state will be activated at the beginning of the next frame. - * - * \a gameState must not be \c null. It's passed by pointer as a - * convenience for the Lua bindings (which can't handle references well). - * - * @param gameState - * The new game state - */ - void - setCurrentGameState( - GameState* gameState - ); /** * @brief Shuts the engine down @@ -384,13 +328,7 @@ class Engine { soundManager() const; /** - * @brief Renders a single frame - * - * Before calling update() the first time, you need to call Engine::init(). - * - * @param milliseconds - * The number of milliseconds to advance. For real-time, this is the - * number of milliseconds since the last frame. + * @brief Updates C++ side things. Called from lua */ void update( @@ -413,68 +351,45 @@ class Engine { int getResolutionHeight() const; - /** - * @brief Keeps a system alive after being shut down for a specified amount of time - * - * Note that this causes update to be called for the specified duration so be careful - * to ensure that the system is not enabled or it will get update calls twice. - * - * @param system - * The system to keep updated - * - * @param milliseconds - * The number of milliseconds to keep the system updated for - */ - void - timedSystemShutdown( - System& system, - int milliseconds - ); + /** - * @brief Returns whether the specified system has already been set for a timed shutdown - * - * @param system - * The system to check for + * @name Lua wrapper methods * - * @return + * These are implemented in Lua. These methods make these functions + * available but they are slow. so avoid if possible. Or maybe + * rewrite the system that needs thse in Lua. */ - bool - isSystemTimedShutdown( - System& system - ) const; + /**@{*/ /** - * @brief Transfers an entity from one gamestate to another - * - * @param oldEntityId - * The id of the entity to transfer in the old entitymanager - * - * @param oldEntityManager - * The old entitymanager which is currently handling the entity - * - * @param newGameState - * The new gamestate to transfer the entity to + * @brief Calls the LuaEngine transfer entity method */ EntityId transferEntityGameState( - EntityId oldEntityId, - EntityManager* oldEntityManager, - GameState* newGameState + EntityId id, + EntityManager* entityManager, + GameStateData* targetState ); + + bool isSystemTimedShutdown(System* system); + + void timedSystemShutdown(System* system, int timeInMS); /** - * @brief The render window + * @brief Gets the current GameStateData or throws */ - Ogre::RenderWindow* - renderWindow() const; + GameStateData* + getCurrentGameStateFromLua(); + + /**@}*/ + /** - * @brief Registers the console object + * @brief The render window */ - void - registerConsoleObject(luabind::object consoleObject); - + Ogre::RenderWindow* + renderWindow() const; /** * @brief Gets the current version of thrive as a string. diff --git a/src/engine/entity.cpp b/src/engine/entity.cpp index 220dfd496de..78328a64c3c 100644 --- a/src/engine/entity.cpp +++ b/src/engine/entity.cpp @@ -3,11 +3,9 @@ #include "engine/engine.h" #include "engine/entity_manager.h" #include "engine/game_state.h" +#include "scripting/wrapper_classes.h" #include "game.h" -#include "scripting/luabind.h" - -#include -#include +#include "scripting/luajit.h" using namespace thrive; @@ -28,62 +26,113 @@ struct Entity::Implementation { }; - -static void -Entity_addComponent( - Entity* self, - Component* nakedComponent -) { - self->addComponent( - std::unique_ptr(nakedComponent) +void Entity::luaBindings( + sol::state &lua +){ + lua.new_usertype("Entity", + + sol::constructors, + sol::types, + sol::types>(), + + // This should be automatically bound but here we do it explicitly + sol::meta_function::equal_to, &Entity::operator==, + + // The first overload is for passing c++ types here. + "addComponent", sol::overload([](Entity &self, std::unique_ptr &component){ + + if(!component) + throw std::runtime_error("Entity:addComponent null C++ component"); + + // This can probably be bypassed + std::unique_ptr temp; + temp.swap(component); + + self.addComponent( + std::move(temp) + ); + + }, [](Entity &self, sol::table componentTable){ + + if(!componentTable.valid()) + throw std::runtime_error("Entity:addComponent invalid argument"); + + // This can be disabled to increase performance + if(componentTable.get_or("TYPE_NAME", "").empty()) + throw std::runtime_error("Lua Component class is missing TYPE_NAME"); + + self.addComponent( + std::make_unique(componentTable) + ); + }), + + "destroy", &Entity::destroy, + "exists", &Entity::exists, + + "getComponent", &Entity::getComponent, + + // Gets a component from an entity, creating the component if it's not present + // + // @param componentCls + // The class object of the component type + // + // Rest of the parameters are passed to the component constructor if a + // new component instance needs to be created + "getOrCreate", [](Entity &self, sol::table componentCls, + sol::variadic_args va) + { + Component* component = self.getComponent(componentCls["TYPE_ID"]); + + if(component) + return component; + + auto factory = componentCls.get("new"); + + auto result = factory(va); + + if(!result.valid()) + throw std::runtime_error("Entity getOrCreate failed to call " + "Lua component 'new' method:" + result.get()); + + auto newComponent = std::make_unique( + result.get() + ); + + + component = newComponent.get(); + self.addComponent(std::move(newComponent)); + + return component; + }, + + "isVolatile", &Entity::isVolatile, + "removeComponent", &Entity::removeComponent, + // prefer to call LuaEngine:transferEntityGameState. This is slow + //"transfer", &Entity::transfer, + "setVolatile", &Entity::setVolatile, + "stealName", &Entity::stealName, + "addChild", &Entity::addChild, + "hasChildren", &Entity::hasChildren, + "id", sol::property(&Entity::id) + ); } - -luabind::scope -Entity::luaBindings() { - using namespace luabind; - return class_("Entity") - .def(constructor<>()) - .def(constructor()) - .def(constructor()) - .def(constructor()) - .def(constructor()) - .def(constructor()) - - .def(const_self == other()) - .def("addComponent", &Entity_addComponent, adopt(_2)) - .def("destroy", &Entity::destroy) - .def("exists", &Entity::exists) - .def("getComponent", &Entity::getComponent) - .def("isVolatile", &Entity::isVolatile) - .def("removeComponent", &Entity::removeComponent) - .def("transfer", &Entity::transfer) - .def("setVolatile", &Entity::setVolatile) - .def("stealName", &Entity::stealName) - .def("addChild", &Entity::addChild) - .def("hasChildren", &Entity::hasChildren) - .property("id", &Entity::id) - ; -} - - -static EntityManager& +static EntityManager* getEntityManager( - GameState* gameState + GameStateData* gameState ) { - if (gameState) { - return gameState->entityManager(); - } - else { - return Game::instance().engine().currentGameState()->entityManager(); - } + if(gameState == nullptr) + throw std::runtime_error("Entity constructor: getEntityManager can't get " + "manager from null gameState"); + + return gameState->entityManager(); } Entity::Entity( - GameState* gameState -) : Entity(getEntityManager(gameState).generateNewId(), gameState) + GameStateData* gameState +) : Entity(getEntityManager(gameState)->generateNewId(), gameState) { } @@ -91,16 +140,16 @@ Entity::Entity( Entity::Entity( EntityId id, - GameState* gameState -) : m_impl(new Implementation(id, &getEntityManager(gameState))) + GameStateData* gameState +) : m_impl(new Implementation(id, getEntityManager(gameState))) { } Entity::Entity( const std::string& name, - GameState* gameState -) : Entity(getEntityManager(gameState).getNamedId(name), gameState) + GameStateData* gameState +) : Entity(getEntityManager(gameState)->getNamedId(name), gameState) { } @@ -208,9 +257,13 @@ Entity::removeComponent( Entity Entity::transfer( - GameState* newGameState + GameStateData* newGameStateData ) { - return Entity(Game::instance().engine().transferEntityGameState(m_impl->m_id, m_impl->m_entityManager, newGameState), newGameState); + + EntityId newID = Game::instance().engine().transferEntityGameState(m_impl->m_id, + m_impl->m_entityManager, newGameStateData); + + return Entity(newID, newGameStateData); } void diff --git a/src/engine/entity.h b/src/engine/entity.h index 3bc580cfc3c..a1f56f5febd 100644 --- a/src/engine/entity.h +++ b/src/engine/entity.h @@ -5,13 +5,14 @@ #include #include -namespace luabind { -class scope; + +namespace sol { +class state; } namespace thrive { -class GameState; +class GameStateData; class EntityManager; /** @@ -33,13 +34,14 @@ class Entity { * @brief Lua bindings * * Exposes the following \b constructors: - * - \c Entity(): Entity() - * - \c Entity(number): Entity(EntityId) - * - \c Entity(string): Entity(const std::string&) + * - \c Entity(GameStateData) + * - \c Entity(EntityId, GameStateData) + * - \c Entity(string, GameStateData) * * Exposes the following \b functions: * - \c addComponent(Component): addComponent(std::unique_ptr) * - \c getComponent(number): getComponent(ComponentTypeId) + * - \c getOrCreate(number): getOrCreate(ComponentTypeId, ...) Args for new component * - \c removeComponent(number): removeComponent(ComponentTypeId) * - \c transfer(gameState) : transfer(gameState) * - \c setVolatile(bool) : setVolatile(bool) @@ -50,8 +52,7 @@ class Entity { * Exposes the following \b operators: * - \c ==: operator==(const Entity&) */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -59,12 +60,11 @@ class Entity { * Creates a new unnamed entity * * @param gameState - * The game state the new entity belongs to. If \c null, the current game - * state of the global engine object is used. + * The game state the new entity belongs to. If \c null, throws an error * */ Entity( - GameState* gameState = nullptr + GameStateData* gameState ); /** @@ -76,13 +76,12 @@ class Entity { * The entity id to interface to * * @param gameState - * The game state the entity belongs to. If \c null, the current game - * state of the global engine object is used. + * The game state the entity belongs to. If \c null, throws an error * */ Entity( EntityId id, - GameState* gameState = nullptr + GameStateData* gameState ); /** @@ -96,13 +95,12 @@ class Entity { * The name of the entity to interface to * * @param gameState - * The game state the entity belongs to. If \c null, the current game - * state of the global engine object is used. + * The game state the entity belongs to. If \c null, throws an error * */ Entity( const std::string& name, - GameState* gameState = nullptr + GameStateData* gameState ); /** @@ -284,10 +282,15 @@ class Entity { * @return * The new entity in the new gamestate. * Note that the actual transfer will take place before next update so the old entity is valid until then. + * @note + * This makes a call to lua and is pretty slow so prefer directly calling + * LuaEngine:transferEntityGameState in lua code + * @todo + * remove this if this is no longer used */ Entity transfer( - GameState* newGameState + GameStateData* newGameState ); /** diff --git a/src/engine/entity_manager.cpp b/src/engine/entity_manager.cpp index c39ad53831b..af005f9ce74 100644 --- a/src/engine/entity_manager.cpp +++ b/src/engine/entity_manager.cpp @@ -14,6 +14,37 @@ using namespace thrive; + +void +EntityManager::luaBindings(sol::state &lua){ + + lua.new_usertype("EntityManager", + + sol::constructors>(), + + "processRemovals", &EntityManager::processRemovals, + "getNameMappingFor", &EntityManager::getNameMappingFor, + + "getNamedId", sol::overload( + [](EntityManager &self, const std::string* name, bool force){ + if(!name) + throw std::runtime_error("name is null"); + return self.getNamedId(*name, force); + + }, [](EntityManager &self, const std::string &name, bool force){ + + return self.getNamedId(name, force); + }), + + "storage", &EntityManager::storage, + "restore", &EntityManager::restore, + "clear", &EntityManager::clear, + + "generateNewId", &EntityManager::generateNewId, + "transferEntity", &EntityManager::transferEntity + ); +} + struct EntityManager::Implementation { ComponentCollection& diff --git a/src/engine/entity_manager.h b/src/engine/entity_manager.h index 85437a70c7e..4647887ecf0 100644 --- a/src/engine/entity_manager.h +++ b/src/engine/entity_manager.h @@ -6,12 +6,16 @@ #include #include +namespace sol{ +class state; +} + namespace thrive { class Component; class ComponentCollection; class ComponentFactory; -class GameState; +class GameStateData; class StorageContainer; /** @@ -24,6 +28,18 @@ class EntityManager { public: + + /** + * @brief Lua bindings + * + * Exposes: + * - EntityManager::new + * + * @return + */ + static void + luaBindings(sol::state &lua); + /** * @brief Constructor */ diff --git a/src/engine/game_state.cpp b/src/engine/game_state.cpp index b1d763eb108..6dc5ec34000 100644 --- a/src/engine/game_state.cpp +++ b/src/engine/game_state.cpp @@ -1,275 +1,119 @@ #include "engine/game_state.h" -#include - #include "engine/engine.h" -#include "engine/entity_manager.h" -#include "engine/serialization.h" -#include "engine/system.h" - -#include "gui/CEGUIWindow.h" +#include "scripting/script_helpers.h" #include #include using namespace thrive; -struct GameState::Implementation { - - Implementation( - Engine& engine, - std::string name, - std::vector> systems, - Initializer initializer, - std::string guiLayoutName - ) : m_engine(engine), - m_initializer(initializer), - m_name(name), - m_systems(std::move(systems)), - m_guiLayoutName(guiLayoutName), - m_guiWindow(nullptr) - { - } - - void - setupPhysics() { - m_physics.collisionConfiguration.reset(new btDefaultCollisionConfiguration()); - m_physics.dispatcher.reset(new btCollisionDispatcher( - m_physics.collisionConfiguration.get() - )); - m_physics.broadphase.reset(new btDbvtBroadphase()); - m_physics.solver.reset(new btSequentialImpulseConstraintSolver()); - m_physics.world.reset(new btDiscreteDynamicsWorld( - m_physics.dispatcher.get(), - m_physics.broadphase.get(), - m_physics.solver.get(), - m_physics.collisionConfiguration.get() - )); - m_physics.world->setGravity(btVector3(0,0,0)); - } - - void - setupSceneManager() { - // TODO: configure the number of worker threads, currently always 2 - m_sceneManager = m_engine.ogreRoot()->createSceneManager( - Ogre::ST_GENERIC, 2, Ogre::INSTANCING_CULLING_THREADED, - m_name - ); - - m_sceneManager->setAmbientLight( - Ogre::ColourValue(0.5, 0.5, 0.5) - ); - } - - Engine& m_engine; - - EntityManager m_entityManager; - - Initializer m_initializer; - - std::string m_name; - - Ogre::SceneManager* m_sceneManager = nullptr; - - struct Physics { - std::unique_ptr broadphase; +void GameStateData::luaBindings(sol::state &lua){ - std::unique_ptr collisionConfiguration; + lua.new_usertype("GameStateData", - std::unique_ptr dispatcher; - - std::unique_ptr solver; - - std::unique_ptr world; - - } m_physics; - - std::vector> m_systems; - - std::string m_guiLayoutName; - - CEGUIWindow m_guiWindow; - -}; - - -luabind::scope -GameState::luaBindings() { - using namespace luabind; - return class_("GameState") - .def("name", &GameState::name) - .def("rootGUIWindow", &GameState::rootGUIWindow) - .def("entityManager", static_cast(&GameState::entityManager)) - ; + sol::constructors>(), + + "luaEngine", &GameStateData::m_engine, + "name", sol::property(&GameStateData::name) + ); } - -GameState::GameState( - Engine& engine, - std::string name, - std::vector> systems, - Initializer initializer, - std::string guiLayoutName -) : m_impl(new Implementation(engine, name, std::move(systems), initializer, guiLayoutName)) +GameStateData::GameStateData( + sol::table stateObj, + Engine* engine, + EntityManager* entityManager, + PhysicalWorld* physics +) : + m_engine(engine), + m_entityManager(entityManager), + m_physicalWorld(physics), + m_luaSide(stateObj) { -} + // TODO: configure the number of worker threads, currently always 2 + m_sceneManager = Ogre::Root::getSingleton().createSceneManager( + Ogre::ST_GENERIC, 2, Ogre::INSTANCING_CULLING_THREADED, + name() + ); + // And allow this to be configured, too + m_sceneManager->setAmbientLight( + Ogre::ColourValue(0.5, 0.5, 0.5) + ); +} -GameState::~GameState() {} +GameStateData::~GameStateData(){ + // Destroy scene manager + Ogre::Root* root = Ogre::Root::getSingletonPtr(); -void -GameState::activate() { - m_impl->m_guiWindow.show(); - CEGUIWindow::getRootWindow().addChild(&m_impl->m_guiWindow); - for (const auto& system : m_impl->m_systems) { - system->activate(); + // This object might be destroyed when the Lua state is destroyed so it is not safe + // to just assume that root is valid + if(root){ + + root->destroySceneManager( + m_sceneManager + ); } -} - -void -GameState::deactivate() { - for (const auto& system : m_impl->m_systems) { - system->deactivate(); - } - m_impl->m_guiWindow.hide(); - CEGUIWindow::getRootWindow().removeChild(&m_impl->m_guiWindow); + m_sceneManager = nullptr; } +// ------------------------------------ // -Engine& -GameState::engine() { - return m_impl->m_engine; -} - +Engine* +GameStateData::engine(){ -const Engine& -GameState::engine() const { - return m_impl->m_engine; + return m_engine; } +EntityManager* +GameStateData::entityManager(){ -EntityManager& -GameState::entityManager() { - return m_impl->m_entityManager; + return m_entityManager; } -void -GameState::init() { - m_impl->m_guiWindow = CEGUIWindow(m_impl->m_guiLayoutName); - m_impl->setupPhysics(); - m_impl->setupSceneManager(); - for (const auto& system : m_impl->m_systems) { - system->init(this); - } - m_impl->m_initializer(); -} +PhysicalWorld* +GameStateData::physicalWorld(){ -const std::vector>& -GameState::systems() const { - return m_impl->m_systems; + return m_physicalWorld; } -void -GameState::load( - const StorageContainer& storage -) { - StorageContainer entities = storage.get("entities"); - m_impl->m_entityManager.clear(); - try { - m_impl->m_entityManager.restore( - entities, - m_impl->m_engine.componentFactory() - ); - } - catch (const luabind::error& e) { - luabind::object error_msg(luabind::from_stack( - e.state(), - -1 - )); - // TODO: Log error - std::cerr << error_msg << std::endl; - throw; - } -} +Ogre::SceneManager* +GameStateData::sceneManager() const{ -std::string -GameState::name() const { - return m_impl->m_name; + return m_sceneManager; } -btDiscreteDynamicsWorld* -GameState::physicsWorld() const { - return m_impl->m_physics.world.get(); -} - -CEGUIWindow -GameState::rootGUIWindow(){ - return m_impl->m_guiWindow; -} +std::vector +GameStateData::getCppSystems(){ + auto result = m_luaSide.get("getCppSystems")(m_luaSide); + if(!result.valid()) + throw std::runtime_error("GameStateData::getCppSystems failed to " + "call lua side"); + sol::table systems = result.get(); -Ogre::SceneManager* -GameState::sceneManager() const { - return m_impl->m_sceneManager; + return createVectorFromLuaTable(systems); } +std::string +GameStateData::name() const{ -void -GameState::shutdown() { - for (const auto& system : m_impl->m_systems) { - system->shutdown(); - } - m_impl->m_physics.world.reset(); - m_impl->m_engine.ogreRoot()->destroySceneManager( - m_impl->m_sceneManager - ); + return m_luaSide.get("name"); } -StorageContainer -GameState::storage() const { - StorageContainer storage; - StorageContainer entities; - try { - entities = m_impl->m_entityManager.storage( - m_impl->m_engine.componentFactory() - ); - } - catch (const luabind::error& e) { - luabind::object error_msg(luabind::from_stack( - e.state(), - -1 - )); - // TODO: Log error - std::cerr << error_msg << std::endl; - throw; - } - storage.set("entities", std::move(entities)); - return storage; -} -void -GameState::update( - int renderTime, - int logicTime -) { - for(auto& system : m_impl->m_systems) { - if (system->enabled()) { - //Uncomment to debug mystical crashes and other anomalies - //std::cout << "Updating system " << system->getName() << std::endl; - system->update(renderTime, logicTime); - //std::cout << "Done updating system " << system->getName() << std::endl; - } - } - m_impl->m_entityManager.processRemovals(); -} + + + diff --git a/src/engine/game_state.h b/src/engine/game_state.h index adfc43966b9..fa8dec57b64 100644 --- a/src/engine/game_state.h +++ b/src/engine/game_state.h @@ -1,133 +1,66 @@ #pragma once #include -#include -#include -class btDiscreteDynamicsWorld; +#include "scripting/luajit.h" -namespace luabind { - class scope; + +namespace sol { +class state; } namespace Ogre { - class SceneManager; +class SceneManager; } namespace thrive { -class CEGUIWindow; class Engine; class EntityManager; -class StorageContainer; class System; +class PhysicalWorld; + /** -* @brief Represents a distinct set of active systems and entities -* -* The game has to switch between different states. Examples of a state are -* "main menu", "microbe gameplay" or "microbe editor". These states usually -* share very few entities and even fewer systems, so it is sensible to -* separate them completely (and, if necessary, share data over other channels). +* @brief Wrapper that allows C++ systems to access state data owned by +* Lua also owns the states Ogre::SceneManager because that was easier +* to setup in C++ than in lua * -* Each GameState has its own EntityManager and its own set of systems. Game -* states are identified by their name, a unique string. -* -* GameStates cannot be created directly. Use Engine::createGameState to create -* new GameStates. +* @note Some of these methods might be really slow so avoid if possible. +* Or maybe rewrite the system in Lua. */ - - -class GameState { - +class GameStateData { public: - /** - * @brief Typedef for the game state's initializer function - */ - using Initializer = std::function; - /** * @brief Lua bindings * * Exposes: - * - GameState::name() - * - GameState::rootGUIWindow() - * - GameState::entityManager() // NOTE: Entitymanager class may not be exposed to luabind + * - GameStateData * * @return */ - static luabind::scope - luaBindings(); + static void + luaBindings(sol::state &lua); - /** - * @brief Not copyable - * - */ - GameState(const GameState&) = delete; - /** - * @brief Destructor - */ - ~GameState(); + GameStateData( + sol::table stateObj, + Engine* engine, + EntityManager* entityManager, + PhysicalWorld* physics + ); - /** - * @brief Not copyable - * - */ - GameState& operator=(const GameState&) = delete; + ~GameStateData(); - /** - * @brief Returns the engine this game state belongs to - * - * @return - */ - Engine& + Engine* engine(); - /** - * @brief Returns the engine this game state belongs to - * - * @return - */ - const Engine& - engine() const; - - /** - * @brief Returns the game state's entity manager - * - * @return - */ - EntityManager& + EntityManager* entityManager(); - /** - * @brief Returns the game state's entity manager - * - * @return - */ - const EntityManager& - entityManager() const; - - /** - * @brief The game state's name - * - * @return - */ - std::string - name() const; - - /** - * @brief The physics world - */ - btDiscreteDynamicsWorld* - physicsWorld() const; - - /** - * @brief The root CEGUIWindow - */ - CEGUIWindow - rootGUIWindow(); + PhysicalWorld* + physicalWorld(); /** * @brief The Ogre scene manager @@ -135,11 +68,14 @@ class GameState { Ogre::SceneManager* sceneManager() const; + /** + * @brief Finds a C++ based system matching type S + */ template - S* - findSystem() { - for (const auto& system : this->systems()) { - S* foundSystem = dynamic_cast(system.get()); + S* findSystem(){ + + for (const auto& system : this->getCppSystems()) { + S* foundSystem = dynamic_cast(system); if (foundSystem) { return foundSystem; } @@ -147,108 +83,28 @@ class GameState { return nullptr; } -private: - - friend class Engine; - - /** - * @brief Constructor - * - * Use Engine::addGameState to create new game states - * - * @param engine - * The engine this game state belongs to - * - * @param name - * The game state's name, a unique identifier - * - * @param systems - * The game state's systems. The game state takes ownership of them. - * - * @param initializer - * A function that is called after initializing the game - * state. You can set up basic entities in this callback. - */ - GameState( - Engine& engine, - std::string name, - std::vector> systems, - Initializer initializer, - std::string guiLayoutName - ); - - /** - * @brief Called by the engine when the game state is activated - */ - void - activate(); - - /** - * @brief Called by the engine when the game state is deactivated - */ - void - deactivate(); - - /** - * @brief Called by the engine to initialize the game state - * - * Initializes all the systems in turn - */ - void - init(); - - const std::vector>& - systems() const; - /** - * @brief Called by the engine during loading of a savegame - * - * @param storage + * @brief retrieves C++ systems from the lua state * - * @see GameState::storage() + * This is pretty slow so avoid if possible */ - void - load( - const StorageContainer& storage - ); + std::vector + getCppSystems(); - /** - * @brief Called by the engine to shut the game state down - * - * Shuts down all the systems in turn + /* + * @brief Returns the name of this game state */ - void - shutdown(); - - /** - * @brief Called by the engine during savegame creation - * - * @return - * - * @see GameState::load() - */ - StorageContainer - storage() const; - - /** - * @brief Called by the engine to update the game state - * - * Updates all the systems in turn - * - * @param milliseconds - * The number of milliseconds of game time elapsed since the - * last frame (which may have been rendered by another game state). - */ - void - update( - int renderTime, - int logicTime - ); + std::string + name() const; - struct Implementation; - std::unique_ptr m_impl; +private: + Engine* m_engine; + EntityManager* m_entityManager; + PhysicalWorld* m_physicalWorld; + Ogre::SceneManager* m_sceneManager = nullptr; + sol::table m_luaSide; }; } diff --git a/src/engine/player_data.cpp b/src/engine/player_data.cpp index c89cb500d51..753552f1bcb 100644 --- a/src/engine/player_data.cpp +++ b/src/engine/player_data.cpp @@ -3,7 +3,7 @@ #include "engine/game_state.h" #include "engine/serialization.h" #include "general/locked_map.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include "engine/entity.h" #include @@ -19,7 +19,7 @@ struct PlayerData::Implementation { } EntityId m_activeCreature = NULL_ENTITY; - GameState* m_activeCreatureGamestate = nullptr; + GameStateData* m_activeCreatureGamestate = nullptr; std::string m_playerName; @@ -29,19 +29,21 @@ struct PlayerData::Implementation { }; -luabind::scope -PlayerData::luaBindings() { - using namespace luabind; - return class_("PlayerData") - .def(constructor()) - .def("playerName", &PlayerData::playerName) - .def("lockedMap", &PlayerData::lockedMap) - .def("activeCreature", &PlayerData::activeCreature) - .def("setActiveCreature", &PlayerData::setActiveCreature) - .def("activeCreatureGamestate", &PlayerData::activeCreatureGamestate) - .def("isBoolSet", &PlayerData::isBoolSet) - .def("setBool", &PlayerData::setBool) - ; +void PlayerData::luaBindings( + sol::state &lua +){ + lua.new_usertype("PlayerData", + + sol::constructors>(), + + "playerName", &PlayerData::playerName, + "lockedMap", &PlayerData::lockedMap, + "activeCreature", &PlayerData::activeCreature, + "setActiveCreature", &PlayerData::setActiveCreature, + "activeCreatureGamestate", &PlayerData::activeCreatureGamestate, + "isBoolSet", &PlayerData::isBoolSet, + "setBool", &PlayerData::setBool + ); } PlayerData::PlayerData( @@ -70,15 +72,15 @@ PlayerData::activeCreature(){ void PlayerData::setActiveCreature( EntityId creatureId, - GameState& gamestate + GameStateData* gamestate ){ m_impl->m_activeCreature = creatureId; - m_impl->m_activeCreatureGamestate = &gamestate; + m_impl->m_activeCreatureGamestate = gamestate; } -GameState& +GameStateData* PlayerData::activeCreatureGamestate(){ - return *m_impl->m_activeCreatureGamestate; + return m_impl->m_activeCreatureGamestate; } bool @@ -105,10 +107,16 @@ void PlayerData::load( const StorageContainer& storage ) { + + if(!m_impl->m_activeCreatureGamestate) + throw std::runtime_error("PlayerData.activeCreatureGamestate is null in 'load'"); + + m_impl->m_playerName = storage.get("playerName"); StorageContainer lockedMapStorage = storage.get("lockedMap"); //This isn't the prettiest way to do it, but we need to reobtain a reference to the players creature - m_impl->m_activeCreature = Entity(m_impl->m_playerName).id(); + m_impl->m_activeCreature = Entity(m_impl->m_playerName, + m_impl->m_activeCreatureGamestate).id(); StorageList boolValues = storage.get("boolValues"); for (const StorageContainer& container : boolValues) { std::string boolKey = container.get("boolKey"); diff --git a/src/engine/player_data.h b/src/engine/player_data.h index 20330835e09..797642891a8 100644 --- a/src/engine/player_data.h +++ b/src/engine/player_data.h @@ -5,13 +5,13 @@ #include #include -namespace luabind { - class scope; +namespace sol { +class state; } namespace thrive { -class GameState; +class GameStateData; class StorageContainer; class LockedMap; @@ -48,8 +48,7 @@ class PlayerData { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Getter for the players name @@ -87,7 +86,7 @@ class PlayerData { void setActiveCreature( EntityId creatureId, - GameState& gamestate + GameStateData* gamestate ); /** @@ -95,7 +94,7 @@ class PlayerData { * * @return */ - GameState& + GameStateData* activeCreatureGamestate(); /** diff --git a/src/engine/rng.cpp b/src/engine/rng.cpp index 176acea7c2c..9ba642b777b 100644 --- a/src/engine/rng.cpp +++ b/src/engine/rng.cpp @@ -1,6 +1,6 @@ #include "rng.h" #include "chrono" -#include "scripting/luabind.h" +#include "scripting/luajit.h" using namespace thrive; @@ -25,17 +25,17 @@ struct RNG::Implementation { std::mt19937 m_mt; }; - -luabind::scope -RNG::luaBindings(){ - using namespace luabind; - return class_("RNG") - .def("getInt", &RNG::getInt) - .def("getReal", &RNG::getDouble) - .def("generateRandomSeed", &RNG::generateRandomSeed) - .def("setSeed", &RNG::setSeed) - .def("getSeed", &RNG::getSeed) - ; +void RNG::luaBindings( + sol::state &lua +){ + lua.new_usertype("RNG", + + "getInt", &RNG::getInt, + "getReal", &RNG::getDouble, + "generateRandomSeed", &RNG::generateRandomSeed, + "setSeed", &RNG::setSeed, + "getSeed", &RNG::getSeed + ); } RNG::RNG() diff --git a/src/engine/rng.h b/src/engine/rng.h index 3b1725bf7e1..a6a436b8cf1 100644 --- a/src/engine/rng.h +++ b/src/engine/rng.h @@ -5,8 +5,8 @@ #include -namespace luabind { -class scope; +namespace sol { +class state; } namespace thrive { @@ -36,8 +36,7 @@ class RNG final { * - RNG::setSeed(seed) * - RNG::getSeed() */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor using proper random seed diff --git a/src/engine/rolling_grid.cpp b/src/engine/rolling_grid.cpp index ff4f9d34418..08f7749a8d3 100644 --- a/src/engine/rolling_grid.cpp +++ b/src/engine/rolling_grid.cpp @@ -3,7 +3,7 @@ #include #include "engine/rolling_grid.h" #include -#include "scripting/luabind.h" +#include "scripting/luajit.h" using namespace thrive; @@ -159,16 +159,16 @@ struct RollingGrid::Implementation { } }; +void RollingGrid::luaBindings( + sol::state &lua +){ + lua.new_usertype("RollingGrid", -luabind::scope -RollingGrid::luaBindings() { - using namespace luabind; - return class_("RollingGrid") - .def(constructor()) - .def("move", &RollingGrid::move) - .def("get", &RollingGrid::get) - .def("set", &RollingGrid::set) - ; + sol::constructors>(), + "move", &RollingGrid::move, + "get", &RollingGrid::get, + "set", &RollingGrid::set + ); } RollingGrid::RollingGrid(int width, int height, int resolution) diff --git a/src/engine/rolling_grid.h b/src/engine/rolling_grid.h index c8f053ae403..5c7b18077fa 100644 --- a/src/engine/rolling_grid.h +++ b/src/engine/rolling_grid.h @@ -5,8 +5,8 @@ // Defines a basic grid that fits the criteria set on issue 165 -namespace luabind { - class scope; +namespace sol { +class state; } namespace thrive { @@ -43,8 +43,7 @@ class RollingGrid { * - RollingGrid::set(long, long, int) * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); // TODO probably not the best move function /** diff --git a/src/engine/script_bindings.cpp b/src/engine/script_bindings.cpp deleted file mode 100644 index 31ef1b65798..00000000000 --- a/src/engine/script_bindings.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "engine/script_bindings.h" - -#include "engine/component.h" -#include "engine/component_factory.h" -#include "engine/engine.h" -#include "engine/entity.h" -#include "engine/game_state.h" -#include "engine/serialization.h" -#include "engine/system.h" -#include "engine/touchable.h" -#include "engine/player_data.h" -#include "engine/rng.h" -#include "scripting/luabind.h" - - -luabind::scope -thrive::EngineBindings::luaBindings() { - return ( - StorageContainer::luaBindings(), - StorageList::luaBindings(), - System::luaBindings(), - Component::luaBindings(), - ComponentFactory::luaBindings(), - Entity::luaBindings(), - Touchable::luaBindings(), - GameState::luaBindings(), - Engine::luaBindings(), - RNG::luaBindings(), - PlayerData::luaBindings() - ); -} diff --git a/src/engine/script_bindings.h b/src/engine/script_bindings.h deleted file mode 100644 index 55c0cf57591..00000000000 --- a/src/engine/script_bindings.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -namespace luabind { -class scope; -} - -namespace thrive { - -/** -* @brief Helper for Engine script bindings -*/ -struct EngineBindings { - - /** - * @brief Bindings for basic Engine classes - * - * @return - */ - static luabind::scope - luaBindings(); - -}; - -} diff --git a/src/engine/serialization.cpp b/src/engine/serialization.cpp index cb852d46aa0..6d5a27a1ed5 100644 --- a/src/engine/serialization.cpp +++ b/src/engine/serialization.cpp @@ -1,11 +1,8 @@ #include "engine/serialization.h" -#include "scripting/luabind.h" - #include #include #include -#include #include #include @@ -145,18 +142,18 @@ TYPE_INFO(Ogre::Quaternion, StorageContainer, 320) TYPE_INFO(Ogre::ColourValue, uint32_t, 336) } // namespace -#define TO_LUA_CASE(typeName) \ - case TypeInfo::Id: \ - { \ - using Info = TypeInfo; \ - auto storedValue = boost::get(value.value); \ - auto value = Info::convertFromStoredType(storedValue); \ - return luabind::object(L, value); \ - } +#define TO_LUA_CASE(typeName) \ +case TypeInfo::Id: \ +{ \ + using Info = TypeInfo; \ + auto storedValue = boost::get(value.value); \ + auto value = Info::convertFromStoredType(storedValue); \ + return sol::make_object(lua, value); \ +} -static luabind::object +static sol::object toLua( - lua_State* L, + sol::state_view &lua, const StoredValue& value ) { switch(value.typeId) { @@ -182,7 +179,7 @@ toLua( TO_LUA_CASE(Ogre::Quaternion); TO_LUA_CASE(Ogre::ColourValue); default: - return luabind::object(); + return sol::nil; } } @@ -289,29 +286,48 @@ GET_SET_CONTAINS(Ogre::Vector3) GET_SET_CONTAINS(Ogre::Quaternion) GET_SET_CONTAINS(Ogre::ColourValue) -luabind::scope -StorageContainer::luaBindings() { - using namespace luabind; - return - class_("StorageContainer") - .def(constructor<>()) - .def("contains", static_cast(&StorageContainer::contains)) - .def("get", &StorageContainer::luaGet) - .def("set", &StorageContainer::set) - .def("set", &StorageContainer::set) - .def("set", &StorageContainer::set) - .def("set", &StorageContainer::set) - .def("set", &StorageContainer::set) + +void StorageContainer::luaBindings( + sol::state &lua +){ + lua.new_usertype("StorageContainer", + + sol::constructors>(), + + "get", sol::overload([](StorageContainer &self, const std::string &key, + sol::this_state s) + { + return self.luaGet(key, sol::nil, s); + + }, &StorageContainer::luaGet), + + "contains", static_cast( + (&StorageContainer::contains)), + + // Overridden set method // + + "set", sol::overload( + &StorageContainer::set, + &StorageContainer::set, + &StorageContainer::set, + &StorageContainer::set, + &StorageContainer::set, // Compound types - .def("set", &StorageContainer::set) - .def("set", &StorageContainer::set) - .def("set", &StorageContainer::set) - .def("set", &StorageContainer::set) - .def("set", &StorageContainer::set) - ; + &StorageContainer::set, + &StorageContainer::set, + &StorageContainer::set, + &StorageContainer::set, + &StorageContainer::set + // Extra wrappers + // ,[](StorageContainer &self, const std::string &key, const StorageContainer &value){ + + // self.set(key, value); + // } + ) + ); } - StorageContainer::StorageContainer() : m_impl(new Implementation()) { @@ -365,18 +381,20 @@ StorageContainer::contains( } -luabind::object +sol::object StorageContainer::luaGet( const std::string& key, - luabind::object defaultValue + sol::object defaultValue, + sol::this_state s ) const { auto iter = m_impl->m_content.find(key); if (iter == m_impl->m_content.end()) { return defaultValue; } else { - luabind::object obj = toLua(defaultValue.interpreter(), iter->second); - if (obj) { + sol::state_view lua(s); + sol::object obj = toLua(lua, iter->second); + if (obj.valid()) { return obj; } else { @@ -563,15 +581,18 @@ TypeInfo::convertToStoredType( // StorageList //////////////////////////////////////////////////////////////////////////////// -luabind::scope -StorageList::luaBindings() { - using namespace luabind; - return class_("StorageList") - .def(constructor<>()) - .def("append", &StorageList::append) - .def("get", &StorageList::get) - .def("size", &StorageList::size) - ; +void StorageList::luaBindings( + sol::state &lua +){ + + lua.new_usertype("StorageList", + + sol::constructors>(), + + "append", &StorageList::append, + "get", &StorageList::get, + "size", &StorageList::size + ); } diff --git a/src/engine/serialization.h b/src/engine/serialization.h index e47e36c82f2..f4496c59741 100644 --- a/src/engine/serialization.h +++ b/src/engine/serialization.h @@ -1,6 +1,6 @@ #pragma once -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include #include @@ -45,8 +45,7 @@ class StorageContainer { * - StorageContainer::set * */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -98,6 +97,25 @@ class StorageContainer { StorageContainer&& other ); + /** + * @brief Required for lua bindings + */ + bool operator ==( + const StorageContainer &other + ) const { + return this == &other; + } + + /** + * @brief Required for lua bindings + */ + bool operator <( + const StorageContainer &other + ) const { + (void)other; + return false; + } + /** * @brief Checks for a key * @@ -166,10 +184,10 @@ class StorageContainer { * * @return */ - luabind::object - luaGet( + sol::object luaGet( const std::string& key, - luabind::object defaultValue + sol::object defaultValue, + sol::this_state s ) const; /** @@ -254,8 +272,7 @@ class StorageList : public std::vector { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor diff --git a/src/engine/system.cpp b/src/engine/system.cpp index 2cecd1146c0..bf005e06321 100644 --- a/src/engine/system.cpp +++ b/src/engine/system.cpp @@ -2,127 +2,40 @@ #include "engine/engine.h" #include "engine/game_state.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include using namespace thrive; - -/** -* @brief Wrapper class to enable subclassing System in Lua -* -* \cond -*/ -struct SystemWrapper : System, luabind::wrap_base { - - void - init( - GameState* gameState - ) override { - this->call("init", gameState); - } - - void - initNamed( - std::string name, - GameState* gameState - ) override { - this->call("initNamed", name, gameState); - } - - static void default_init( - System* self, - GameState* gameState - ) { - self->System::init(gameState); - } - - static void default_initNamed( - System* self, - std::string name, - GameState* gameState - ) { - self->System::initNamed(name, gameState); - } - - void - shutdown() override { - this->call("shutdown"); - } - - static void default_shutdown( - System* self - ) { - self->System::shutdown(); - } - - static void default_activate( - System* self - ) { - self->System::activate(); - } - - void - activate() override { - this->call("activate"); - } - - static void default_deactivate( - System* self - ) { - self->System::deactivate(); - } - - void - deactivate() override { - this->call("deactivate"); - } - - void - update( - int renderTime, - int logicTime - ) override { - this->call("update", renderTime, logicTime); - } - - static void default_update( - System*, - int, - int - ) { - throw std::runtime_error("System::update has no default implementation"); - } - -}; - -/** -* \endcond -*/ - - -luabind::scope -System::luaBindings() { - using namespace luabind; - return class_("System") - .def(constructor<>()) - .def("enabled", &System::enabled) - .def("init", &System::initNamed, &SystemWrapper::default_initNamed) - .def("setEnabled", &System::setEnabled) - .def("activate", &System::activate, &SystemWrapper::default_activate) - .def("deactivate", &System::deactivate, &SystemWrapper::default_deactivate) - .def("shutdown", &System::shutdown, &SystemWrapper::default_shutdown) - .def("update", &System::update, &SystemWrapper::default_update) - ; +void System::luaBindings( + sol::state &lua +){ + lua.new_usertype("System", + + // We are an abstract class + "new", sol::no_constructor, + + "enabled", &System::enabled, + // This doesn't need to be called from Lua. Derived systems + //register the actual thing + //"init", &System::initNamed, + "setEnabled", &System::setEnabled, + "activate", &System::activate, + "deactivate", &System::deactivate, + "shutdown", &System::shutdown, + "update", &System::update, + + // Marker for Lua to detect C++ systems + "isCppSystem", sol::var(true) + ); } - struct System::Implementation { bool m_enabled = true; - GameState* m_gameState = nullptr; + GameStateData* m_gameState = nullptr; std::string m_name = "Unknown-System"; @@ -156,22 +69,10 @@ System::enabled() const { return m_impl->m_enabled; } - -Engine* -System::engine() const { - if (m_impl->m_gameState) { - return &m_impl->m_gameState->engine(); - } - else { - return nullptr; - } -} - - EntityManager* System::entityManager() const { if (m_impl->m_gameState) { - return &m_impl->m_gameState->entityManager(); + return m_impl->m_gameState->entityManager(); } else { return nullptr; @@ -179,7 +80,7 @@ System::entityManager() const { } -GameState* +GameStateData* System::gameState() const { return m_impl->m_gameState; } @@ -187,18 +88,20 @@ System::gameState() const { void System::init( - GameState* gameState + GameStateData* gameState ) { - assert(m_impl->m_gameState == nullptr && "Cannot initialize system that is already attached to a GameState"); + assert(m_impl->m_gameState == nullptr && + "Cannot initialize system that is already attached to a GameState"); m_impl->m_gameState = gameState; } void System::initNamed( - std::string name, - GameState* gameState + const std::string &name, + GameStateData* gameState ) { - assert(m_impl->m_gameState == nullptr && "Cannot initialize system that is already attached to a GameState"); + assert(m_impl->m_gameState == nullptr && + "Cannot initialize system that is already attached to a GameState"); m_impl->m_gameState = gameState; m_impl->m_name = name; } diff --git a/src/engine/system.h b/src/engine/system.h index f95ef05e111..79924414dc5 100644 --- a/src/engine/system.h +++ b/src/engine/system.h @@ -3,15 +3,15 @@ #include -namespace luabind { -class scope; +namespace sol { +class state; } namespace thrive { class Engine; class EntityManager; -class GameState; +class GameStateData; /** * @brief A system handles one specific part of the game @@ -28,13 +28,17 @@ class System { * @brief Lua bindings * * Exposes: - * - System::active - * - System::setActive + * - System::enabled + * - System::init + * - System::setEnabled + * - System::activate + * - System::deactivate + * - System::shutdown + * - System::update * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -74,16 +78,6 @@ class System { bool enabled() const; - /** - * @brief The system's engine - * - * @return - * The system's engine or \c nullptr if the system hasn't been - * initialized yet. - */ - Engine* - engine() const; - /** * @brief Returns the system's entity manager * @@ -98,7 +92,7 @@ class System { * * If the system has not been initialized yet, this returns \c nullptr. */ - GameState* + GameStateData* gameState() const; /** @@ -111,7 +105,7 @@ class System { */ virtual void init( - GameState* gameState + GameStateData* gameState ); /** @@ -127,8 +121,8 @@ class System { */ virtual void initNamed( - std::string name, - GameState* gameState + const std::string &name, + GameStateData* gameState ); /** diff --git a/src/engine/tests/entity.cpp b/src/engine/tests/entity.cpp index 60ec39104e5..7c7a6b69e7a 100644 --- a/src/engine/tests/entity.cpp +++ b/src/engine/tests/entity.cpp @@ -12,57 +12,58 @@ using namespace thrive; +// TODO: this needs to be basically rewritten in Lua -struct EntityTest : public ::testing::Test { +// struct EntityTest : public ::testing::Test { - EntityTest() - : gameState(engine.createGameState("test", {}, GameState::Initializer(), "DragDropDemo")) - { +// EntityTest() +// : gameState(engine.createGameState("test", {}, GameState::Initializer(), "DragDropDemo")) +// { - } +// } - Engine engine; +// Engine engine; - GameState* gameState = nullptr; +// GameState* gameState = nullptr; -}; +// }; -TEST_F(EntityTest, Exists) { - // Null Id should never exist - Entity nullEntity(NULL_ENTITY, gameState); - EXPECT_FALSE(nullEntity.exists()); - // Entity without components doesn't exist either - Entity entity(gameState); - EXPECT_FALSE(entity.exists()); - // Add some component, then it should exist - entity.addComponent(make_unique>()); - EXPECT_TRUE(entity.exists()); -} +// TEST_F(EntityTest, Exists) { +// // Null Id should never exist +// Entity nullEntity(NULL_ENTITY, gameState); +// EXPECT_FALSE(nullEntity.exists()); +// // Entity without components doesn't exist either +// Entity entity(gameState); +// EXPECT_FALSE(entity.exists()); +// // Add some component, then it should exist +// entity.addComponent(make_unique>()); +// EXPECT_TRUE(entity.exists()); +// } -TEST_F(EntityTest, HasComponent) { - Entity entity(gameState); - EXPECT_FALSE(entity.hasComponent(TestComponent<0>::TYPE_ID)); - entity.addComponent(make_unique>()); - EXPECT_TRUE(entity.hasComponent(TestComponent<0>::TYPE_ID)); -} +// TEST_F(EntityTest, HasComponent) { +// Entity entity(gameState); +// EXPECT_FALSE(entity.hasComponent(TestComponent<0>::TYPE_ID)); +// entity.addComponent(make_unique>()); +// EXPECT_TRUE(entity.hasComponent(TestComponent<0>::TYPE_ID)); +// } -TEST_F(EntityTest, RemoveComponent) { - Entity entity(gameState); - EXPECT_FALSE(entity.hasComponent(TestComponent<0>::TYPE_ID)); - entity.addComponent(make_unique>()); - EXPECT_TRUE(entity.hasComponent(TestComponent<0>::TYPE_ID)); - entity.removeComponent(TestComponent<0>::TYPE_ID); - gameState->entityManager().processRemovals(); - EXPECT_FALSE(entity.hasComponent(TestComponent<0>::TYPE_ID)); -} +// TEST_F(EntityTest, RemoveComponent) { +// Entity entity(gameState); +// EXPECT_FALSE(entity.hasComponent(TestComponent<0>::TYPE_ID)); +// entity.addComponent(make_unique>()); +// EXPECT_TRUE(entity.hasComponent(TestComponent<0>::TYPE_ID)); +// entity.removeComponent(TestComponent<0>::TYPE_ID); +// gameState->entityManager().processRemovals(); +// EXPECT_FALSE(entity.hasComponent(TestComponent<0>::TYPE_ID)); +// } -TEST_F(EntityTest, NamedEntity) { - Entity unnamed(gameState); - Entity named("named", gameState); - Entity namedCopy("named", gameState); - EXPECT_FALSE(named == unnamed); - EXPECT_TRUE(named == namedCopy); -} +// TEST_F(EntityTest, NamedEntity) { +// Entity unnamed(gameState); +// Entity named("named", gameState); +// Entity namedCopy("named", gameState); +// EXPECT_FALSE(named == unnamed); +// EXPECT_TRUE(named == namedCopy); +// } diff --git a/src/engine/touchable.cpp b/src/engine/touchable.cpp index acc404e22bd..4cb23aa30e3 100644 --- a/src/engine/touchable.cpp +++ b/src/engine/touchable.cpp @@ -1,21 +1,20 @@ #include "engine/touchable.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" using namespace thrive; +void Touchable::luaBindings( + sol::state &lua +){ + lua.new_usertype("Touchable", -luabind::scope -Touchable::luaBindings() { - using namespace luabind; - return class_("Touchable") - .def("hasChanges", &Touchable::hasChanges) - .def("touch", &Touchable::touch) - .def("untouch", &Touchable::untouch) - ; + "hasChanges", &Touchable::hasChanges, + "touch", &Touchable::touch, + "untouch", &Touchable::untouch + ); } - bool Touchable::hasChanges() const { return m_hasChanges; diff --git a/src/engine/touchable.h b/src/engine/touchable.h index cf165372f55..cef7845aaa5 100644 --- a/src/engine/touchable.h +++ b/src/engine/touchable.h @@ -1,7 +1,7 @@ #pragma once -namespace luabind { - class scope; +namespace sol { +class state; } namespace thrive { @@ -30,8 +30,7 @@ class Touchable { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Whether this Touchable has unapplied changes diff --git a/src/game.cpp b/src/game.cpp index 38518894902..e292c8efca8 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -2,9 +2,10 @@ #include "engine/engine.h" #include "engine/typedefs.h" -#include "scripting/luabind.h" #include "util/make_unique.h" +#include "scripting/luajit.h" + #include #include #include @@ -31,6 +32,61 @@ struct Game::Implementation { }; +void Game::luaBindings(sol::state &lua){ + + // These probably don't need to be exposed + // lua.new_usertype("boost.time_point" + // ); + + // lua.new_usertype("boost.duration" + // ); + + + + lua.new_usertype("Game", + + "new", sol::no_constructor, + + "shouldQuit", sol::property([](Game &us){ + return us.m_impl->m_quit; + }), + + // Static functions. Access with Game.func + "now", []() -> Implementation::Clock::time_point{ + + return Implementation::Clock::now(); + }, + + "delta", [](const Implementation::Clock::time_point &now, + const Implementation::Clock::time_point &lastUpdate) -> + Implementation::Clock::duration + { + return now - lastUpdate; + }, + + "asMS", [](const Implementation::Clock::duration &duration) -> int32_t + { + return boost::chrono::duration_cast(duration).count(); + }, + + "asSeconds", [](const Implementation::Clock::duration &duration) -> float + { + return boost::chrono::duration_cast>( + duration).count(); + }, + + "sleepIfNeeded", [](Game &us, + const Implementation::Clock::duration &frameDuration) + { + auto sleepDuration = us.m_impl->m_targetFrameDuration - frameDuration; + if (sleepDuration.count() > 0) { + boost::this_thread::sleep_for(sleepDuration); + } + } + ); +} + + Game& Game::instance() { @@ -63,37 +119,21 @@ Game::quit() { void Game::run() { try { - unsigned int fpsCount = 0; - int fpsTime = 0; - auto lastUpdate = Implementation::Clock::now(); + m_impl->m_engine.init(); + // Start game loop m_impl->m_quit = false; - while (not m_impl->m_quit) { - auto now = Implementation::Clock::now(); - auto delta = now - lastUpdate; - int milliSeconds = boost::chrono::duration_cast(delta).count(); - lastUpdate = now; - m_impl->m_engine.update(milliSeconds); - auto frameDuration = Implementation::Clock::now() - now; - auto sleepDuration = m_impl->m_targetFrameDuration - frameDuration; - if (sleepDuration.count() > 0) { - boost::this_thread::sleep_for(sleepDuration); - } - fpsCount += 1; - fpsTime += boost::chrono::duration_cast(frameDuration).count(); - if (fpsTime >= 1000) { - float fps = 1000 * float(fpsCount) / float(fpsTime); - std::cout << "FPS: " << fps << std::endl; - fpsCount = 0; - fpsTime = 0; - } - } - m_impl->m_engine.shutdown(); + m_impl->m_engine.enterLuaMain(this); } - catch (const luabind::error& e) { - printLuaError(e); + catch (const sol::error& e) { + + std::cerr << "Main loop/init failed with error: " << + e.what() << std::endl; } + + // Shutdown needs to be called even if init/main loop fails + m_impl->m_engine.shutdown(); } diff --git a/src/game.h b/src/game.h index 861ab35bb1b..ede52757110 100644 --- a/src/game.h +++ b/src/game.h @@ -3,6 +3,11 @@ #include #include +namespace sol{ + +class state; +} + namespace thrive { class Engine; @@ -17,6 +22,19 @@ class Game { public: + /** + * @brief Lua bindings + * + * Exposes: + * - Game::Implementation::shouldQuit + * - now + * - delta + * - asMS + * - sleepIfNeeded + * + * @return + */ + static void luaBindings(sol::state &lua); /** * @brief Singleton instance diff --git a/src/general/CMakeLists.txt b/src/general/CMakeLists.txt index 358bd8cb9fd..bab8268091d 100644 --- a/src/general/CMakeLists.txt +++ b/src/general/CMakeLists.txt @@ -5,8 +5,6 @@ add_sources( "${CMAKE_CURRENT_SOURCE_DIR}/locked_map.h" "${CMAKE_CURRENT_SOURCE_DIR}/powerup_system.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/powerup_system.h" - "${CMAKE_CURRENT_SOURCE_DIR}/script_bindings.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/script_bindings.h" "${CMAKE_CURRENT_SOURCE_DIR}/perlin_noise.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/perlin_noise.h" "${CMAKE_CURRENT_SOURCE_DIR}/thrive_math.cpp" diff --git a/src/general/locked_map.cpp b/src/general/locked_map.cpp index 392dd277e2b..fc022e1624f 100644 --- a/src/general/locked_map.cpp +++ b/src/general/locked_map.cpp @@ -6,21 +6,20 @@ #include "engine/game_state.h" #include "engine/serialization.h" -#include - - using namespace thrive; -luabind::scope -LockedMap::luaBindings() { - using namespace luabind; - return class_("LockedMap") - .def(constructor<>()) - .def("addLock", &LockedMap::addLock) - .def("isLocked", &LockedMap::isLocked) - .def("unlock", &LockedMap::unlock) - .def("locksList", &LockedMap::locksList, return_stl_iterator) - ; +void LockedMap::luaBindings( + sol::state &lua +){ + lua.new_usertype("LockedMap", + + sol::constructors>(), + + "addLock", &LockedMap::addLock, + "isLocked", &LockedMap::isLocked, + "unlock", &LockedMap::unlock, + "locksList", &LockedMap::locksList + ); } void diff --git a/src/general/locked_map.h b/src/general/locked_map.h index 303a4aa1ac5..b7ba1e34bc4 100644 --- a/src/general/locked_map.h +++ b/src/general/locked_map.h @@ -3,13 +3,11 @@ #include "engine/system.h" #include "engine/touchable.h" #include "engine/typedefs.h" -#include "scripting/luabind.h" -#include #include #include -namespace luabind { -class scope; +namespace sol { +class state; } @@ -35,8 +33,7 @@ class LockedMap { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** diff --git a/src/general/powerup_system.cpp b/src/general/powerup_system.cpp index a218e05fdf3..a702c1160f1 100644 --- a/src/general/powerup_system.cpp +++ b/src/general/powerup_system.cpp @@ -10,31 +10,26 @@ #include "engine/entity_filter.h" #include "engine/game_state.h" #include "engine/serialization.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include -#include -#include -#include - using namespace thrive; -luabind::scope -PowerupComponent::luaBindings() { - using namespace luabind; - return class_("PowerupComponent") - .enum_("ID") [ - value("TYPE_ID", PowerupComponent::TYPE_ID) - ] - .scope [ - def("TYPE_NAME", &PowerupComponent::TYPE_NAME) - ] - .def(constructor<>()) - .def("setEffect", - static_cast(&PowerupComponent::setEffect) - ) - ; +void PowerupComponent::luaBindings( + sol::state &lua +){ + lua.new_usertype("PowerupComponent", + + "new", sol::factories([](){ + return std::make_unique(); + }), + + COMPONENT_BINDINGS(PowerupComponent), + + "setEffect", static_cast(&PowerupComponent::setEffect) + ); } void @@ -109,14 +104,18 @@ REGISTER_COMPONENT(PowerupComponent) // PowerupSystem //////////////////////////////////////////////////////////////////////////////// -luabind::scope -PowerupSystem::luaBindings() { - using namespace luabind; - return class_("PowerupSystem") - .def(constructor<>()) - ; -} +void PowerupSystem::luaBindings( + sol::state &lua +){ + lua.new_usertype("PowerupSystem", + sol::constructors>(), + + sol::base_classes, sol::bases(), + + "init", &PowerupSystem::init + ); +} struct PowerupSystem::Implementation { @@ -146,12 +145,12 @@ PowerupSystem::~PowerupSystem() {} void PowerupSystem::init( - GameState* gameState + GameStateData* gameState ) { System::initNamed("PowerupSystem", gameState); - m_impl->m_entities.setEntityManager(&gameState->entityManager()); + m_impl->m_entities.setEntityManager(gameState->entityManager()); m_impl->m_powerupCollisions.init(gameState); - m_impl->m_entityManager = &gameState->entityManager(); + m_impl->m_entityManager = gameState->entityManager(); } diff --git a/src/general/powerup_system.h b/src/general/powerup_system.h index 9d5e09a6c7f..3a049020bc6 100644 --- a/src/general/powerup_system.h +++ b/src/general/powerup_system.h @@ -4,12 +4,9 @@ #include "engine/system.h" #include "engine/touchable.h" #include "engine/typedefs.h" -#include "scripting/luabind.h" -#include - -namespace luabind { -class scope; +namespace sol { +class state; } @@ -33,8 +30,7 @@ class PowerupComponent : public Component { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Sets the effect to use upon activation of the powerup @@ -99,8 +95,7 @@ class PowerupSystem : public System { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -116,7 +111,7 @@ class PowerupSystem : public System { * @brief Initializes the system * */ - void init(GameState* gameState) override; + void init(GameStateData* gameState) override; /** * @brief Shuts the system down diff --git a/src/general/script_bindings.cpp b/src/general/script_bindings.cpp deleted file mode 100644 index 21794455a86..00000000000 --- a/src/general/script_bindings.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "general/script_bindings.h" - -#include "scripting/luabind.h" -#include "general/timed_life_system.h" -#include "general/locked_map.h" -#include "general/powerup_system.h" - -luabind::scope -thrive::GeneralBindings::luaBindings() { - return ( - // Components - TimedLifeComponent::luaBindings(), - LockedMap::luaBindings(), - PowerupComponent::luaBindings(), - // Systems - TimedLifeSystem::luaBindings(), - PowerupSystem::luaBindings() - // Other - ); -} - - diff --git a/src/general/script_bindings.h b/src/general/script_bindings.h deleted file mode 100644 index d6edf1abb32..00000000000 --- a/src/general/script_bindings.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -namespace luabind { -class scope; -} - -namespace thrive { - -/** -* @brief Helper for script bindings -*/ -struct GeneralBindings { - - /** - * @brief Exports relevant general bindings to Lua - * - * @return - */ - static luabind::scope - luaBindings(); - -}; - -} - - diff --git a/src/general/timed_life_system.cpp b/src/general/timed_life_system.cpp index 47df280e11e..38decfeba4f 100644 --- a/src/general/timed_life_system.cpp +++ b/src/general/timed_life_system.cpp @@ -6,29 +6,27 @@ #include "engine/game_state.h" #include "engine/serialization.h" #include "game.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" using namespace thrive; REGISTER_COMPONENT(TimedLifeComponent) +void TimedLifeComponent::luaBindings( + sol::state &lua +){ + lua.new_usertype("TimedLifeComponent", -luabind::scope -TimedLifeComponent::luaBindings() { - using namespace luabind; - return class_("TimedLifeComponent") - .enum_("ID") [ - value("TYPE_ID", TimedLifeComponent::TYPE_ID) - ] - .scope [ - def("TYPE_NAME", &TimedLifeComponent::TYPE_NAME) - ] - .def(constructor<>()) - .def_readwrite("timeToLive", &TimedLifeComponent::m_timeToLive) - ; -} + "new", sol::factories([](){ + return std::make_unique(); + }), + + COMPONENT_BINDINGS(TimedLifeComponent), + "timeToLive", &TimedLifeComponent::m_timeToLive + ); +} void TimedLifeComponent::load( @@ -51,14 +49,18 @@ TimedLifeComponent::storage() const { // TimedLifeSystem //////////////////////////////////////////////////////////////////////////////// -luabind::scope -TimedLifeSystem::luaBindings() { - using namespace luabind; - return class_("TimedLifeSystem") - .def(constructor<>()) - ; -} +void TimedLifeSystem::luaBindings( + sol::state &lua +){ + lua.new_usertype("TimedLifeSystem", + sol::constructors>(), + + sol::base_classes, sol::bases(), + + "init", &TimedLifeSystem::init + ); +} struct TimedLifeSystem::Implementation { @@ -79,10 +81,10 @@ TimedLifeSystem::~TimedLifeSystem() {} void TimedLifeSystem::init( - GameState* gameState + GameStateData* gameState ) { System::initNamed("TimedLifeSystem", gameState); - m_impl->m_entities.setEntityManager(&gameState->entityManager()); + m_impl->m_entities.setEntityManager(gameState->entityManager()); } diff --git a/src/general/timed_life_system.h b/src/general/timed_life_system.h index fa6745e1a08..5cbfde7fc22 100644 --- a/src/general/timed_life_system.h +++ b/src/general/timed_life_system.h @@ -3,11 +3,10 @@ #include "engine/component.h" #include "engine/system.h" #include "engine/touchable.h" -#include "scripting/luabind.h" -namespace luabind { -class scope; +namespace sol { +class state; } @@ -31,8 +30,7 @@ class TimedLifeComponent : public Component { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief The time until the owning entity despawns @@ -65,8 +63,7 @@ class TimedLifeSystem : public System { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -82,7 +79,7 @@ class TimedLifeSystem : public System { * @brief Initializes the system * */ - void init(GameState* gameState) override; + void init(GameStateData* gameState) override; /** * @brief Shuts the system down diff --git a/src/gui/CEGUIVideoPlayer.cpp b/src/gui/CEGUIVideoPlayer.cpp index 20eac4c5f3f..aee6716223e 100644 --- a/src/gui/CEGUIVideoPlayer.cpp +++ b/src/gui/CEGUIVideoPlayer.cpp @@ -3,15 +3,13 @@ #include "engine/engine.h" #include "game.h" #include "script_wrappers.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include #include #include #include #include -#include -#include #include #include @@ -38,8 +36,8 @@ CEGUIVideoPlayer::CEGUIVideoPlayer( &CEGUI::ImageManager::getSingleton().create( "BitmapImage", "ThriveGeneric/VideoImage")); - m_window->setWidth(CEGUI::UDim(0,width)); - m_window->setHeight(CEGUI::UDim(0,height)); + m_window->setWidth(CEGUI::UDim(0, width)); + m_window->setHeight(CEGUI::UDim(0, height)); } CEGUIVideoPlayer::CEGUIVideoPlayer( @@ -56,26 +54,36 @@ CEGUIVideoPlayer::~CEGUIVideoPlayer() delete m_tex; } -luabind::scope -CEGUIVideoPlayer::luaBindings() { - using namespace luabind; - return class_("CEGUIVideoPlayer") - .def(constructor()) - .def(constructor()) - .def("play", &CEGUIVideoPlayer::play) - .def("close", &CEGUIVideoPlayer::close) - .def("setVideo", &CEGUIVideoPlayer::setVideo) - .def("update", &CEGUIVideoPlayer::update) - .def("getDuration", &CEGUIVideoPlayer::getDuration) - .def("getCurrentTime", &CEGUIVideoPlayer::getCurrentTime) - .def("seek", &CEGUIVideoPlayer::seek) - .scope - [ - def("destroyVideoPlayer", &destroyVideoPlayer, adopt(_1)) //Static - ]; - ; + +void CEGUIVideoPlayer::luaBindings( + sol::state &lua +){ + lua.new_usertype("CEGUIVideoPlayer", + + "new", sol::factories([](const std::string &name, int width, int height){ + + return new CEGUIVideoPlayer(name, width, height); + + }, [](const std::string &name){ + + return new CEGUIVideoPlayer(name); + }), + + sol::base_classes, sol::bases(), + + "play", &CEGUIVideoPlayer::play, + "close", &CEGUIVideoPlayer::close, + "setVideo", &CEGUIVideoPlayer::setVideo, + "update", &CEGUIVideoPlayer::update, + "getDuration", &CEGUIVideoPlayer::getDuration, + "getCurrentTime", &CEGUIVideoPlayer::getCurrentTime, + "seek", &CEGUIVideoPlayer::seek, + + "destroyVideoPlayer", &destroyVideoPlayer //Static + ); } + void CEGUIVideoPlayer::play() { m_videoPlayer->play(); @@ -89,7 +97,7 @@ CEGUIVideoPlayer::destroyVideoPlayer(CEGUIVideoPlayer* player) void CEGUIVideoPlayer::pause() { - + throw std::runtime_error("CEGUIVideoPlayer::pause is unimplemented"); } void @@ -131,13 +139,18 @@ CEGUIVideoPlayer::setVideo( CEGUI::OgreTexture& rendererTexture = static_cast(texture); - rendererTexture.setOgreTexture(Ogre::TextureManager::getSingleton().getByName(m_videoPlayer->getTextureName()), false); + rendererTexture.setOgreTexture(Ogre::TextureManager::getSingleton().getByName( + m_videoPlayer->getTextureName()), false); + + CEGUI::OgreRenderer* ogreRenderer = static_cast( + CEGUI::System::getSingleton().getRenderer()); - CEGUI::OgreRenderer* ogreRenderer = static_cast(CEGUI::System::getSingleton().getRenderer()); bool isTextureTargetVerticallyFlipped = ogreRenderer->isTexCoordSystemFlipped(); + CEGUI::Rectf imageArea; int videoW = m_videoPlayer->getVideoWidth(); int videoH = m_videoPlayer->getVideoHeight(); + if (isTextureTargetVerticallyFlipped){ imageArea= CEGUI::Rectf(0.0f, videoW, videoH, 0.0f); } @@ -145,8 +158,15 @@ CEGUIVideoPlayer::setVideo( imageArea= CEGUI::Rectf(0.0f, 0.0f, videoW, videoH); } m_videoImage->setImageArea(imageArea); - // You most likely don't want autoscaling for RTT images. If you display it in stretched-mode inside a button or Generic/Image widget, then this setting does not play a role anyways. - m_videoImage->setAutoScaled(CEGUI::ASM_Disabled); + + // You most likely don't want autoscaling for RTT images. If you + // display it in stretched-mode inside a button or Generic/Image + // widget, then this setting does not play a role anyways. + #ifdef WIN32 + m_videoImage->setAutoScaled(CEGUI::AutoScaledMode::ASM_Disabled); + #else + m_videoImage->setAutoScaled(CEGUI::AutoScaledMode::Disabled); + #endif m_videoImage->setTexture(&rendererTexture); } diff --git a/src/gui/CEGUIVideoPlayer.h b/src/gui/CEGUIVideoPlayer.h index ad96e1696a7..e681e32c5d4 100644 --- a/src/gui/CEGUIVideoPlayer.h +++ b/src/gui/CEGUIVideoPlayer.h @@ -1,14 +1,13 @@ #pragma once #include -#include #include #include #include "gui/CEGUIWindow.h" -namespace luabind { -class scope; +namespace sol { +class state; } namespace Ogre { @@ -76,8 +75,7 @@ class CEGUIVideoPlayer : public CEGUIWindow{ * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Sets the video to play diff --git a/src/gui/CEGUIWindow.cpp b/src/gui/CEGUIWindow.cpp index d51040a442d..d98bcc2ab1c 100644 --- a/src/gui/CEGUIWindow.cpp +++ b/src/gui/CEGUIWindow.cpp @@ -4,10 +4,8 @@ #include "game.h" #include "ogre/mouse.h" #include "script_wrappers.h" -#include "scripting/luabind.h" #include -#include #include #include @@ -157,7 +155,7 @@ CEGUIWindow::CEGUIWindow( std::string name ){ m_window = CEGUI::WindowManager::getSingleton().createWindow(type, name); - //Only used for when the gui movement mode is activated ); + //Only used for when the gui movement mode is activated m_window->subscribeEvent("MouseClick", handleWindowMove); } @@ -166,65 +164,77 @@ CEGUIWindow::~CEGUIWindow() { } -luabind::scope -CEGUIWindow::luaBindings() { - using namespace luabind; - return class_("CEGUIWindow") - //.scope - //[ - // def("getRootWindow", &CEGUIWindow::getRootWindow) //Better to use gameState::rootGUIWindow - //] - .def(constructor()) - .def(constructor()) - .def("isNull", &CEGUIWindow::isNull) - .def("getText", &CEGUIWindow::getText) - .def("setText", &CEGUIWindow::setText) - .def("appendText", &CEGUIWindow::appendText) - .def("setImage", &CEGUIWindow::setImage) - .def("setProperty", &CEGUIWindow::setProperty) - .def("getParent", &CEGUIWindow::getParent) - .def("getChild", &CEGUIWindow::getChild) - .def("addChild", &CEGUIWindow::addChild) - .def("removeChild", &CEGUIWindow::removeChild) - .def("registerEventHandler", - static_cast(&CEGUIWindow::registerEventHandler) - ) - .def("enable", &CEGUIWindow::enable) - .def("disable", &CEGUIWindow::disable) - .def("setFocus", &CEGUIWindow::setFocus) - .def("show", &CEGUIWindow::show) - .def("hide", &CEGUIWindow::hide) - .def("moveToFront", &CEGUIWindow::moveToFront) - .def("moveToBack", &CEGUIWindow::moveToBack) - .def("moveInFront", &CEGUIWindow::moveInFront) - .def("moveBehind", &CEGUIWindow::moveBehind) - .def("setPositionAbs", &CEGUIWindow::setPositionAbs) - .def("setPositionRel", &CEGUIWindow::setPositionRel) - .def("setSizeAbs", &CEGUIWindow::setSizeAbs) - .def("setSizeRel", &CEGUIWindow::setSizeRel) - .def("getName", &CEGUIWindow::getName) - .def("playAnimation", &CEGUIWindow::playAnimation) - .def("listWidgetAddItem", &CEGUIWindow::listWidgetAddStandardItem) - .def("listWidgetAddItem", &CEGUIWindow::listWidgetAddTextItem) - .def("listWidgetAddItem", &CEGUIWindow::listWidgetAddItem) - .def("listWidgetResetList", &CEGUIWindow::listWidgetResetList) - .def("listWidgetUpdateItem", &CEGUIWindow::listWidgetUpdateItem) - .def("listWidgetGetFirstSelectedID", &CEGUIWindow::listWidgetGetFirstSelectedID) - .def("listWidgetGetFirstSelectedItemText", - &CEGUIWindow::listWidgetGetFirstSelectedItemText) - .def("progressbarSetProgress", &CEGUIWindow::progressbarSetProgress) - .def("scrollingpaneAddIcon", &CEGUIWindow::scrollingpaneAddIcon) - .def("scrollingpaneGetVerticalPosition", &CEGUIWindow::scrollingpaneGetVerticalPosition) - .def("scrollingpaneSetVerticalPosition", &CEGUIWindow::scrollingpaneSetVerticalPosition) - .def("registerKeyEventHandler", - static_cast(&CEGUIWindow::registerKeyEventHandler) - ) - .scope - [ - def("setGuiMoveMode", &CEGUIWindow::setGuiMoveMode), - def("getWindowUnderMouse", &CEGUIWindow::getWindowUnderMouse) - ] - ; +void CEGUIWindow::luaBindings( + sol::state &lua +){ + // This needs to be incrementally created usertype because otherwise there are way too + // many template instantations and the compiler doesn't like it + auto ceguiWindowRegistration = lua.create_simple_usertype( + sol::constructors, sol::types>(), + + "isNull", &CEGUIWindow::isNull, + "getText", &CEGUIWindow::getText, + "setText", &CEGUIWindow::setText + + ); + + ceguiWindowRegistration.set("appendText", &CEGUIWindow::appendText); + ceguiWindowRegistration.set("setImage", &CEGUIWindow::setImage); + ceguiWindowRegistration.set("setProperty", &CEGUIWindow::setProperty); + ceguiWindowRegistration.set("getParent", &CEGUIWindow::getParent); + ceguiWindowRegistration.set("getChild", &CEGUIWindow::getChild); + ceguiWindowRegistration.set("addChild", &CEGUIWindow::addChild); + ceguiWindowRegistration.set("removeChild", &CEGUIWindow::removeChild); + ceguiWindowRegistration.set("registerEventHandler", static_cast( + &CEGUIWindow::registerEventHandler)); + ceguiWindowRegistration.set("enable", &CEGUIWindow::enable); + ceguiWindowRegistration.set("disable", &CEGUIWindow::disable); + ceguiWindowRegistration.set("setFocus", &CEGUIWindow::setFocus); + ceguiWindowRegistration.set("show", &CEGUIWindow::show); + ceguiWindowRegistration.set("hide", &CEGUIWindow::hide); + ceguiWindowRegistration.set("moveToFront", &CEGUIWindow::moveToFront); + ceguiWindowRegistration.set("moveToBack", &CEGUIWindow::moveToBack); + ceguiWindowRegistration.set("moveInFront", &CEGUIWindow::moveInFront); + ceguiWindowRegistration.set("moveBehind", &CEGUIWindow::moveBehind); + ceguiWindowRegistration.set("setPositionAbs", &CEGUIWindow::setPositionAbs); + ceguiWindowRegistration.set("setPositionRel", &CEGUIWindow::setPositionRel); + ceguiWindowRegistration.set("setSizeAbs", &CEGUIWindow::setSizeAbs); + ceguiWindowRegistration.set("setSizeRel", &CEGUIWindow::setSizeRel); + ceguiWindowRegistration.set("getName", &CEGUIWindow::getName); + ceguiWindowRegistration.set("playAnimation", &CEGUIWindow::playAnimation); + ceguiWindowRegistration.set("listWidgetAddItem", &CEGUIWindow::listWidgetAddStandardItem); + ceguiWindowRegistration.set("listWidgetAddItem", &CEGUIWindow::listWidgetAddTextItem); + ceguiWindowRegistration.set("listWidgetAddItem", &CEGUIWindow::listWidgetAddItem); + ceguiWindowRegistration.set("listWidgetResetList", &CEGUIWindow::listWidgetResetList); + ceguiWindowRegistration.set("listWidgetUpdateItem", &CEGUIWindow::listWidgetUpdateItem); + ceguiWindowRegistration.set("listWidgetGetFirstSelectedID", + &CEGUIWindow::listWidgetGetFirstSelectedID); + ceguiWindowRegistration.set("listWidgetGetFirstSelectedItemText", + &CEGUIWindow::listWidgetGetFirstSelectedItemText); + ceguiWindowRegistration.set("progressbarSetProgress", + &CEGUIWindow::progressbarSetProgress); + ceguiWindowRegistration.set("scrollingpaneAddIcon", &CEGUIWindow::scrollingpaneAddIcon); + ceguiWindowRegistration.set("scrollingpaneGetVerticalPosition", + &CEGUIWindow::scrollingpaneGetVerticalPosition); + ceguiWindowRegistration.set("scrollingpaneSetVerticalPosition", + &CEGUIWindow::scrollingpaneSetVerticalPosition); + ceguiWindowRegistration.set("registerKeyEventHandler", + static_cast( + &CEGUIWindow::registerKeyEventHandler)); + ceguiWindowRegistration.set("setGuiMoveMode", &CEGUIWindow::setGuiMoveMode); + ceguiWindowRegistration.set("getWindowUnderMouse", &CEGUIWindow::getWindowUnderMouse); + + //! Returns the global root window. Use game_state.guiWindow + //! instead unless you really need the global root window + ceguiWindowRegistration.set("getRootWindow", [](){ + + return CEGUIWindow(CEGUI::System::getSingleton(). + getDefaultGUIContext().getRootWindow(), false); + }); + + // Register it + lua.set_usertype("CEGUIWindow", ceguiWindowRegistration); } bool @@ -453,13 +463,14 @@ CEGUIWindow::registerEventHandler( void CEGUIWindow::registerEventHandler( const std::string& eventName, - const luabind::object& callback + const sol::function& callback ) const { // Lambda must return something to avoid an template error. auto callbackLambda = [callback](const CEGUI::EventArgs& args) -> bool { - luabind::call_function(callback, CEGUIWindow(static_cast(args).window, false)); + callback(CEGUIWindow(static_cast(args).window, + false)); return 0; }; @@ -475,12 +486,12 @@ CEGUIWindow::registerKeyEventHandler( void CEGUIWindow::registerKeyEventHandler( - const luabind::object& callback + const sol::function& callback ) const { // Event doesn't exist anymore // auto callbackLambda = [callback](const CEGUI::EventArgs& args) -> bool { - luabind::call_function(callback, CEGUIWindow(static_cast< + callback(CEGUIWindow(static_cast< const CEGUI::WindowEventArgs&>(args).window, false), static_cast(static_cast(args).d_character)); return 0; diff --git a/src/gui/CEGUIWindow.h b/src/gui/CEGUIWindow.h index cb712cd082e..010f9c72298 100644 --- a/src/gui/CEGUIWindow.h +++ b/src/gui/CEGUIWindow.h @@ -1,13 +1,14 @@ #pragma once +#include "scripting/luajit.h" + #include -#include #include #include -namespace luabind { -class scope; +namespace sol { +class state; } namespace thrive { @@ -109,8 +110,7 @@ class CEGUIWindow { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); static void setGuiMoveMode( @@ -361,7 +361,7 @@ class CEGUIWindow { void registerEventHandler( const std::string& eventName, - const luabind::object& callback + const sol::function& callback ) const ; /** @@ -378,7 +378,7 @@ class CEGUIWindow { /// Same as above but for lua callbacks void registerKeyEventHandler( - const luabind::object& callback + const sol::function& callback ) const ; /** @@ -507,7 +507,7 @@ class CEGUIWindow { private: - friend class GameState; + friend class GameStateData; //Private constructor. New window is true if this is the first time a CEGUIWindow is created with the window pointer (for event subscribing) CEGUIWindow(CEGUI::Window* window, bool newWindow = true); diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index e073f642a1e..9592d70fa21 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -3,8 +3,6 @@ add_sources( "${CMAKE_CURRENT_SOURCE_DIR}/CEGUIWindow.h" "${CMAKE_CURRENT_SOURCE_DIR}/AlphaHitWindow.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/AlphaHitWindow.h" - "${CMAKE_CURRENT_SOURCE_DIR}/script_bindings.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/script_bindings.h" "${CMAKE_CURRENT_SOURCE_DIR}/cegui_types.h" "${CMAKE_CURRENT_SOURCE_DIR}/script_wrappers.h" "${CMAKE_CURRENT_SOURCE_DIR}/script_wrappers.cpp" diff --git a/src/gui/script_bindings.cpp b/src/gui/script_bindings.cpp deleted file mode 100644 index 951f4dd0130..00000000000 --- a/src/gui/script_bindings.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "gui/script_bindings.h" - -#include "gui/CEGUIWindow.h" -#include "gui/CEGUIVideoPlayer.h" -#include "script_wrappers.h" -#include "scripting/luabind.h" - -using namespace luabind; - -static void -ListboxItem_setColour( - CEGUI::ListboxTextItem* self, - float r, - float g, - float b -) { - self->setTextColours(CEGUI::Colour(r,g,b)); -} - -static void -ListboxItem_setText( - CEGUI::ListboxTextItem* self, - const std::string& text -) { - self->setText(text); -} - - -static luabind::scope -listboxItemBindings() { - return class_("ListboxItem") - .def(constructor()) - .def("setTextColours", &ListboxItem_setColour) - .def("setText", &ListboxItem_setText) - ; -} - -static void -ItemEntry_setText( - CEGUI::ItemEntry* self, - const std::string& text -) { - self->setText(text); -} - -static bool -ItemEntry_isSelected( - CEGUI::ItemEntry* self -) { - return self->isSelected(); -} - -static void -ItemEntry_select( - CEGUI::ItemEntry* self -) { - self->select(); -} - -static void -ItemEntry_deselect( - CEGUI::ItemEntry* self -) { - self->deselect(); -} - -static void -ItemEntry_setSelectable( - CEGUI::ItemEntry* self, - bool setting -) { - self->setSelectable(setting); -} - -static luabind::scope -itemEntryBindings() { - return class_("ItemEntry") - .def(constructor()) - .def("isSelected", &ItemEntry_isSelected) - .def("select", &ItemEntry_select) - .def("deselect", &ItemEntry_deselect) - .def("setSelectable", &ItemEntry_setSelectable) - .def("setText", &ItemEntry_setText) - ; -} - -luabind::scope -thrive::GuiBindings::luaBindings() { - return ( - // Other - listboxItemBindings(), - itemEntryBindings(), - CEGUIWindow::luaBindings(), - CEGUIVideoPlayer::luaBindings(), - ScriptWrappers::StandardItemWrapperBindings() - ); -} - - diff --git a/src/gui/script_bindings.h b/src/gui/script_bindings.h deleted file mode 100644 index 8fbd6548796..00000000000 --- a/src/gui/script_bindings.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -namespace luabind { -class scope; -} - -namespace thrive { - -/** -* @brief Helper for script bindings -*/ -struct GuiBindings { - - /** - * @brief Exports relevant gui bindings to lua - * - * @return - */ - static luabind::scope - luaBindings(); - -}; - -} - - diff --git a/src/gui/script_wrappers.cpp b/src/gui/script_wrappers.cpp index b1e08b8a916..29ddbc407d1 100644 --- a/src/gui/script_wrappers.cpp +++ b/src/gui/script_wrappers.cpp @@ -2,18 +2,19 @@ #include #include -#include "scripting/luabind.h" +#include "scripting/luajit.h" using namespace thrive; -using namespace luabind; -luabind::scope -ScriptWrappers::StandardItemWrapperBindings() { - return class_("StandardItemWrapper") - .def(constructor()) - ; -} +void StandardItemWrapper::luaBindings( + sol::state &lua +){ + lua.new_usertype("StandardItemWrapper", + + sol::constructors>() + ); +} StandardItemWrapper::StandardItemWrapper( const std::string &text, diff --git a/src/gui/script_wrappers.h b/src/gui/script_wrappers.h index 443ed2a6347..7f12cad0ebb 100644 --- a/src/gui/script_wrappers.h +++ b/src/gui/script_wrappers.h @@ -7,9 +7,8 @@ namespace CEGUI { class StandardItem; } -namespace luabind { - - class scope; +namespace sol { +class state; } namespace thrive { @@ -17,6 +16,9 @@ namespace thrive { // StandardItemWrapper class StandardItemWrapper{ public: + + static void luaBindings(sol::state &lua); + //! @brief Constructs a wrapper around CEGUI::StandardItem(text, id) StandardItemWrapper( const std::string &text, @@ -40,12 +42,5 @@ class StandardItemWrapper{ CEGUI::StandardItem* m_item; }; -class ScriptWrappers final{ -public: - static luabind::scope - StandardItemWrapperBindings(); - -}; - } diff --git a/src/microbe_stage/CMakeLists.txt b/src/microbe_stage/CMakeLists.txt index d7d9d5d5caf..e07a7ed2f87 100644 --- a/src/microbe_stage/CMakeLists.txt +++ b/src/microbe_stage/CMakeLists.txt @@ -9,8 +9,6 @@ add_sources( "${CMAKE_CURRENT_SOURCE_DIR}/compound_emitter_system.h" "${CMAKE_CURRENT_SOURCE_DIR}/bio_process_registry.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/bio_process_registry.h" - "${CMAKE_CURRENT_SOURCE_DIR}/script_bindings.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/script_bindings.h" "${CMAKE_CURRENT_SOURCE_DIR}/membrane_system.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/membrane_system.h" "${CMAKE_CURRENT_SOURCE_DIR}/compound_cloud_system.cpp" diff --git a/src/microbe_stage/agent_cloud_system.cpp b/src/microbe_stage/agent_cloud_system.cpp index 9cded69fdce..3ce17008890 100644 --- a/src/microbe_stage/agent_cloud_system.cpp +++ b/src/microbe_stage/agent_cloud_system.cpp @@ -12,7 +12,7 @@ #include "engine/serialization.h" #include "game.h" #include "ogre/scene_node_system.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include "util/make_unique.h" #include @@ -37,24 +37,24 @@ using namespace thrive; // AgentCloudComponent //////////////////////////////////////////////////////////////////////////////// -luabind::scope -AgentCloudComponent::luaBindings() { - using namespace luabind; - return class_("AgentCloudComponent") - .enum_("ID") [ - value("TYPE_ID", AgentCloudComponent::TYPE_ID) - ] - .scope [ - def("TYPE_NAME", &AgentCloudComponent::TYPE_NAME) - ] - .def(constructor<>()) - .def("initialize", &AgentCloudComponent::initialize) - .def_readwrite("direction", &AgentCloudComponent::direction) - .def_readwrite("potency", &AgentCloudComponent::potency) - .def_readonly("width", &AgentCloudComponent::width) - .def_readonly("height", &AgentCloudComponent::height) - .def_readonly("gridSize", &AgentCloudComponent::gridSize) - ; +void AgentCloudComponent::luaBindings( + sol::state &lua +){ + lua.new_usertype("AgentCloudComponent", + + "new", sol::factories([](){ + return std::make_unique(); + }), + + COMPONENT_BINDINGS(AgentCloudComponent), + + "initialize", &AgentCloudComponent::initialize, + "direction", &AgentCloudComponent::direction, + "potency", &AgentCloudComponent::potency, + "width", sol::readonly(&AgentCloudComponent::width), + "height", sol::readonly(&AgentCloudComponent::height), + "gridSize", sol::readonly(&AgentCloudComponent::gridSize) + ); } void @@ -115,14 +115,18 @@ REGISTER_COMPONENT(AgentCloudComponent) // AgentCloudSystem //////////////////////////////////////////////////////////////////////////////// -luabind::scope -AgentCloudSystem::luaBindings() { - using namespace luabind; - return class_("AgentCloudSystem") - .def(constructor<>()) - ; -} +void AgentCloudSystem::luaBindings( + sol::state &lua +){ + lua.new_usertype("AgentCloudSystem", + + sol::constructors>(), + + sol::base_classes, sol::bases(), + "init", &AgentCloudSystem::init + ); +} struct AgentCloudSystem::Implementation { // All entities that have an agent CloudsComponent and a scene node. @@ -147,10 +151,10 @@ AgentCloudSystem::~AgentCloudSystem() { void AgentCloudSystem::init( - GameState* gameState + GameStateData* gameState ) { System::initNamed("AgentCloudSystem", gameState); - m_impl->m_compounds.setEntityManager(&gameState->entityManager()); + m_impl->m_compounds.setEntityManager(gameState->entityManager()); m_impl->m_sceneManager = gameState->sceneManager(); this->gameState = gameState; } diff --git a/src/microbe_stage/agent_cloud_system.h b/src/microbe_stage/agent_cloud_system.h index f878776dccd..83261f50f02 100644 --- a/src/microbe_stage/agent_cloud_system.h +++ b/src/microbe_stage/agent_cloud_system.h @@ -8,7 +8,6 @@ #include "engine/component.h" #include "engine/system.h" #include "engine/touchable.h" -#include "scripting/luabind.h" #include "engine/typedefs.h" #include "general/perlin_noise.h" @@ -58,8 +57,7 @@ class AgentCloudComponent : public Component { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); void load( @@ -90,8 +88,7 @@ class AgentCloudSystem : public System { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -108,7 +105,7 @@ class AgentCloudSystem : public System { * * @param gameState */ - void init(GameState* gameState) override; + void init(GameStateData* gameState) override; /** * @brief Shuts the system down @@ -123,7 +120,8 @@ class AgentCloudSystem : public System { private: struct Implementation; std::unique_ptr m_impl; - GameState* gameState; + //! \todo Remove this. This is in the base class already + GameStateData* gameState; void diffuse(float diffRate, std::vector< std::vector >& oldDens, const std::vector< std::vector >& density, int dt); }; diff --git a/src/microbe_stage/bio_process_registry.cpp b/src/microbe_stage/bio_process_registry.cpp index 64ba4ce3e51..c6329f2b998 100644 --- a/src/microbe_stage/bio_process_registry.cpp +++ b/src/microbe_stage/bio_process_registry.cpp @@ -2,35 +2,37 @@ #include "microbe_stage/bio_process_registry.h" #include "microbe_stage/compound.h" #include "microbe_stage/compound_registry.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include "tinyxml.h" -#include - using namespace thrive; -luabind::scope -BioProcessRegistry::luaBindings() { - using namespace luabind; - return (class_("BioProcessRegistry") - .scope - [ - def("loadFromXML", &BioProcessRegistry::loadFromXML), - def("loadFromLua", &BioProcessRegistry::loadFromLua), - //def("registerBioProcess", &BioProcessRegistry::registerBioProcess), - def("getDisplayName", &BioProcessRegistry::getDisplayName), - def("getInternalName", &BioProcessRegistry::getInternalName), - def("getId", &BioProcessRegistry::getId), - def("getList", &BioProcessRegistry::getList, return_stl_iterator), - def("getInputCompounds", &BioProcessRegistry::getInputCompounds, return_stl_iterator), - def("getOutputCompounds", &BioProcessRegistry::getOutputCompounds, return_stl_iterator) - ] - , - class_>("RecipyCompound") - .def_readonly("compoundId", &std::pair::first) - .def_readonly("amount", &std::pair::second) +void BioProcessRegistry::luaBindings( + sol::state &lua +){ + lua.new_usertype("BioProcessRegistry", + + "new", sol::no_constructor, + + "loadFromXML", &BioProcessRegistry::loadFromXML, + "loadFromLua", &BioProcessRegistry::loadFromLua, + "getDisplayName", &BioProcessRegistry::getDisplayName, + "getInternalName", &BioProcessRegistry::getInternalName, + "getId", &BioProcessRegistry::getId, + + "getList", [](sol::this_state s){ + + THRIVE_BIND_ITERATOR_TO_TABLE(BioProcessRegistry::getList()); + }, + + "getInputCompounds", &BioProcessRegistry::getInputCompounds, + "getOutputCompounds", &BioProcessRegistry::getOutputCompounds ); + + // class_>("RecipyCompound") + // .def_readonly("compoundId", &std::pair::first) + // .def_readonly("amount", &std::pair::second) } namespace { @@ -110,7 +112,7 @@ BioProcessRegistry::loadFromXML( } int energyCost; if (pProcess->QueryIntAttribute("energyCost", &energyCost) != TIXML_SUCCESS){ - throw std::logic_error("Could not access 'speedFactor' attribute on Process element of " + filename); + throw std::logic_error("Could not access 'energyCost' attribute on Process element of " + filename); } const char* processName = pProcess->Attribute("name"); if (processName == nullptr) { @@ -132,28 +134,37 @@ BioProcessRegistry::loadFromXML( void BioProcessRegistry::loadFromLua( - const luabind::object& processTable + sol::table processTable ) { - for (luabind::iterator i(processTable), end; i != end; ++i) { - std::string key = luabind::object_cast(i.key()); - luabind::object data = *i; + + for(const auto& pair : processTable){ + + const auto key = pair.first.as(); + + if(!pair.second.is()) + throw std::runtime_error("BioProcessRegistry value is not a table"); + + auto data = pair.second.as(); + + sol::table inputTable = data.get("inputs"); + sol::table outputTable = data.get("outputs"); - luabind::object inputTable = data["inputs"]; - luabind::object outputTable = data["outputs"]; std::vector> inputs; std::vector> outputs; - for (luabind::iterator ii(inputTable), end; ii != end; ++ii) { - std::string compound = luabind::object_cast(ii.key()); - float amount = luabind::object_cast(*ii); - inputs.push_back({CompoundRegistry::getCompoundId(compound), amount}); + for(const auto& inputsPair : inputTable){ + + const auto compound = inputsPair.first.as(); + const auto amount = inputsPair.second.as(); + inputs.push_back({CompoundRegistry::getCompoundId(compound), amount}); } - for (luabind::iterator oi(outputTable), end; oi != end; ++oi) { - std::string compound = luabind::object_cast(oi.key()); - float amount = luabind::object_cast(*oi); - outputs.push_back({CompoundRegistry::getCompoundId(compound), amount}); + for(const auto& outputsPair : outputTable){ + + const auto compound = outputsPair.first.as(); + const auto amount = outputsPair.second.as(); + outputs.push_back({CompoundRegistry::getCompoundId(compound), amount}); } registerBioProcess( diff --git a/src/microbe_stage/bio_process_registry.h b/src/microbe_stage/bio_process_registry.h index 861aae23ba2..a1605fe2044 100644 --- a/src/microbe_stage/bio_process_registry.h +++ b/src/microbe_stage/bio_process_registry.h @@ -1,16 +1,12 @@ #pragma once -#include "scripting/luabind.h" #include "engine/typedefs.h" #include #include #include -namespace luabind { -class scope; -} - +#include "scripting/luajit.h" namespace thrive { @@ -39,8 +35,7 @@ class BioProcessRegistry { * - BioProcessRegistry::getOutputCompounds * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); static void loadFromXML( @@ -49,7 +44,7 @@ class BioProcessRegistry { static void loadFromLua( - const luabind::object& processTable + sol::table processTable ); /** diff --git a/src/microbe_stage/compound.cpp b/src/microbe_stage/compound.cpp index 24bdbd07664..c22fc778710 100644 --- a/src/microbe_stage/compound.cpp +++ b/src/microbe_stage/compound.cpp @@ -12,12 +12,11 @@ #include "game.h" #include "general/timed_life_system.h" #include "ogre/scene_node_system.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include "util/make_unique.h" #include "tinyxml.h" -#include #include #include #include @@ -27,25 +26,23 @@ using namespace thrive; REGISTER_COMPONENT(CompoundComponent) - -luabind::scope -CompoundComponent::luaBindings() { - using namespace luabind; - return class_("CompoundComponent") - .enum_("ID") [ - value("TYPE_ID", CompoundComponent::TYPE_ID) - ] - .scope [ - def("TYPE_NAME", &CompoundComponent::TYPE_NAME) - ] - .def(constructor<>()) - .def_readwrite("compoundId", &CompoundComponent::m_compoundId) - .def_readwrite("potency", &CompoundComponent::m_potency) - .def_readwrite("velocity", &CompoundComponent::m_velocity) - ; +void CompoundComponent::luaBindings( + sol::state &lua +){ + lua.new_usertype("CompoundComponent", + + "new", sol::factories([](){ + return std::make_unique(); + }), + + COMPONENT_BINDINGS(CompoundComponent), + + "compoundId", &CompoundComponent::m_compoundId, + "potency", &CompoundComponent::m_potency, + "velocity", &CompoundComponent::m_velocity + ); } - void CompoundComponent::load( const StorageContainer& storage @@ -71,12 +68,17 @@ CompoundComponent::storage() const { // CompoundMovementSystem //////////////////////////////////////////////////////////////////////////////// -luabind::scope -CompoundMovementSystem::luaBindings() { - using namespace luabind; - return class_("CompoundMovementSystem") - .def(constructor<>()) - ; +void CompoundMovementSystem::luaBindings( + sol::state &lua +){ + lua.new_usertype("CompoundMovementSystem", + + sol::constructors>(), + + sol::base_classes, sol::bases(), + + "init", &CompoundMovementSystem::init + ); } @@ -100,10 +102,10 @@ CompoundMovementSystem::~CompoundMovementSystem() {} void CompoundMovementSystem::init( - GameState* gameState + GameStateData* gameState ) { System::initNamed("CompoundMovementSystem", gameState); - m_impl->m_entities.setEntityManager(&gameState->entityManager()); + m_impl->m_entities.setEntityManager(gameState->entityManager()); } diff --git a/src/microbe_stage/compound.h b/src/microbe_stage/compound.h index 19759babc46..83e1e463cb3 100644 --- a/src/microbe_stage/compound.h +++ b/src/microbe_stage/compound.h @@ -5,18 +5,16 @@ #include "engine/component.h" #include "engine/system.h" #include "engine/touchable.h" -#include "scripting/luabind.h" #include "engine/typedefs.h" -#include #include #include #include #include #include -namespace luabind { -class scope; +namespace sol { +class state; } @@ -50,8 +48,7 @@ class CompoundComponent : public Component { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief The compound id @@ -94,8 +91,7 @@ class CompoundMovementSystem : public System { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -111,7 +107,7 @@ class CompoundMovementSystem : public System { * @brief Initializes the system * */ - void init(GameState* gameState) override; + void init(GameStateData* gameState) override; /** * @brief Shuts the system down diff --git a/src/microbe_stage/compound_absorber_system.cpp b/src/microbe_stage/compound_absorber_system.cpp index 469c0b3da2a..cfcb8e66989 100644 --- a/src/microbe_stage/compound_absorber_system.cpp +++ b/src/microbe_stage/compound_absorber_system.cpp @@ -13,14 +13,13 @@ #include "engine/serialization.h" #include "game.h" #include "ogre/scene_node_system.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include "util/make_unique.h" #include "microbe_stage/compound.h" #include "microbe_stage/compound_registry.h" #include "tinyxml.h" -#include #include #include #include @@ -33,25 +32,30 @@ using namespace thrive; // CompoundAbsorberComponent //////////////////////////////////////////////////////////////////////////////// -luabind::scope -CompoundAbsorberComponent::luaBindings() { - using namespace luabind; - return class_("CompoundAbsorberComponent") - .enum_("ID") [ - value("TYPE_ID", CompoundAbsorberComponent::TYPE_ID) - ] - .scope [ - def("TYPE_NAME", &CompoundAbsorberComponent::TYPE_NAME) - ] - .def(constructor<>()) - .def("absorbedCompoundAmount", &CompoundAbsorberComponent::absorbedCompoundAmount) - .def("getAbsorbedCompounds", &CompoundAbsorberComponent::getAbsorbedCompounds, return_stl_iterator) - .def("setAbsorbedCompoundAmount", &CompoundAbsorberComponent::setAbsorbedCompoundAmount) - .def("setCanAbsorbCompound", &CompoundAbsorberComponent::setCanAbsorbCompound) - .def("setAbsorbtionCapacity", &CompoundAbsorberComponent::setAbsorbtionCapacity) - .def("enable", &CompoundAbsorberComponent::enable) - .def("disable", &CompoundAbsorberComponent::disable) - ; +void CompoundAbsorberComponent::luaBindings( + sol::state &lua +){ + lua.new_usertype("CompoundAbsorberComponent", + + "new", sol::factories([](){ + return std::make_unique(); + }), + + COMPONENT_BINDINGS(CompoundAbsorberComponent), + + "absorbedCompoundAmount", &CompoundAbsorberComponent::absorbedCompoundAmount, + + "getAbsorbedCompounds", [](CompoundAbsorberComponent& us, sol::this_state s){ + + THRIVE_BIND_ITERATOR_TO_TABLE(us.getAbsorbedCompounds()); + }, + + "setAbsorbedCompoundAmount", &CompoundAbsorberComponent::setAbsorbedCompoundAmount, + "setCanAbsorbCompound", &CompoundAbsorberComponent::setCanAbsorbCompound, + "setAbsorbtionCapacity", &CompoundAbsorberComponent::setAbsorbtionCapacity, + "enable", &CompoundAbsorberComponent::enable, + "disable", &CompoundAbsorberComponent::disable + ); } @@ -159,13 +163,17 @@ REGISTER_COMPONENT(CompoundAbsorberComponent) //////////////////////////////////////////////////////////////////////////////// // CompoundAbsorberSystem //////////////////////////////////////////////////////////////////////////////// +void CompoundAbsorberSystem::luaBindings( + sol::state &lua +){ + lua.new_usertype("CompoundAbsorberSystem", -luabind::scope -CompoundAbsorberSystem::luaBindings() { - using namespace luabind; - return class_("CompoundAbsorberSystem") - .def(constructor<>()) - ; + sol::constructors>(), + + sol::base_classes, sol::bases(), + + "init", &CompoundAbsorberSystem::init + ); } struct CompoundAbsorberSystem::Implementation { @@ -205,12 +213,12 @@ CompoundAbsorberSystem::~CompoundAbsorberSystem() {} void CompoundAbsorberSystem::init( - GameState* gameState + GameStateData* gameState ) { System::initNamed("CompoundAbsorberSystem", gameState); - m_impl->m_compounds.setEntityManager(&gameState->entityManager()); - m_impl->m_agents.setEntityManager(&gameState->entityManager()); - m_impl->m_absorbers.setEntityManager(&gameState->entityManager()); + m_impl->m_compounds.setEntityManager(gameState->entityManager()); + m_impl->m_agents.setEntityManager(gameState->entityManager()); + m_impl->m_absorbers.setEntityManager(gameState->entityManager()); m_impl->m_sceneManager = gameState->sceneManager(); } diff --git a/src/microbe_stage/compound_absorber_system.h b/src/microbe_stage/compound_absorber_system.h index 5b156bce500..3ce4a51b8f6 100644 --- a/src/microbe_stage/compound_absorber_system.h +++ b/src/microbe_stage/compound_absorber_system.h @@ -5,10 +5,8 @@ #include "engine/component.h" #include "engine/system.h" #include "engine/touchable.h" -#include "scripting/luabind.h" #include "engine/typedefs.h" -#include #include #include #include @@ -42,8 +40,7 @@ class CompoundAbsorberComponent : public Component { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief The compounds absorbed in the last time step @@ -174,8 +171,7 @@ class CompoundAbsorberSystem : public System { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -192,7 +188,7 @@ class CompoundAbsorberSystem : public System { * * @param gameState */ - void init(GameState* gameState) override; + void init(GameStateData* gameState) override; /** * @brief Shuts the system down diff --git a/src/microbe_stage/compound_cloud_system.cpp b/src/microbe_stage/compound_cloud_system.cpp index c7432d3af80..7c61a07c6f1 100644 --- a/src/microbe_stage/compound_cloud_system.cpp +++ b/src/microbe_stage/compound_cloud_system.cpp @@ -12,7 +12,7 @@ #include "engine/serialization.h" #include "game.h" #include "ogre/scene_node_system.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include "util/make_unique.h" #include @@ -36,24 +36,23 @@ using namespace thrive; //////////////////////////////////////////////////////////////////////////////// // CompoundCloudComponent //////////////////////////////////////////////////////////////////////////////// - -luabind::scope -CompoundCloudComponent::luaBindings() { - using namespace luabind; - return class_("CompoundCloudComponent") - .enum_("ID") [ - value("TYPE_ID", CompoundCloudComponent::TYPE_ID) - ] - .scope [ - def("TYPE_NAME", &CompoundCloudComponent::TYPE_NAME) - ] - .def(constructor<>()) - .def("initialize", &CompoundCloudComponent::initialize) - .def("addCloud", &CompoundCloudComponent::addCloud) - .def_readonly("width", &CompoundCloudComponent::width) - .def_readonly("height", &CompoundCloudComponent::height) - .def_readonly("gridSize", &CompoundCloudComponent::gridSize) - ; +void CompoundCloudComponent::luaBindings( + sol::state &lua +){ + lua.new_usertype("CompoundCloudComponent", + + "new", sol::factories([](){ + return std::make_unique(); + }), + + COMPONENT_BINDINGS(CompoundCloudComponent), + + "initialize", &CompoundCloudComponent::initialize, + "addCloud", &CompoundCloudComponent::addCloud, + "width", sol::readonly(&CompoundCloudComponent::width), + "height", sol::readonly(&CompoundCloudComponent::height), + "gridSize", sol::readonly(&CompoundCloudComponent::gridSize) + ); } void @@ -145,15 +144,18 @@ REGISTER_COMPONENT(CompoundCloudComponent) //////////////////////////////////////////////////////////////////////////////// // CompoundCloudSystem //////////////////////////////////////////////////////////////////////////////// + void CompoundCloudSystem::luaBindings( + sol::state &lua +){ + lua.new_usertype("CompoundCloudSystem", -luabind::scope -CompoundCloudSystem::luaBindings() { - using namespace luabind; - return class_("CompoundCloudSystem") - .def(constructor<>()) - ; -} + sol::constructors>(), + + sol::base_classes, sol::bases(), + "init", &CompoundCloudSystem::init + ); +} struct CompoundCloudSystem::Implementation { // All entities that have a compoundCloudsComponent. @@ -188,18 +190,23 @@ CompoundCloudSystem::~CompoundCloudSystem() { void CompoundCloudSystem::init( - GameState* gameState + GameStateData* gameState ) { System::initNamed("CompoundCloudSystem", gameState); - m_impl->m_compounds.setEntityManager(&gameState->entityManager()); + m_impl->m_compounds.setEntityManager(gameState->entityManager()); m_impl->m_sceneManager = gameState->sceneManager(); this->gameState = gameState; // Create a background plane on which the fluid clouds will be drawn. Ogre::Plane plane(Ogre::Vector3::UNIT_Z, -1.0); - Ogre::MeshManager::getSingleton().createPlane("CompoundCloudsPlane", "General", plane, width*gridSize, height*gridSize, 1, 1, true, 1, 1, 1, Ogre::Vector3::UNIT_Y); - compoundCloudsPlane = m_impl->m_sceneManager->createEntity("CompoundCloudsPlane", "General"); - m_impl->m_sceneManager->getRootSceneNode()->createChildSceneNode()->attachObject(compoundCloudsPlane); + Ogre::MeshManager::getSingleton().createPlane("CompoundCloudsPlane", "General", + plane, width*gridSize, height*gridSize, 1, 1, true, 1, 1, 1, Ogre::Vector3::UNIT_Y); + + compoundCloudsPlane = m_impl->m_sceneManager->createEntity("CompoundCloudsPlane", + "General"); + m_impl->m_sceneManager->getRootSceneNode()->createChildSceneNode()->attachObject( + compoundCloudsPlane); + compoundCloudsPlane->setMaterialName("CompoundClouds"); } @@ -215,11 +222,9 @@ CompoundCloudSystem::shutdown() { void CompoundCloudSystem::update(int renderTime, int) { -//auto start = std::chrono::high_resolution_clock::now(); - // Get the player's position. - playerNode = static_cast(gameState->entityManager().getComponent( - Entity(gameState->engine().playerData().playerName(), gameState).id(), + playerNode = static_cast(gameState->entityManager()->getComponent( + Entity(Game::instance().engine().playerData().playerName(), gameState).id(), OgreSceneNodeComponent::TYPE_ID)); @@ -229,10 +234,14 @@ CompoundCloudSystem::update(int renderTime, int) { playerNode->m_transform.position.x < offsetX - width/3*gridSize/2 || playerNode->m_transform.position.y < offsetY - height/3*gridSize/2) { - if (playerNode->m_transform.position.x > offsetX + width/3*gridSize/2 ) offsetX += width/3*gridSize; - if (playerNode->m_transform.position.y > offsetY + height/3*gridSize/2) offsetY += height/3*gridSize; - if (playerNode->m_transform.position.x < offsetX - width/3*gridSize/2 ) offsetX -= width/3*gridSize; - if (playerNode->m_transform.position.y < offsetY - height/3*gridSize/2) offsetY -= height/3*gridSize; + if (playerNode->m_transform.position.x > offsetX + width/3*gridSize/2 ) + offsetX += width/3*gridSize; + if (playerNode->m_transform.position.y > offsetY + height/3*gridSize/2) + offsetY += height/3*gridSize; + if (playerNode->m_transform.position.x < offsetX - width/3*gridSize/2 ) + offsetX -= width/3*gridSize; + if (playerNode->m_transform.position.y < offsetY - height/3*gridSize/2) + offsetY -= height/3*gridSize; compoundCloudsPlane->getParentSceneNode()->setPosition(offsetX, offsetY, -1.0); } @@ -252,19 +261,27 @@ CompoundCloudSystem::update(int renderTime, int) { compoundCloud->oldDens.resize(width, std::vector(height, 0)); // Modifies the material to draw this compound cloud in addition to the others. - Ogre::MaterialPtr materialPtr = Ogre::MaterialManager::getSingleton().getByName("CompoundClouds", "General"); + Ogre::MaterialPtr materialPtr = Ogre::MaterialManager::getSingleton().getByName( + "CompoundClouds", "General"); + Ogre::Pass* pass = materialPtr->getTechnique(0)->createPass(); + pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA); pass->setVertexProgram("CompoundCloud_VS"); pass->setFragmentProgram("CompoundCloud_PS"); - //Ogre::TexturePtr texturePtr = Ogre::TextureManager::getSingleton().load(compoundCloud->compound + ".bmp", "General"); - Ogre::TexturePtr texturePtr = Ogre::TextureManager::getSingleton().createManual(CompoundRegistry::getCompoundInternalName(compoundCloud->m_compoundId), "General", Ogre::TEX_TYPE_2D, width, height, - 0, Ogre::PF_BYTE_BGRA, Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE); + + Ogre::TexturePtr texturePtr = Ogre::TextureManager::getSingleton().createManual( + CompoundRegistry::getCompoundInternalName(compoundCloud->m_compoundId), + "General", Ogre::TEX_TYPE_2D, width, height, + 0, Ogre::PF_BYTE_BGRA, Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE); + Ogre::HardwarePixelBufferSharedPtr cloud; cloud = texturePtr->getBuffer(); cloud->lock(Ogre::HardwareBuffer::HBL_DISCARD); const Ogre::PixelBox& pixelBox = cloud->getCurrentLock(); + uint8_t* pDest = static_cast(pixelBox.data); + // Fill in some pixel data. This will give a semi-transparent blue, // but this is of course dependent on the chosen pixel format. for (int i = 0; i < width; i++) @@ -281,13 +298,15 @@ CompoundCloudSystem::update(int renderTime, int) { } // Unlock the pixel buffer cloud->unlock(); - pass->createTextureUnitState(CompoundRegistry::getCompoundInternalName(compoundCloud->m_compoundId)); + pass->createTextureUnitState()->setTexture(texturePtr); texturePtr = Ogre::TextureManager::getSingleton().load("PerlinNoise.jpg", "General"); pass->createTextureUnitState()->setTexture(texturePtr); - compoundCloudsPlane->getSubEntity(0)->setCustomParameter(1, Ogre::Vector4(0.0f, 0.0f, 0.0f, 0.0f)); + compoundCloudsPlane->getSubEntity(0)->setCustomParameter(1, + Ogre::Vector4(0.0f, 0.0f, 0.0f, 0.0f)); } + // Clear the list of newly added entities so that we don't reinitialize them next frame. m_impl->m_compounds.clearChanges(); @@ -307,12 +326,14 @@ CompoundCloudSystem::update(int renderTime, int) { for (int y = 0; y < height/3; y++) { compoundCloud->density[x][y] = compoundCloud->density[x][y+height/3]; - compoundCloud->density[x][y+height/3] = compoundCloud->density[x][y+height*2/3]; + compoundCloud->density[x][y+height/3] = + compoundCloud->density[x][y+height*2/3]; compoundCloud->density[x][y+height*2/3] = 0.0; } } Ogre::Vector4 offset = compoundCloudsPlane->getSubEntity(0)->getCustomParameter(1); - compoundCloudsPlane->getSubEntity(0)->setCustomParameter(1, Ogre::Vector4(offset.x, offset.y-1.0f/3, 0.0f, 0.0f)); + compoundCloudsPlane->getSubEntity(0)->setCustomParameter(1, + Ogre::Vector4(offset.x, offset.y-1.0f/3, 0.0f, 0.0f)); } // If we moved right. else if (compoundCloud->offsetX < offsetX && compoundCloud->offsetY == offsetY) @@ -322,12 +343,14 @@ CompoundCloudSystem::update(int renderTime, int) { for (int y = 0; y < height; y++) { compoundCloud->density[x][y] = compoundCloud->density[x+height/3][y]; - compoundCloud->density[x+height/3][y] = compoundCloud->density[x+height*2/3][y]; + compoundCloud->density[x+height/3][y] = + compoundCloud->density[x+height*2/3][y]; compoundCloud->density[x+height*2/3][y] = 0.0; } } Ogre::Vector4 offset = compoundCloudsPlane->getSubEntity(0)->getCustomParameter(1); - compoundCloudsPlane->getSubEntity(0)->setCustomParameter(1, Ogre::Vector4(offset.x-1.0f/3, offset.y, 0.0f, 0.0f)); + compoundCloudsPlane->getSubEntity(0)->setCustomParameter(1, + Ogre::Vector4(offset.x-1.0f/3, offset.y, 0.0f, 0.0f)); } // If we moved left. else if (compoundCloud->offsetX > offsetX && compoundCloud->offsetY == offsetY) @@ -336,13 +359,15 @@ CompoundCloudSystem::update(int renderTime, int) { { for (int y = 0; y < height; y++) { - compoundCloud->density[x+height*2/3][y] = compoundCloud->density[x+height/3][y]; + compoundCloud->density[x+height*2/3][y] = + compoundCloud->density[x+height/3][y]; compoundCloud->density[x+height/3][y] = compoundCloud->density[x][y]; compoundCloud->density[x][y] = 0.0; } } Ogre::Vector4 offset = compoundCloudsPlane->getSubEntity(0)->getCustomParameter(1); - compoundCloudsPlane->getSubEntity(0)->setCustomParameter(1, Ogre::Vector4(offset.x+1.0f/3, offset.y, 0.0f, 0.0f)); + compoundCloudsPlane->getSubEntity(0)->setCustomParameter(1, + Ogre::Vector4(offset.x+1.0f/3, offset.y, 0.0f, 0.0f)); } // If we moved downwards. else if (compoundCloud->offsetX == offsetX && compoundCloud->offsetY > offsetY) @@ -351,17 +376,21 @@ CompoundCloudSystem::update(int renderTime, int) { { for (int y = 0; y < height/3; y++) { - compoundCloud->density[x][y+height*2/3] = compoundCloud->density[x][y+height/3]; + compoundCloud->density[x][y+height*2/3] = + compoundCloud->density[x][y+height/3]; compoundCloud->density[x][y+height/3] = compoundCloud->density[x][y]; compoundCloud->density[x][y] = 0.0; } } Ogre::Vector4 offset = compoundCloudsPlane->getSubEntity(0)->getCustomParameter(1); - compoundCloudsPlane->getSubEntity(0)->setCustomParameter(1, Ogre::Vector4(offset.x, offset.y+1.0f/3, 0.0f, 0.0f)); + compoundCloudsPlane->getSubEntity(0)->setCustomParameter(1, + Ogre::Vector4(offset.x, offset.y+1.0f/3, 0.0f, 0.0f)); } + compoundCloud->offsetX = offsetX; compoundCloud->offsetY = offsetY; } + // Compound clouds move from area of high concentration to area of low. diffuse(.01, compoundCloud->oldDens, compoundCloud->density, renderTime); // Move the compound clouds about the velocity field. @@ -369,7 +398,10 @@ CompoundCloudSystem::update(int renderTime, int) { // Store the pixel data in a hardware buffer for quick access. Ogre::HardwarePixelBufferSharedPtr cloud; - cloud = Ogre::TextureManager::getSingleton().getByName(CompoundRegistry::getCompoundInternalName(compoundCloud->m_compoundId), "General")->getBuffer(); + cloud = Ogre::TextureManager::getSingleton().getByName( + CompoundRegistry::getCompoundInternalName(compoundCloud->m_compoundId), + "General")->getBuffer(); + cloud->lock(Ogre::HardwareBuffer::HBL_DISCARD); const Ogre::PixelBox& pixelBox = cloud->getCurrentLock(); uint8_t* pDest = static_cast(pixelBox.data); @@ -395,14 +427,10 @@ CompoundCloudSystem::update(int renderTime, int) { } pDest += pixelBox.getRowSkip() * Ogre::PixelUtil::getNumElemBytes(pixelBox.format); } + // Unlock the pixel buffer. cloud->unlock(); } - - -//auto end = std::chrono::high_resolution_clock::now(); - -//std::cout << "total: " << std::to_string(std::chrono::duration_cast(end-start).count()) << std::endl; } void @@ -434,7 +462,9 @@ CompoundCloudSystem::CreateVelocityField() { } void -CompoundCloudSystem::diffuse(float diffRate, std::vector< std::vector >& oldDens, const std::vector< std::vector >& density, int dt) { +CompoundCloudSystem::diffuse(float diffRate, std::vector< std::vector >& oldDens, + const std::vector< std::vector >& density, int dt) +{ dt = 1; float a = dt*diffRate; @@ -449,7 +479,9 @@ CompoundCloudSystem::diffuse(float diffRate, std::vector< std::vector > } void -CompoundCloudSystem::advect(std::vector< std::vector >& oldDens, std::vector< std::vector >& density, int dt) { +CompoundCloudSystem::advect(std::vector< std::vector >& oldDens, + std::vector< std::vector >& density, int dt) +{ dt = 1; for (int x = 0; x < width; x++) diff --git a/src/microbe_stage/compound_cloud_system.h b/src/microbe_stage/compound_cloud_system.h index 1c908344e08..92e9e8cea68 100644 --- a/src/microbe_stage/compound_cloud_system.h +++ b/src/microbe_stage/compound_cloud_system.h @@ -8,7 +8,6 @@ #include "engine/component.h" #include "engine/system.h" #include "engine/touchable.h" -#include "scripting/luabind.h" #include "engine/typedefs.h" #include "general/perlin_noise.h" @@ -65,8 +64,7 @@ class CompoundCloudComponent : public Component { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); void load( @@ -116,8 +114,7 @@ class CompoundCloudSystem : public System { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -134,7 +131,7 @@ class CompoundCloudSystem : public System { * * @param gameState */ - void init(GameState* gameState) override; + void init(GameStateData* gameState) override; /** * @brief Shuts the system down @@ -149,7 +146,8 @@ class CompoundCloudSystem : public System { private: struct Implementation; std::unique_ptr m_impl; - GameState* gameState; + //! \todo Remove this. This is in the base class already + GameStateData* gameState; Ogre::Entity* compoundCloudsPlane; OgreSceneNodeComponent* playerNode; diff --git a/src/microbe_stage/compound_emitter_system.cpp b/src/microbe_stage/compound_emitter_system.cpp index 7e3e11e3636..0aaa2ee6469 100644 --- a/src/microbe_stage/compound_emitter_system.cpp +++ b/src/microbe_stage/compound_emitter_system.cpp @@ -11,12 +11,11 @@ #include "game.h" #include "general/timed_life_system.h" #include "ogre/scene_node_system.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include "util/make_unique.h" #include "microbe_stage/compound.h" #include "microbe_stage/compound_registry.h" -#include #include #include #include @@ -26,29 +25,27 @@ using namespace thrive; //////////////////////////////////////////////////////////////////////////////// // CompoundEmitterComponent //////////////////////////////////////////////////////////////////////////////// - -luabind::scope -CompoundEmitterComponent::luaBindings() { - using namespace luabind; - return class_("CompoundEmitterComponent") - .enum_("ID") [ - value("TYPE_ID", CompoundEmitterComponent::TYPE_ID) - ] - .scope [ - def("TYPE_NAME", &CompoundEmitterComponent::TYPE_NAME) - ] - .def(constructor<>()) - .def("emitCompound", &CompoundEmitterComponent::emitCompound) - .def_readwrite("emissionRadius", &CompoundEmitterComponent::m_emissionRadius) - .def_readwrite("maxInitialSpeed", &CompoundEmitterComponent::m_maxInitialSpeed) - .def_readwrite("minInitialSpeed", &CompoundEmitterComponent::m_minInitialSpeed) - .def_readwrite("minEmissionAngle", &CompoundEmitterComponent::m_minEmissionAngle) - .def_readwrite("maxEmissionAngle", &CompoundEmitterComponent::m_maxEmissionAngle) - .def_readwrite("particleLifetime", &CompoundEmitterComponent::m_particleLifetime) - ; +void CompoundEmitterComponent::luaBindings( + sol::state &lua +){ + lua.new_usertype("CompoundEmitterComponent", + + "new", sol::factories([](){ + return std::make_unique(); + }), + + COMPONENT_BINDINGS(CompoundEmitterComponent), + + "emitCompound", &CompoundEmitterComponent::emitCompound, + "emissionRadius", &CompoundEmitterComponent::m_emissionRadius, + "maxInitialSpeed", &CompoundEmitterComponent::m_maxInitialSpeed, + "minInitialSpeed", &CompoundEmitterComponent::m_minInitialSpeed, + "minEmissionAngle", &CompoundEmitterComponent::m_minEmissionAngle, + "maxEmissionAngle", &CompoundEmitterComponent::m_maxEmissionAngle, + "particleLifetime", &CompoundEmitterComponent::m_particleLifetime + ); } - void CompoundEmitterComponent::emitCompound( CompoundId compoundId, @@ -93,25 +90,24 @@ REGISTER_COMPONENT(CompoundEmitterComponent) // TimedCompoundEmitterComponent //////////////////////////////////////////////////////////////////////////////// -luabind::scope -TimedCompoundEmitterComponent::luaBindings() { - using namespace luabind; - return class_("TimedCompoundEmitterComponent") - .enum_("ID") [ - value("TYPE_ID", TimedCompoundEmitterComponent::TYPE_ID) - ] - .scope [ - def("TYPE_NAME", &TimedCompoundEmitterComponent::TYPE_NAME) - ] - .def(constructor<>()) - .def_readwrite("emitInterval", &TimedCompoundEmitterComponent::m_emitInterval) - .def_readwrite("compoundId", &TimedCompoundEmitterComponent::m_compoundId) - .def_readwrite("particlesPerEmission", &TimedCompoundEmitterComponent::m_particlesPerEmission) - .def_readwrite("potencyPerParticle", &TimedCompoundEmitterComponent::m_potencyPerParticle) - ; + void TimedCompoundEmitterComponent::luaBindings( + sol::state &lua +){ + lua.new_usertype("TimedCompoundEmitterComponent", + + "new", sol::factories([](){ + return std::make_unique(); + }), + + COMPONENT_BINDINGS(TimedCompoundEmitterComponent), + + "emitInterval", &TimedCompoundEmitterComponent::m_emitInterval, + "compoundId", &TimedCompoundEmitterComponent::m_compoundId, + "particlesPerEmission", &TimedCompoundEmitterComponent::m_particlesPerEmission, + "potencyPerParticle", &TimedCompoundEmitterComponent::m_potencyPerParticle + ); } - void TimedCompoundEmitterComponent::load( const StorageContainer& storage @@ -142,15 +138,18 @@ REGISTER_COMPONENT(TimedCompoundEmitterComponent) //////////////////////////////////////////////////////////////////////////////// // CompoundEmitterSystem //////////////////////////////////////////////////////////////////////////////// +void CompoundEmitterSystem::luaBindings( + sol::state &lua +){ + lua.new_usertype("CompoundEmitterSystem", -luabind::scope -CompoundEmitterSystem::luaBindings() { - using namespace luabind; - return class_("CompoundEmitterSystem") - .def(constructor<>()) - ; -} + sol::constructors>(), + + sol::base_classes, sol::bases(), + "init", &CompoundEmitterSystem::init + ); +} struct CompoundEmitterSystem::Implementation { @@ -175,10 +174,10 @@ CompoundEmitterSystem::~CompoundEmitterSystem() {} void CompoundEmitterSystem::init( - GameState* gameState + GameStateData* gameState ) { System::initNamed("CompoundEmitterSystem", gameState); - m_impl->m_entities.setEntityManager(&gameState->entityManager()); + m_impl->m_entities.setEntityManager(gameState->entityManager()); m_impl->m_sceneManager = gameState->sceneManager(); } @@ -199,7 +198,8 @@ emitCompound( double angle, double radius, CompoundEmitterComponent* emitterComponent, - EntityId emittingEntityId + EntityId emittingEntityId, + GameStateData* currentState ) { Ogre::Vector3 emissionOffset(0,0,0); @@ -221,7 +221,7 @@ emitCompound( radius * Ogre::Math::Cos(emissionAngle), 0.0 ); - EntityId compoundEntityId = Game::instance().engine().currentGameState()->entityManager().generateNewId(); + EntityId compoundEntityId = currentState->entityManager()->generateNewId(); // Scene Node auto compoundSceneNodeComponent = make_unique(); auto meshScale = CompoundRegistry::getCompoundMeshScale(compoundId); @@ -255,7 +255,7 @@ emitCompound( components.emplace_back(std::move(compoundRigidBodyComponent)); components.emplace_back(std::move(collisionHandler)); for (auto& component : components) { - Game::instance().engine().currentGameState()->entityManager().addComponent( + currentState->entityManager()->addComponent( compoundEntityId, std::move(component) ); @@ -273,7 +273,9 @@ CompoundEmitterSystem::update(int, int logicTime) { for (auto emission : emitterComponent->m_compoundEmissions) { - emitCompound(std::get<0>(emission), std::get<1>(emission), sceneNodeComponent->m_transform.position, std::get<2>(emission), std::get<3>(emission), emitterComponent, value.first); + emitCompound(std::get<0>(emission), std::get<1>(emission), + sceneNodeComponent->m_transform.position, std::get<2>(emission), + std::get<3>(emission), emitterComponent, value.first, gameState()); } emitterComponent->m_compoundEmissions.clear(); if (timedEmitterComponent) @@ -289,7 +291,11 @@ CompoundEmitterSystem::update(int, int logicTime) { emitterComponent->m_minEmissionAngle.valueDegrees(), emitterComponent->m_maxEmissionAngle.valueDegrees() ); - emitCompound(timedEmitterComponent->m_compoundId, timedEmitterComponent->m_potencyPerParticle, sceneNodeComponent->m_transform.position, angle, emitterComponent->m_emissionRadius, emitterComponent, value.first); + emitCompound(timedEmitterComponent->m_compoundId, + timedEmitterComponent->m_potencyPerParticle, + sceneNodeComponent->m_transform.position, angle, + emitterComponent->m_emissionRadius, emitterComponent, value.first, + gameState()); } } } diff --git a/src/microbe_stage/compound_emitter_system.h b/src/microbe_stage/compound_emitter_system.h index 615189c0f86..99621cfb0db 100644 --- a/src/microbe_stage/compound_emitter_system.h +++ b/src/microbe_stage/compound_emitter_system.h @@ -5,11 +5,9 @@ #include "engine/component.h" #include "engine/system.h" #include "engine/touchable.h" -#include "scripting/luabind.h" #include "engine/typedefs.h" #include "microbe_stage/compound.h" -#include #include #include #include @@ -44,8 +42,7 @@ class CompoundEmitterComponent : public Component { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief How far away the particles are spawned @@ -139,8 +136,7 @@ class TimedCompoundEmitterComponent : public Component { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief The compound id to emit @@ -193,8 +189,7 @@ class CompoundEmitterSystem : public System { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -211,7 +206,7 @@ class CompoundEmitterSystem : public System { * * @param gameState */ - void init(GameState* gameState) override; + void init(GameStateData* gameState) override; /** * @brief Shuts the system down diff --git a/src/microbe_stage/compound_registry.cpp b/src/microbe_stage/compound_registry.cpp index 9ecd72f3b58..d286a33cf88 100644 --- a/src/microbe_stage/compound_registry.cpp +++ b/src/microbe_stage/compound_registry.cpp @@ -8,50 +8,55 @@ #include "engine/serialization.h" #include "game.h" #include "ogre/scene_node_system.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include "util/make_unique.h" #include "microbe_stage/compound.h" #include "tinyxml.h" -#include #include #include #include using namespace thrive; -luabind::scope -CompoundRegistry::luaBindings() { - using namespace luabind; - return class_("CompoundRegistry") - .scope - [ - def("registerCompoundType", &CompoundRegistry::registerCompoundType), - def("registerAgentType", - static_cast(&CompoundRegistry::registerAgentType) - ), - def("loadFromXML", &CompoundRegistry::loadFromXML), - def("loadFromLua", &CompoundRegistry::loadFromLua), - def("loadAgentFromLua", &CompoundRegistry::loadAgentFromLua), - def("getCompoundDisplayName", &CompoundRegistry::getCompoundDisplayName), - def("getCompoundInternalName", &CompoundRegistry::getCompoundInternalName), - def("getCompoundMeshName", &CompoundRegistry::getCompoundMeshName), - def("getCompoundUnitVolume", &CompoundRegistry::getCompoundUnitVolume), - def("getCompoundId", &CompoundRegistry::getCompoundId), - def("getCompoundList", &CompoundRegistry::getCompoundList, return_stl_iterator), - def("getCompoundMeshScale", &CompoundRegistry::getCompoundMeshScale), - def("getAgentEffect", &CompoundRegistry::getAgentEffect) - ] - ; +void CompoundRegistry::luaBindings( + sol::state &lua +){ + lua.new_usertype("CompoundRegistry", + + "new", sol::no_constructor, + + "registerCompoundType", &CompoundRegistry::registerCompoundType, + "registerAgentType", + static_cast(&CompoundRegistry::registerAgentType), + + "loadFromXML", &CompoundRegistry::loadFromXML, + "loadFromLua", &CompoundRegistry::loadFromLua, + "loadAgentFromLua", &CompoundRegistry::loadAgentFromLua, + "getCompoundDisplayName", &CompoundRegistry::getCompoundDisplayName, + "getCompoundInternalName", &CompoundRegistry::getCompoundInternalName, + "getCompoundMeshName", &CompoundRegistry::getCompoundMeshName, + "getCompoundUnitVolume", &CompoundRegistry::getCompoundUnitVolume, + "getCompoundId", &CompoundRegistry::getCompoundId, + + // sol:: doesn't like boost wrapped iterators + "getCompoundList", [](sol::this_state s){ + + THRIVE_BIND_ITERATOR_TO_TABLE(CompoundRegistry::getCompoundList()); + }, + + "getCompoundMeshScale", &CompoundRegistry::getCompoundMeshScale, + "getAgentEffect", &CompoundRegistry::getAgentEffect + ); } @@ -82,17 +87,21 @@ compoundRegistryMap() { void CompoundRegistry::loadFromLua( - const luabind::object& compoundTable, - const luabind::object& agentTable + sol::table compoundTable, + sol::table agentTable ) { - for (luabind::iterator i(compoundTable), end; i != end; ++i) { - std::string key = luabind::object_cast(i.key()); - luabind::object data = *i; - std::string name = luabind::object_cast(data["name"]); - float weight = luabind::object_cast(data["weight"]); - std::string meshname = luabind::object_cast(data["mesh"]); - bool isUseful = luabind::object_cast(data["isUseful"]); - float size = luabind::object_cast(data["size"]); + + for(const auto& pair : compoundTable){ + + const auto key = pair.first.as(); + auto data = pair.second.as(); + + const auto name = data.get("name"); + const auto weight = data.get("weight"); + const auto meshname = data.get("mesh"); + const auto size = data.get("size"); + bool isUseful = data.get("isUseful"); + registerCompoundType( key, name, @@ -102,15 +111,19 @@ CompoundRegistry::loadFromLua( weight ); } - for (luabind::iterator i(agentTable), end; i != end; ++i) { - std::string key = luabind::object_cast(i.key()); - luabind::object data = *i; - std::string name = luabind::object_cast(data["name"]); - float weight = luabind::object_cast(data["weight"]); - std::string meshname = luabind::object_cast(data["mesh"]); - float size = luabind::object_cast(data["size"]); - // std::cerr << "before casting effect" << std::endl; - luabind::object effect = data["effect"]; + + for(const auto& pair : agentTable){ + + const auto key = pair.first.as(); + auto data = pair.second.as(); + + const auto name = data.get("name"); + const auto weight = data.get("weight"); + const auto meshname = data.get("mesh"); + const auto size = data.get("size"); + + sol::object effect = data["effect"]; + registerAgentType( key, name, @@ -122,71 +135,22 @@ CompoundRegistry::loadFromLua( ); } } -/*||=== Build: install in Thrive (compiler: GNU GCC Compiler) ===| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.cpp|121|error: no matching function for call to 'thrive::CompoundRegistry::registerAgentType( -std::string&, -std::string&, -std::string&, -float&, -bool, -float&, -luabind::adl::object&) - -static thrive::CompoundId thrive::CompoundRegistry::registerAgentType( -const string&, -const string&, -const string&, -double, int, -std::function*)| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.h|134|note: candidate expects 6 arguments, 7 provided| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.h|169|note: static thrive::CompoundId thrive::CompoundRegistry::registerAgentType(const string&, const string&, const string&, double, int, const luabind::adl::object&)| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.h|169|note: candidate expects 6 arguments, 7 provided| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.cpp|145|error: no matching function for call to 'thrive::CompoundRegistry::registerAgentType(std::string&, std::string&, std::string&, float&, bool, float&, luabind::adl::object&)'| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.cpp|145|note: candidates are:| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.h|134|note: static thrive::CompoundId thrive::CompoundRegistry::registerAgentType(const string&, const string&, const string&, double, int, std::function*)| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.h|134|note: candidate expects 6 arguments, 7 provided| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.h|169|note: static thrive::CompoundId thrive::CompoundRegistry::registerAgentType(const string&, const string&, const string&, double, int, const luabind::adl::object&)| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.h|169|note: candidate expects 6 arguments, 7 provided| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.cpp|254|error: no matching function for call to 'thrive::CompoundRegistry::registerAgentType(const char*&, const char*&, const char*&, double&, bool, int&, std::function*&)'| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.cpp|254|note: candidates are:| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.h|134|note: static thrive::CompoundId thrive::CompoundRegistry::registerAgentType(const string&, const string&, const string&, double, int, std::function*)| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.h|134|note: candidate expects 6 arguments, 7 provided| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.h|169|note: static thrive::CompoundId thrive::CompoundRegistry::registerAgentType(const string&, const string&, const string&, double, int, const luabind::adl::object&)| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.h|169|note: candidate expects 6 arguments, 7 provided| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.cpp|281|error: no matching function for call to 'thrive::CompoundRegistry::registerAgentType(const string&, const string&, const string&, double&, bool&, int&, std::function*)'| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.cpp|281|note: candidates are:| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.h|134|note: static thrive::CompoundId thrive::CompoundRegistry::registerAgentType(const string&, const string&, const string&, double, int, std::function*)| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.h|134|note: candidate expects 6 arguments, 7 provided| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.h|169|note: static thrive::CompoundId thrive::CompoundRegistry::registerAgentType(const string&, const string&, const string&, double, int, const luabind::adl::object&)| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.h|169|note: candidate expects 6 arguments, 7 provided| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.cpp|309|error: no matching function for call to 'thrive::CompoundRegistry::registerAgentType(const string&, const string&, const string&, double&, int&, bool, std::function*&)'| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.cpp|309|note: candidates are:| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.h|134|note: static thrive::CompoundId thrive::CompoundRegistry::registerAgentType(const string&, const string&, const string&, double, int, std::function*)| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.h|134|note: candidate expects 6 arguments, 7 provided| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.cpp|287|note: static thrive::CompoundId thrive::CompoundRegistry::registerAgentType(const string&, const string&, const string&, double, int, const luabind::adl::object&)| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.cpp|287|note: candidate expects 6 arguments, 7 provided| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.cpp|313|error: prototype for 'thrive::CompoundId thrive::CompoundRegistry::registerAgentType(const string&, const string&, const string&, double, bool, float, std::function*)' does not match any in class 'thrive::CompoundRegistry'| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.cpp|287|error: candidates are: static thrive::CompoundId thrive::CompoundRegistry::registerAgentType(const string&, const string&, const string&, double, int, const luabind::adl::object&)| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.h|134|error: static thrive::CompoundId thrive::CompoundRegistry::registerAgentType(const string&, const string&, const string&, double, int, std::function*)| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.cpp|282|error: control reaches end of non-void function [-Werror=return-type]| -C:\Users\User\Documents\GitHub\Thrive\Thrive\src\microbe_stage\compound_registry.cpp|310|error: control reaches end of non-void function [-Werror=return-type]| -CMakeFiles\ThriveLib.dir\build.make|962|recipe for target 'CMakeFiles/ThriveLib.dir/src/microbe_stage/compound_registry.cpp.obj' failed| -CMakeFiles\Makefile2|99|recipe for target 'CMakeFiles/ThriveLib.dir/all' failed| -C:\Users\User\Documents\GitHub\Thrive\Build\Makefile|126|recipe for target 'all' failed| -||=== Build failed: 13 error(s), 0 warning(s) (2 minute(s), 21 second(s)) ===| -*/ + void CompoundRegistry::loadAgentFromLua( - const luabind::object& internalName, - const luabind::object& data + sol::object internalName, + sol::table data ) { - std::string internal_name = luabind::object_cast(internalName); - std::string name = luabind::object_cast(data["name"]); - float weight = luabind::object_cast(data["weight"]); - std::string meshname = luabind::object_cast(data["mesh"]); - float size = luabind::object_cast(data["size"]); + + const auto internal_name = internalName.as(); + + const auto name = data.get("name"); + const auto weight = data.get("weight"); + const auto meshname = data.get("mesh"); + const auto size = data.get("size"); + // std::cerr << "before casting effect" << std::endl; - luabind::object effect = data["effect"]; + sol::object effect = data["effect"]; registerAgentType( internal_name, name, @@ -280,7 +244,8 @@ CompoundRegistry::loadFromXML( auto effectLambda = new std::function( [luaFunctionName](EntityId entityId, double potency) -> bool { - luabind::call_function(Game::instance().engine().luaState(), luaFunctionName.c_str(), entityId, potency); + sol::state_view(Game::instance().engine().luaState())[luaFunctionName]( + entityId, potency); return true; }); const char* name = pAgent->Attribute("name"); @@ -344,12 +309,12 @@ CompoundRegistry::registerAgentType( double meshScale, bool isUseful, float unitVolume, - const luabind::object& effect + sol::object effect ) { auto effectLambda = new std::function( [effect](EntityId entityId, double potency) -> bool { - luabind::call_function(effect, entityId, potency); + effect.as()(entityId, potency); return true; }); //Call overload diff --git a/src/microbe_stage/compound_registry.h b/src/microbe_stage/compound_registry.h index 8ac226f2776..3563e41a85f 100644 --- a/src/microbe_stage/compound_registry.h +++ b/src/microbe_stage/compound_registry.h @@ -5,10 +5,9 @@ #include "engine/component.h" #include "engine/system.h" #include "engine/touchable.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include "engine/typedefs.h" -#include #include #include #include @@ -45,8 +44,7 @@ class CompoundRegistry final { * - CompoundRegistry::getCompoundMeshScale * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Loads compounds from an XML document @@ -64,14 +62,14 @@ class CompoundRegistry final { */ static void loadFromLua( - const luabind::object& configTable, - const luabind::object& agentTable + sol::table configTable, + sol::table agentTable ); static void loadAgentFromLua( - const luabind::object& internalName, - const luabind::object& agentData + sol::object internalName, + sol::table agentData ); /** @@ -102,7 +100,7 @@ class CompoundRegistry final { const std::string& meshName, double meshScale, bool isUseful, - float unitVolume + float unitVolume ); /** @@ -174,7 +172,7 @@ class CompoundRegistry final { double meshScale, bool isUseful, float unitVolume, - const luabind::object& effect + sol::object effect ); /** diff --git a/src/microbe_stage/membrane_system.cpp b/src/microbe_stage/membrane_system.cpp index 0214d5da5be..efac01aefc1 100644 --- a/src/microbe_stage/membrane_system.cpp +++ b/src/microbe_stage/membrane_system.cpp @@ -9,7 +9,7 @@ #include "engine/serialization.h" #include "game.h" #include "ogre/scene_node_system.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include "util/make_unique.h" #include @@ -28,25 +28,25 @@ using namespace thrive; // Membrane Component //////////////////////////////////////////////////////////////////////////////// -luabind::scope -MembraneComponent::luaBindings() { - using namespace luabind; - return class_("MembraneComponent") - .enum_("ID") [ - value("TYPE_ID", MembraneComponent::TYPE_ID) - ] - .scope [ - def("TYPE_NAME", &MembraneComponent::TYPE_NAME) - ] - .def(constructor<>()) - .def("sendOrganelles", &MembraneComponent::sendOrganelles) - .def("clear", &MembraneComponent::clear) - .def("getExternOrganellePos", &MembraneComponent::getExternOrganellePos) - .def("setColour", &MembraneComponent::setColour) - .def("getColour", &MembraneComponent::getColour) - .def_readonly("entity", &MembraneComponent::m_entity) - .def_readonly("dimensions", &MembraneComponent::cellDimensions) - ; +void MembraneComponent::luaBindings( + sol::state &lua +){ + lua.new_usertype("MembraneComponent", + + "new", sol::factories([](){ + return std::make_unique(); + }), + + COMPONENT_BINDINGS(MembraneComponent), + + "sendOrganelles", &MembraneComponent::sendOrganelles, + "clear", &MembraneComponent::clear, + "getExternOrganellePos", &MembraneComponent::getExternOrganellePos, + "setColour", &MembraneComponent::setColour, + "getColour", &MembraneComponent::getColour, + "entity", sol::readonly(&MembraneComponent::m_entity), + "dimensions", sol::readonly(&MembraneComponent::cellDimensions) + ); } MembraneComponent::MembraneComponent() @@ -322,15 +322,16 @@ void MembraneComponent::clear() m_entity->detachFromParent(); } -luabind::object MembraneComponent::getExternOrganellePos(double x, double y) +sol::object MembraneComponent::getExternOrganellePos(double x, double y) { - luabind::object externalOrganellePosition = luabind::newtable(Game::instance().engine().luaState()); + sol::state_view lua(Game::instance().engine().luaState()); + + auto externalOrganellePosition = lua.create_table(); Ogre::Vector3 organelleCoords = GetExternalOrganelle(x, y); externalOrganellePosition[1] = organelleCoords.x; externalOrganellePosition[2] = organelleCoords.y; - return externalOrganellePosition; } @@ -342,15 +343,18 @@ REGISTER_COMPONENT(MembraneComponent) //////////////////////////////////////////////////////////////////////////////// // MembraneSystem //////////////////////////////////////////////////////////////////////////////// +void MembraneSystem::luaBindings( + sol::state &lua +){ + lua.new_usertype("MembraneSystem", -luabind::scope -MembraneSystem::luaBindings() { - using namespace luabind; - return class_("MembraneSystem") - .def(constructor<>()) - ; -} + sol::constructors>(), + + sol::base_classes, sol::bases(), + "init", &MembraneSystem::init + ); +} struct MembraneSystem::Implementation { @@ -376,10 +380,10 @@ MembraneSystem::~MembraneSystem() {} void MembraneSystem::init( - GameState* gameState + GameStateData* gameState ) { System::initNamed("MembraneSystem", gameState); - m_impl->m_entities.setEntityManager(&gameState->entityManager()); + m_impl->m_entities.setEntityManager(gameState->entityManager()); m_impl->m_sceneManager = gameState->sceneManager(); } diff --git a/src/microbe_stage/membrane_system.h b/src/microbe_stage/membrane_system.h index c2fc91ede7c..e12a3b31afd 100644 --- a/src/microbe_stage/membrane_system.h +++ b/src/microbe_stage/membrane_system.h @@ -3,10 +3,10 @@ #include "engine/component.h" #include "engine/system.h" #include "engine/touchable.h" -#include "scripting/luabind.h" #include "engine/typedefs.h" -#include +#include "scripting/luajit.h" + #include #include #include @@ -37,8 +37,7 @@ class MembraneComponent : public Component { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); MembraneComponent(); @@ -99,7 +98,7 @@ class MembraneComponent : public Component { // Gets the position of the closest membrane point - luabind::object getExternOrganellePos(double x, double y); + sol::object getExternOrganellePos(double x, double y); bool isInitialized; bool wantsMembrane; @@ -160,8 +159,7 @@ class MembraneSystem : public System { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -178,7 +176,7 @@ class MembraneSystem : public System { * * @param gameState */ - void init(GameState* gameState) override; + void init(GameStateData* gameState) override; /** * @brief Shuts the system down diff --git a/src/microbe_stage/process_system.cpp b/src/microbe_stage/process_system.cpp index 77754a3f5ac..b61157cf371 100644 --- a/src/microbe_stage/process_system.cpp +++ b/src/microbe_stage/process_system.cpp @@ -6,9 +6,11 @@ #include "engine/component_factory.h" #include "engine/engine.h" #include "engine/entity.h" +#include "engine/entity_filter.h" #include "engine/game_state.h" #include "engine/entity_filter.h" #include "engine/serialization.h" +#include "game.h" #include "general/thrive_math.h" @@ -21,21 +23,22 @@ using namespace thrive; REGISTER_COMPONENT(ProcessorComponent) -luabind::scope -ProcessorComponent::luaBindings() { - using namespace luabind; - return class_("ProcessorComponent") - .enum_("ID") [ - value("TYPE_ID", ProcessorComponent::TYPE_ID) - ] - .scope [ - def("TYPE_NAME", &ProcessorComponent::TYPE_NAME) - ] - .def(constructor<>()) - .def("setCapacity", &ProcessorComponent::setCapacity) - ; +void ProcessorComponent::luaBindings( + sol::state &lua +){ + lua.new_usertype("ProcessorComponent", + + "new", sol::factories([](){ + return std::make_unique(); + }), + + COMPONENT_BINDINGS(ProcessorComponent), + + "setCapacity", &ProcessorComponent::setCapacity + ); } + void ProcessorComponent::load(const StorageContainer& storage) { @@ -70,25 +73,25 @@ ProcessorComponent::setCapacity(BioProcessId id, float capacity) REGISTER_COMPONENT(CompoundBagComponent) -luabind::scope -CompoundBagComponent::luaBindings() { - using namespace luabind; - return class_("CompoundBagComponent") - .enum_("ID") [ - value("TYPE_ID", CompoundBagComponent::TYPE_ID) - ] - .scope [ - def("TYPE_NAME", &CompoundBagComponent::TYPE_NAME) - ] - .def(constructor<>()) - .def("setProcessor", &CompoundBagComponent::setProcessor) - .def("giveCompound", &CompoundBagComponent::giveCompound) - .def("takeCompound", &CompoundBagComponent::takeCompound) - .def("getCompoundAmount", &CompoundBagComponent::getCompoundAmount) - .def("getPrice", &CompoundBagComponent::getPrice) - .def("getDemand", &CompoundBagComponent::getDemand) - .def_readwrite("storageSpace", &CompoundBagComponent::storageSpace) - ; +void CompoundBagComponent::luaBindings( + sol::state &lua +){ + lua.new_usertype("CompoundBagComponent", + + "new", sol::factories([](){ + return std::make_unique(); + }), + + COMPONENT_BINDINGS(CompoundBagComponent), + + "setProcessor", &CompoundBagComponent::setProcessor, + "giveCompound", &CompoundBagComponent::giveCompound, + "takeCompound", &CompoundBagComponent::takeCompound, + "getCompoundAmount", &CompoundBagComponent::getCompoundAmount, + "getPrice", &CompoundBagComponent::getPrice, + "getDemand", &CompoundBagComponent::getDemand, + "storageSpace", &CompoundBagComponent::storageSpace + ); } CompoundBagComponent::CompoundBagComponent() { @@ -122,7 +125,9 @@ CompoundBagComponent::load(const StorageContainer& storage) } this->speciesName = storage.get("speciesName"); - this->processor = static_cast(Entity(this->speciesName).getComponent(ProcessorComponent::TYPE_ID)); + this->processor = static_cast(Entity(this->speciesName, + Game::instance().engine().getCurrentGameStateFromLua()). + getComponent(ProcessorComponent::TYPE_ID)); } StorageContainer @@ -188,13 +193,20 @@ CompoundBagComponent::getDemand(CompoundId compoundId) { return compounds[compoundId].demand; } -luabind::scope -ProcessSystem::luaBindings() { - using namespace luabind; - return class_("ProcessSystem") - .def(constructor<>()) - ; +void ProcessSystem::luaBindings( + sol::state &lua +){ + lua.new_usertype("ProcessSystem", + + sol::constructors>(), + + sol::base_classes, sol::bases(), + + "init", &ProcessSystem::init + ); } + + struct ProcessSystem::Implementation { EntityFilter< @@ -228,9 +240,10 @@ ProcessSystem::ProcessSystem() ProcessSystem::~ProcessSystem() {} void -ProcessSystem::init(GameState* gameState) { +ProcessSystem::init(GameStateData* gameState) +{ System::initNamed("ProcessSystem", gameState); - m_impl->m_entities.setEntityManager(&gameState->entityManager()); + m_impl->m_entities.setEntityManager(gameState->entityManager()); } void diff --git a/src/microbe_stage/process_system.h b/src/microbe_stage/process_system.h index 06f0b7501cc..451fece0997 100644 --- a/src/microbe_stage/process_system.h +++ b/src/microbe_stage/process_system.h @@ -3,7 +3,6 @@ #include "engine/component.h" #include "engine/system.h" #include "engine/touchable.h" -#include "scripting/luabind.h" #include "engine/typedefs.h" #include @@ -30,8 +29,8 @@ #define INITIAL_COMPOUND_PRICE 10.0 #define INITIAL_COMPOUND_DEMAND 1.0 -namespace luabind { -class scope; +namespace sol { +class state; } namespace thrive { @@ -40,8 +39,7 @@ class ProcessorComponent : public Component { COMPONENT(Processor) public: - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); void load( @@ -70,8 +68,7 @@ class CompoundBagComponent : public Component { COMPONENT(CompoundBag) public: - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); CompoundBagComponent(); @@ -85,7 +82,7 @@ class CompoundBagComponent : public Component { float storageSpace; float storageSpaceOccupied; - ProcessorComponent* processor; + ProcessorComponent* processor = nullptr; std::string speciesName; std::unordered_map compounds; @@ -111,8 +108,7 @@ class CompoundBagComponent : public Component { class ProcessSystem : public System { public: - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -128,7 +124,7 @@ class ProcessSystem : public System { * @brief Initializes the system * */ - void init(GameState* gameState) override; + void init(GameStateData* gameState) override; /** * @brief Shuts the system down diff --git a/src/microbe_stage/script_bindings.cpp b/src/microbe_stage/script_bindings.cpp deleted file mode 100644 index 16e2e0f7149..00000000000 --- a/src/microbe_stage/script_bindings.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "microbe_stage/script_bindings.h" - -#include "scripting/luabind.h" -#include "microbe_stage/compound.h" -#include "microbe_stage/compound_absorber_system.h" -#include "microbe_stage/compound_emitter_system.h" -#include "microbe_stage/compound_registry.h" -#include "microbe_stage/bio_process_registry.h" -#include "microbe_stage/membrane_system.h" -#include "microbe_stage/compound_cloud_system.h" -#include "microbe_stage/process_system.h" -#include "microbe_stage/agent_cloud_system.h" -#include "microbe_stage/species_component.h" - -luabind::scope -thrive::MicrobeBindings::luaBindings() { - return ( - // Components - CompoundComponent::luaBindings(), - ProcessorComponent::luaBindings(), - CompoundBagComponent::luaBindings(), - CompoundAbsorberComponent::luaBindings(), - CompoundEmitterComponent::luaBindings(), - TimedCompoundEmitterComponent::luaBindings(), - MembraneComponent::luaBindings(), - CompoundCloudComponent::luaBindings(), - AgentCloudComponent::luaBindings(), - SpeciesComponent::luaBindings(), - // Systems - CompoundMovementSystem::luaBindings(), - CompoundAbsorberSystem::luaBindings(), - CompoundEmitterSystem::luaBindings(), - MembraneSystem::luaBindings(), - CompoundCloudSystem::luaBindings(), - ProcessSystem::luaBindings(), - AgentCloudSystem::luaBindings(), - // Other - CompoundRegistry::luaBindings(), - BioProcessRegistry::luaBindings() - ); -} diff --git a/src/microbe_stage/script_bindings.h b/src/microbe_stage/script_bindings.h deleted file mode 100644 index 37b9c3783ed..00000000000 --- a/src/microbe_stage/script_bindings.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -namespace luabind { -class scope; -} - -namespace thrive { - -/** -* @brief Helper for script bindings -*/ -struct MicrobeBindings { - - /** - * @brief Exports relevant microbe bindings to Lua - * - * @return - */ - static luabind::scope - luaBindings(); - -}; - -} - - diff --git a/src/microbe_stage/species_component.cpp b/src/microbe_stage/species_component.cpp index d49810480cf..c7fa3aa4b03 100644 --- a/src/microbe_stage/species_component.cpp +++ b/src/microbe_stage/species_component.cpp @@ -1,6 +1,5 @@ #include "species_component.h" -#include #include #include "engine/engine.h" #include "engine/serialization.h" @@ -11,37 +10,37 @@ using namespace thrive; unsigned int SpeciesComponent::SPECIES_NUM = 0; -luabind::scope -SpeciesComponent::luaBindings() { - using namespace luabind; - return class_("SpeciesComponent") - .enum_("ID") [ - value("TYPE_ID", SpeciesComponent::TYPE_ID) - ] - .scope [ - def("TYPE_NAME", &SpeciesComponent::TYPE_NAME) - ] - .def(constructor()) - .def_readwrite("name", &SpeciesComponent::name) - .def_readwrite("organelles", &SpeciesComponent::organelles) - .def_readwrite("avgCompoundAmounts", &SpeciesComponent::avgCompoundAmounts) - .def_readwrite("colour", &SpeciesComponent::colour) - .def("load", &SpeciesComponent::load) - .def("storage", &SpeciesComponent::storage) - ; +void SpeciesComponent::luaBindings( + sol::state &lua +){ + lua.new_usertype("SpeciesComponent", + + "new", sol::factories([](const std::string &name){ + return std::make_unique(name); + }), + + COMPONENT_BINDINGS(SpeciesComponent), + + "name", &SpeciesComponent::name, + "organelles", &SpeciesComponent::organelles, + "avgCompoundAmounts", &SpeciesComponent::avgCompoundAmounts, + "colour", &SpeciesComponent::colour, + "load", &SpeciesComponent::load, + "storage", &SpeciesComponent::storage + ); } SpeciesComponent::SpeciesComponent(const std::string& _name) : colour(1,0,1), name(_name) { if (name == "") { - name = "noname" + SPECIES_NUM; + name = "noname" + std::to_string(SPECIES_NUM); ++SPECIES_NUM; } - lua_State* lua_state = Game::instance().engine().luaState(); + sol::state_view lua(Game::instance().engine().luaState()); - organelles = luabind::newtable(lua_state); - avgCompoundAmounts = luabind::newtable(lua_state); + organelles = lua.create_table(); + avgCompoundAmounts = lua.create_table(); } void @@ -50,15 +49,14 @@ SpeciesComponent::load(const StorageContainer& storage) { name = storage.get("name"); colour = storage.get("colour"); - lua_State* lua_state = Game::instance().engine().luaState(); - - organelles = luabind::newtable(lua_state); + sol::state_view lua(Game::instance().engine().luaState()); + StorageContainer orgs = storage.get("organelles"); int i = 1; while (orgs.contains(std::to_string(i))) { StorageContainer org = orgs.get(std::to_string(i)); - luabind::object organelle = luabind::newtable(lua_state); + sol::table organelle = lua.create_table(); organelle["name"] = org.get("name"); organelle["q"] = org.get("q"); @@ -69,7 +67,7 @@ SpeciesComponent::load(const StorageContainer& storage) { i++; } - avgCompoundAmounts = luabind::newtable(lua_state); + avgCompoundAmounts = lua.create_table(); StorageContainer amts = storage.get("avgCompoundAmounts"); for (const std::string& k : amts.keys()) { @@ -86,23 +84,29 @@ SpeciesComponent::storage() const { StorageContainer orgs; int i = 1; - for (luabind::iterator it(organelles), end; it != end; it++, i++) { - const luabind::object& data = *it; + for (const auto& pair : organelles) { + + sol::table data = pair.second.as(); + + StorageContainer org; - org.set("name", luabind::object_cast(data["name"])); - org.set("q", luabind::object_cast(data["q"])); - org.set("r", luabind::object_cast(data["r"])); - org.set("rotation", luabind::object_cast(data["rotation"])); + org.set("name", data.get("name")); + org.set("q", data.get("q")); + org.set("r", data.get("r")); + org.set("rotation", data.get("rotation")); orgs.set(std::to_string(i), org); + + ++i; } storage.set("organelles", orgs); StorageContainer amts; - for (luabind::iterator it(avgCompoundAmounts), end; it != end; it++) { - const std::string& key = luabind::object_cast(it.key()); - const Ogre::Real& data = luabind::object_cast(*it); + for (const auto& pair : avgCompoundAmounts) { + + const std::string& key = pair.first.as(); + const Ogre::Real& data = pair.second.as(); amts.set(key, data); } diff --git a/src/microbe_stage/species_component.h b/src/microbe_stage/species_component.h index 9eb580f27bf..d7e8f56a712 100644 --- a/src/microbe_stage/species_component.h +++ b/src/microbe_stage/species_component.h @@ -1,7 +1,9 @@ #pragma once -#include "scripting/luabind.h" #include "engine/component.h" + +#include "scripting/luajit.h" + #include #include @@ -11,13 +13,12 @@ class SpeciesComponent : public Component { COMPONENT(SpeciesComponent) public: - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); SpeciesComponent(const std::string& _name = ""); - luabind::object organelles; - luabind::object avgCompoundAmounts; + sol::table organelles; + sol::table avgCompoundAmounts; Ogre::Vector3 colour; std::string name; diff --git a/src/ogre/CMakeLists.txt b/src/ogre/CMakeLists.txt index 9f85e1a5c33..cc8344dd67b 100644 --- a/src/ogre/CMakeLists.txt +++ b/src/ogre/CMakeLists.txt @@ -13,8 +13,6 @@ add_sources( "${CMAKE_CURRENT_SOURCE_DIR}/render_system.h" "${CMAKE_CURRENT_SOURCE_DIR}/scene_node_system.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/scene_node_system.h" - "${CMAKE_CURRENT_SOURCE_DIR}/script_bindings.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/script_bindings.h" "${CMAKE_CURRENT_SOURCE_DIR}/sky_system.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/sky_system.h" ) diff --git a/src/ogre/camera_system.cpp b/src/ogre/camera_system.cpp index ec406b0deed..e5b559092a2 100644 --- a/src/ogre/camera_system.cpp +++ b/src/ogre/camera_system.cpp @@ -5,7 +5,7 @@ #include "engine/entity_filter.h" #include "engine/serialization.h" #include "ogre/scene_node_system.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include #include @@ -32,32 +32,38 @@ OgreCameraComponent_getCameraToViewportRay( } } -luabind::scope -OgreCameraComponent::luaBindings() { - using namespace luabind; - return class_("OgreCameraComponent") - .enum_("ID") [ - value("TYPE_ID", OgreCameraComponent::TYPE_ID) - ] - .scope [ - def("TYPE_NAME", &OgreCameraComponent::TYPE_NAME), - class_("Properties") - .def_readwrite("polygonMode", &Properties::polygonMode) - .def_readwrite("fovY", &Properties::fovY) - .def_readwrite("nearClipDistance", &Properties::nearClipDistance) - .def_readwrite("farClipDistance", &Properties::farClipDistance) - .def_readwrite("orthographicalMode", &Properties::orthographicalMode) - .def_readwrite("offset", &Properties::offset) - ] - .enum_("PolygonMode") [ - value("PM_POINTS", Ogre::PM_POINTS), - value("PM_WIREFRAME", Ogre::PM_WIREFRAME), - value("PM_SOLID", Ogre::PM_SOLID) - ] - .def(constructor()) - .def("getCameraToViewportRay", OgreCameraComponent_getCameraToViewportRay) - .def_readonly("properties", &OgreCameraComponent::m_properties) - ; +void OgreCameraComponent::luaBindings( + sol::state &lua +){ + lua.new_usertype("OgreCameraComponentProperties", + + sol::base_classes, sol::bases(), + + "polygonMode", &Properties::polygonMode, + "fovY", &Properties::fovY, + "nearClipDistance", &Properties::nearClipDistance, + "farClipDistance", &Properties::farClipDistance, + "orthographicalMode", &Properties::orthographicalMode, + "offset", &Properties::offset + ); + + lua.new_usertype("OgreCameraComponent", + + "new", sol::factories([](const std::string &name){ + return std::make_unique(name); + }), + + COMPONENT_BINDINGS(OgreCameraComponent), + + "PolygonMode", sol::var(lua.create_table_with( + "PM_POINTS", Ogre::PM_POINTS, + "PM_WIREFRAME", Ogre::PM_WIREFRAME, + "PM_SOLID", Ogre::PM_SOLID + )), + + "getCameraToViewportRay", OgreCameraComponent_getCameraToViewportRay, + "properties", sol::readonly(&OgreCameraComponent::m_properties) + ); } OgreCameraComponent::OgreCameraComponent( @@ -114,12 +120,17 @@ REGISTER_COMPONENT(OgreCameraComponent) // OgreCameraSystem //////////////////////////////////////////////////////////////////////////////// -luabind::scope -OgreCameraSystem::luaBindings() { - using namespace luabind; - return class_("OgreCameraSystem") - .def(constructor<>()) - ; +void OgreCameraSystem::luaBindings( + sol::state &lua +){ + lua.new_usertype("OgreCameraSystem", + + sol::constructors>(), + + sol::base_classes, sol::bases(), + + "init", &OgreCameraSystem::init + ); } @@ -147,12 +158,12 @@ OgreCameraSystem::~OgreCameraSystem() {} void OgreCameraSystem::init( - GameState* gameState + GameStateData* gameState ) { System::initNamed("OgreCameraSystem", gameState); assert(m_impl->m_sceneManager == nullptr && "Double init of system"); m_impl->m_sceneManager = gameState->sceneManager(); - m_impl->m_entities.setEntityManager(&gameState->entityManager()); + m_impl->m_entities.setEntityManager(gameState->entityManager()); } diff --git a/src/ogre/camera_system.h b/src/ogre/camera_system.h index 6dc15e3f05f..989832748b2 100644 --- a/src/ogre/camera_system.h +++ b/src/ogre/camera_system.h @@ -9,8 +9,8 @@ #include #include -namespace luabind { -class scope; +namespace sol { +class state; } namespace Ogre { @@ -83,8 +83,7 @@ class OgreCameraComponent : public Component { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -175,8 +174,7 @@ class OgreCameraSystem : public System { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -192,7 +190,7 @@ class OgreCameraSystem : public System { * @brief Initializes the system * */ - void init(GameState* gameState) override; + void init(GameStateData* gameState) override; /** * @brief Shuts the system down diff --git a/src/ogre/keyboard.cpp b/src/ogre/keyboard.cpp index d0a0f9d26d1..854a431010c 100644 --- a/src/ogre/keyboard.cpp +++ b/src/ogre/keyboard.cpp @@ -1,6 +1,6 @@ #include "ogre/keyboard.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include @@ -109,169 +109,178 @@ struct Keyboard::Implementation : public OIS::KeyListener{ }; -luabind::scope -Keyboard::luaBindings() { - using namespace luabind; - return class_("Keyboard") - .def("isKeyDown", &Keyboard::isKeyDown) - .def("wasKeyPressed", &Keyboard::wasKeyPressed) - .def("wasKeyReleased", &Keyboard::wasKeyReleased) - .scope [ - class_("KeyEvent") - .def_readonly("key", &Keyboard::KeyEvent::key) - .def_readonly("alt", &Keyboard::KeyEvent::alt) - .def_readonly("ctrl", &Keyboard::KeyEvent::ctrl) - .def_readonly("shift", &Keyboard::KeyEvent::shift) - .def_readonly("pressed", &Keyboard::KeyEvent::pressed) - ] - .enum_("KeyCode") [ - value("KC_UNASSIGNED", OIS::KC_UNASSIGNED), - value("KC_ESCAPE", OIS::KC_ESCAPE), - value("KC_1", OIS::KC_1), - value("KC_2", OIS::KC_2), - value("KC_3", OIS::KC_3), - value("KC_4", OIS::KC_4), - value("KC_5", OIS::KC_5), - value("KC_6", OIS::KC_6), - value("KC_7", OIS::KC_7), - value("KC_8", OIS::KC_8), - value("KC_9", OIS::KC_9), - value("KC_0", OIS::KC_0), - value("KC_MINUS", OIS::KC_MINUS), - value("KC_EQUALS", OIS::KC_EQUALS), - value("KC_BACK", OIS::KC_BACK), - value("KC_TAB", OIS::KC_TAB), - value("KC_Q", OIS::KC_Q), - value("KC_W", OIS::KC_W), - value("KC_E", OIS::KC_E), - value("KC_R", OIS::KC_R), - value("KC_T", OIS::KC_T), - value("KC_Y", OIS::KC_Y), - value("KC_U", OIS::KC_U), - value("KC_I", OIS::KC_I), - value("KC_O", OIS::KC_O), - value("KC_P", OIS::KC_P), - value("KC_LBRACKET", OIS::KC_LBRACKET), - value("KC_RBRACKET", OIS::KC_RBRACKET), - value("KC_RETURN", OIS::KC_RETURN), - value("KC_LCONTROL", OIS::KC_LCONTROL), - value("KC_A", OIS::KC_A), - value("KC_S", OIS::KC_S), - value("KC_D", OIS::KC_D), - value("KC_F", OIS::KC_F), - value("KC_G", OIS::KC_G), - value("KC_H", OIS::KC_H), - value("KC_J", OIS::KC_J), - value("KC_K", OIS::KC_K), - value("KC_L", OIS::KC_L), - value("KC_SEMICOLON", OIS::KC_SEMICOLON), - value("KC_APOSTROPHE", OIS::KC_APOSTROPHE), - value("KC_GRAVE", OIS::KC_GRAVE), - value("KC_LSHIFT", OIS::KC_LSHIFT), - value("KC_BACKSLASH", OIS::KC_BACKSLASH), - value("KC_Z", OIS::KC_Z), - value("KC_X", OIS::KC_X), - value("KC_C", OIS::KC_C), - value("KC_V", OIS::KC_V), - value("KC_B", OIS::KC_B), - value("KC_N", OIS::KC_N), - value("KC_M", OIS::KC_M), - value("KC_COMMA", OIS::KC_COMMA), - value("KC_PERIOD", OIS::KC_PERIOD), - value("KC_SLASH", OIS::KC_SLASH), - value("KC_RSHIFT", OIS::KC_RSHIFT), - value("KC_MULTIPLY", OIS::KC_MULTIPLY), - value("KC_LMENU", OIS::KC_LMENU), - value("KC_SPACE", OIS::KC_SPACE), - value("KC_CAPITAL", OIS::KC_CAPITAL), - value("KC_F1", OIS::KC_F1), - value("KC_F2", OIS::KC_F2), - value("KC_F3", OIS::KC_F3), - value("KC_F4", OIS::KC_F4), - value("KC_F5", OIS::KC_F5), - value("KC_F6", OIS::KC_F6), - value("KC_F7", OIS::KC_F7), - value("KC_F8", OIS::KC_F8), - value("KC_F9", OIS::KC_F9), - value("KC_F10", OIS::KC_F10), - value("KC_NUMLOCK", OIS::KC_NUMLOCK), - value("KC_SCROLL", OIS::KC_SCROLL), - value("KC_NUMPAD7", OIS::KC_NUMPAD7), - value("KC_NUMPAD8", OIS::KC_NUMPAD8), - value("KC_NUMPAD9", OIS::KC_NUMPAD9), - value("KC_SUBTRACT", OIS::KC_SUBTRACT), - value("KC_NUMPAD4", OIS::KC_NUMPAD4), - value("KC_NUMPAD5", OIS::KC_NUMPAD5), - value("KC_NUMPAD6", OIS::KC_NUMPAD6), - value("KC_ADD", OIS::KC_ADD), - value("KC_NUMPAD1", OIS::KC_NUMPAD1), - value("KC_NUMPAD2", OIS::KC_NUMPAD2), - value("KC_NUMPAD3", OIS::KC_NUMPAD3), - value("KC_NUMPAD0", OIS::KC_NUMPAD0), - value("KC_DECIMAL", OIS::KC_DECIMAL), - value("KC_OEM_102", OIS::KC_OEM_102), - value("KC_F11", OIS::KC_F11), - value("KC_F12", OIS::KC_F12), - value("KC_F13", OIS::KC_F13), - value("KC_F14", OIS::KC_F14), - value("KC_F15", OIS::KC_F15), - value("KC_KANA", OIS::KC_KANA), - value("KC_ABNT_C1", OIS::KC_ABNT_C1), - value("KC_CONVERT", OIS::KC_CONVERT), - value("KC_NOCONVERT", OIS::KC_NOCONVERT), - value("KC_YEN", OIS::KC_YEN), - value("KC_ABNT_C2", OIS::KC_ABNT_C2), - value("KC_NUMPADEQUALS", OIS::KC_NUMPADEQUALS), - value("KC_PREVTRACK", OIS::KC_PREVTRACK), - value("KC_AT", OIS::KC_AT), - value("KC_COLON", OIS::KC_COLON), - value("KC_UNDERLINE", OIS::KC_UNDERLINE), - value("KC_KANJI", OIS::KC_KANJI), - value("KC_STOP", OIS::KC_STOP), - value("KC_AX", OIS::KC_AX), - value("KC_UNLABELED", OIS::KC_UNLABELED), - value("KC_NEXTTRACK", OIS::KC_NEXTTRACK), - value("KC_NUMPADENTER", OIS::KC_NUMPADENTER), - value("KC_RCONTROL", OIS::KC_RCONTROL), - value("KC_MUTE", OIS::KC_MUTE), - value("KC_CALCULATOR", OIS::KC_CALCULATOR), - value("KC_PLAYPAUSE", OIS::KC_PLAYPAUSE), - value("KC_MEDIASTOP", OIS::KC_MEDIASTOP), - value("KC_VOLUMEDOWN", OIS::KC_VOLUMEDOWN), - value("KC_VOLUMEUP", OIS::KC_VOLUMEUP), - value("KC_WEBHOME", OIS::KC_WEBHOME), - value("KC_NUMPADCOMMA", OIS::KC_NUMPADCOMMA), - value("KC_DIVIDE", OIS::KC_DIVIDE), - value("KC_SYSRQ", OIS::KC_SYSRQ), - value("KC_RMENU", OIS::KC_RMENU), - value("KC_PAUSE", OIS::KC_PAUSE), - value("KC_HOME", OIS::KC_HOME), - value("KC_UP", OIS::KC_UP), - value("KC_PGUP", OIS::KC_PGUP), - value("KC_LEFT", OIS::KC_LEFT), - value("KC_RIGHT", OIS::KC_RIGHT), - value("KC_END", OIS::KC_END), - value("KC_DOWN", OIS::KC_DOWN), - value("KC_PGDOWN", OIS::KC_PGDOWN), - value("KC_INSERT", OIS::KC_INSERT), - value("KC_DELETE", OIS::KC_DELETE), - value("KC_LWIN", OIS::KC_LWIN), - value("KC_RWIN", OIS::KC_RWIN), - value("KC_APPS", OIS::KC_APPS), - value("KC_POWER", OIS::KC_POWER), - value("KC_SLEEP", OIS::KC_SLEEP), - value("KC_WAKE", OIS::KC_WAKE), - value("KC_WEBSEARCH", OIS::KC_WEBSEARCH), - value("KC_WEBFAVORITES", OIS::KC_WEBFAVORITES), - value("KC_WEBREFRESH", OIS::KC_WEBREFRESH), - value("KC_WEBSTOP", OIS::KC_WEBSTOP), - value("KC_WEBFORWARD", OIS::KC_WEBFORWARD), - value("KC_WEBBACK", OIS::KC_WEBBACK), - value("KC_MYCOMPUTER", OIS::KC_MYCOMPUTER), - value("KC_MAIL", OIS::KC_MAIL), - value("KC_MEDIASELECT", OIS::KC_MEDIASELECT) - ] - ; +void Keyboard::luaBindings( + sol::state &lua +){ + lua.new_usertype("KeyboardKeyEvent", + + "key", sol::readonly(&Keyboard::KeyEvent::key), + "alt", sol::readonly(&Keyboard::KeyEvent::alt), + "ctrl", sol::readonly(&Keyboard::KeyEvent::ctrl), + "shift", sol::readonly(&Keyboard::KeyEvent::shift), + "pressed", sol::readonly(&Keyboard::KeyEvent::pressed) + ); + + lua.new_usertype("Keyboard", + + "new", sol::no_constructor, + + "isKeyDown", &Keyboard::isKeyDown, + "wasKeyPressed", &Keyboard::wasKeyPressed, + "wasKeyReleased", &Keyboard::wasKeyReleased + ); + + // This cannot be a template because template recursion goes too deep + auto table = lua.create_table(); + + table.set("KC_UNASSIGNED", OIS::KC_UNASSIGNED); + table.set("KC_ESCAPE", OIS::KC_ESCAPE); + table.set("KC_1", OIS::KC_1); + table.set("KC_2", OIS::KC_2); + table.set("KC_3", OIS::KC_3); + table.set("KC_4", OIS::KC_4); + table.set("KC_5", OIS::KC_5); + table.set("KC_6", OIS::KC_6); + table.set("KC_7", OIS::KC_7); + table.set("KC_8", OIS::KC_8); + table.set("KC_9", OIS::KC_9); + table.set("KC_0", OIS::KC_0); + table.set("KC_MINUS", OIS::KC_MINUS); + table.set("KC_EQUALS", OIS::KC_EQUALS); + table.set("KC_BACK", OIS::KC_BACK); + table.set("KC_TAB", OIS::KC_TAB); + table.set("KC_Q", OIS::KC_Q); + table.set("KC_W", OIS::KC_W); + table.set("KC_E", OIS::KC_E); + table.set("KC_R", OIS::KC_R); + table.set("KC_T", OIS::KC_T); + table.set("KC_Y", OIS::KC_Y); + table.set("KC_U", OIS::KC_U); + table.set("KC_I", OIS::KC_I); + table.set("KC_O", OIS::KC_O); + table.set("KC_P", OIS::KC_P); + table.set("KC_LBRACKET", OIS::KC_LBRACKET); + table.set("KC_RBRACKET", OIS::KC_RBRACKET); + table.set("KC_RETURN", OIS::KC_RETURN); + table.set("KC_LCONTROL", OIS::KC_LCONTROL); + table.set("KC_A", OIS::KC_A); + table.set("KC_S", OIS::KC_S); + table.set("KC_D", OIS::KC_D); + table.set("KC_F", OIS::KC_F); + table.set("KC_G", OIS::KC_G); + table.set("KC_H", OIS::KC_H); + table.set("KC_J", OIS::KC_J); + table.set("KC_K", OIS::KC_K); + table.set("KC_L", OIS::KC_L); + table.set("KC_SEMICOLON", OIS::KC_SEMICOLON); + table.set("KC_APOSTROPHE", OIS::KC_APOSTROPHE); + table.set("KC_GRAVE", OIS::KC_GRAVE); + table.set("KC_LSHIFT", OIS::KC_LSHIFT); + table.set("KC_BACKSLASH", OIS::KC_BACKSLASH); + table.set("KC_Z", OIS::KC_Z); + table.set("KC_X", OIS::KC_X); + table.set("KC_C", OIS::KC_C); + table.set("KC_V", OIS::KC_V); + table.set("KC_B", OIS::KC_B); + table.set("KC_N", OIS::KC_N); + table.set("KC_M", OIS::KC_M); + table.set("KC_COMMA", OIS::KC_COMMA); + table.set("KC_PERIOD", OIS::KC_PERIOD); + table.set("KC_SLASH", OIS::KC_SLASH); + table.set("KC_RSHIFT", OIS::KC_RSHIFT); + table.set("KC_MULTIPLY", OIS::KC_MULTIPLY); + table.set("KC_LMENU", OIS::KC_LMENU); + table.set("KC_SPACE", OIS::KC_SPACE); + table.set("KC_CAPITAL", OIS::KC_CAPITAL); + table.set("KC_F1", OIS::KC_F1); + table.set("KC_F2", OIS::KC_F2); + table.set("KC_F3", OIS::KC_F3); + table.set("KC_F4", OIS::KC_F4); + table.set("KC_F5", OIS::KC_F5); + table.set("KC_F6", OIS::KC_F6); + table.set("KC_F7", OIS::KC_F7); + table.set("KC_F8", OIS::KC_F8); + table.set("KC_F9", OIS::KC_F9); + table.set("KC_F10", OIS::KC_F10); + table.set("KC_NUMLOCK", OIS::KC_NUMLOCK); + table.set("KC_SCROLL", OIS::KC_SCROLL); + table.set("KC_NUMPAD7", OIS::KC_NUMPAD7); + table.set("KC_NUMPAD8", OIS::KC_NUMPAD8); + table.set("KC_NUMPAD9", OIS::KC_NUMPAD9); + table.set("KC_SUBTRACT", OIS::KC_SUBTRACT); + table.set("KC_NUMPAD4", OIS::KC_NUMPAD4); + table.set("KC_NUMPAD5", OIS::KC_NUMPAD5); + table.set("KC_NUMPAD6", OIS::KC_NUMPAD6); + table.set("KC_ADD", OIS::KC_ADD); + table.set("KC_NUMPAD1", OIS::KC_NUMPAD1); + table.set("KC_NUMPAD2", OIS::KC_NUMPAD2); + table.set("KC_NUMPAD3", OIS::KC_NUMPAD3); + table.set("KC_NUMPAD0", OIS::KC_NUMPAD0); + table.set("KC_DECIMAL", OIS::KC_DECIMAL); + table.set("KC_OEM_102", OIS::KC_OEM_102); + table.set("KC_F11", OIS::KC_F11); + table.set("KC_F12", OIS::KC_F12); + table.set("KC_F13", OIS::KC_F13); + table.set("KC_F14", OIS::KC_F14); + table.set("KC_F15", OIS::KC_F15); + table.set("KC_KANA", OIS::KC_KANA); + table.set("KC_ABNT_C1", OIS::KC_ABNT_C1); + table.set("KC_CONVERT", OIS::KC_CONVERT); + table.set("KC_NOCONVERT", OIS::KC_NOCONVERT); + table.set("KC_YEN", OIS::KC_YEN); + table.set("KC_ABNT_C2", OIS::KC_ABNT_C2); + table.set("KC_NUMPADEQUALS", OIS::KC_NUMPADEQUALS); + table.set("KC_PREVTRACK", OIS::KC_PREVTRACK); + table.set("KC_AT", OIS::KC_AT); + table.set("KC_COLON", OIS::KC_COLON); + table.set("KC_UNDERLINE", OIS::KC_UNDERLINE); + table.set("KC_KANJI", OIS::KC_KANJI); + table.set("KC_STOP", OIS::KC_STOP); + table.set("KC_AX", OIS::KC_AX); + table.set("KC_UNLABELED", OIS::KC_UNLABELED); + table.set("KC_NEXTTRACK", OIS::KC_NEXTTRACK); + table.set("KC_NUMPADENTER", OIS::KC_NUMPADENTER); + table.set("KC_RCONTROL", OIS::KC_RCONTROL); + table.set("KC_MUTE", OIS::KC_MUTE); + table.set("KC_CALCULATOR", OIS::KC_CALCULATOR); + table.set("KC_PLAYPAUSE", OIS::KC_PLAYPAUSE); + table.set("KC_MEDIASTOP", OIS::KC_MEDIASTOP); + table.set("KC_VOLUMEDOWN", OIS::KC_VOLUMEDOWN); + table.set("KC_VOLUMEUP", OIS::KC_VOLUMEUP); + table.set("KC_WEBHOME", OIS::KC_WEBHOME); + table.set("KC_NUMPADCOMMA", OIS::KC_NUMPADCOMMA); + table.set("KC_DIVIDE", OIS::KC_DIVIDE); + table.set("KC_SYSRQ", OIS::KC_SYSRQ); + table.set("KC_RMENU", OIS::KC_RMENU); + table.set("KC_PAUSE", OIS::KC_PAUSE); + table.set("KC_HOME", OIS::KC_HOME); + table.set("KC_UP", OIS::KC_UP); + table.set("KC_PGUP", OIS::KC_PGUP); + table.set("KC_LEFT", OIS::KC_LEFT); + table.set("KC_RIGHT", OIS::KC_RIGHT); + table.set("KC_END", OIS::KC_END); + table.set("KC_DOWN", OIS::KC_DOWN); + table.set("KC_PGDOWN", OIS::KC_PGDOWN); + table.set("KC_INSERT", OIS::KC_INSERT); + table.set("KC_DELETE", OIS::KC_DELETE); + table.set("KC_LWIN", OIS::KC_LWIN); + table.set("KC_RWIN", OIS::KC_RWIN); + table.set("KC_APPS", OIS::KC_APPS); + table.set("KC_POWER", OIS::KC_POWER); + table.set("KC_SLEEP", OIS::KC_SLEEP); + table.set("KC_WAKE", OIS::KC_WAKE); + table.set("KC_WEBSEARCH", OIS::KC_WEBSEARCH); + table.set("KC_WEBFAVORITES", OIS::KC_WEBFAVORITES); + table.set("KC_WEBREFRESH", OIS::KC_WEBREFRESH); + table.set("KC_WEBSTOP", OIS::KC_WEBSTOP); + table.set("KC_WEBFORWARD", OIS::KC_WEBFORWARD); + table.set("KC_WEBBACK", OIS::KC_WEBBACK); + table.set("KC_MYCOMPUTER", OIS::KC_MYCOMPUTER); + table.set("KC_MAIL", OIS::KC_MAIL); + table.set("KC_MEDIASELECT", OIS::KC_MEDIASELECT); + + lua["KEYCODE"] = table; + } diff --git a/src/ogre/keyboard.h b/src/ogre/keyboard.h index 87d1c777812..0e68f55014a 100644 --- a/src/ogre/keyboard.h +++ b/src/ogre/keyboard.h @@ -4,8 +4,8 @@ #include #include -namespace luabind { -class scope; +namespace sol { +class state; } namespace OIS { @@ -71,8 +71,7 @@ class Keyboard { * - KeyCode * */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor diff --git a/src/ogre/light_system.cpp b/src/ogre/light_system.cpp index c93b6db7ce5..0048ed1ca24 100644 --- a/src/ogre/light_system.cpp +++ b/src/ogre/light_system.cpp @@ -5,7 +5,7 @@ #include "engine/entity_filter.h" #include "engine/serialization.h" #include "ogre/scene_node_system.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include #include @@ -28,40 +28,45 @@ OgreLightComponent::setRange( m_properties.touch(); } +void OgreLightComponent::luaBindings( + sol::state &lua +){ + + lua.new_usertype("OgreLightComponentProperties", + + sol::base_classes, sol::bases(), + + "attenuationConstant", &Properties::attenuationConstant, + "attenuationLinear", &Properties::attenuationLinear, + "attenuationRange", &Properties::attenuationRange, + "attenuationQuadratic", &Properties::attenuationQuadratic, + "diffuseColour", &Properties::diffuseColour, + "specularColour", &Properties::specularColour, + "spotlightFalloff", &Properties::spotlightFalloff, + "spotlightInnerAngle", &Properties::spotlightInnerAngle, + "spotlightNearClipDistance", &Properties::spotlightNearClipDistance, + "spotlightOuterAngle", &Properties::spotlightOuterAngle, + "type", &Properties::type + ); + + lua.new_usertype("OgreLightComponent", -luabind::scope -OgreLightComponent::luaBindings() { - using namespace luabind; - return class_("OgreLightComponent") - .enum_("ID") [ - value("TYPE_ID", OgreLightComponent::TYPE_ID) - ] - .scope [ - def("TYPE_NAME", &OgreLightComponent::TYPE_NAME), - class_("Properties") - .def_readwrite("attenuationConstant", &Properties::attenuationConstant) - .def_readwrite("attenuationLinear", &Properties::attenuationLinear) - .def_readwrite("attenuationRange", &Properties::attenuationRange) - .def_readwrite("attenuationQuadratic", &Properties::attenuationQuadratic) - .def_readwrite("diffuseColour", &Properties::diffuseColour) - .def_readwrite("specularColour", &Properties::specularColour) - .def_readwrite("spotlightFalloff", &Properties::spotlightFalloff) - .def_readwrite("spotlightInnerAngle", &Properties::spotlightInnerAngle) - .def_readwrite("spotlightNearClipDistance", &Properties::spotlightNearClipDistance) - .def_readwrite("spotlightOuterAngle", &Properties::spotlightOuterAngle) - .def_readwrite("type", &Properties::type) - ] - .enum_("LightTypes") [ - value("LT_POINT", Ogre::Light::LT_POINT), - value("LT_DIRECTIONAL", Ogre::Light::LT_DIRECTIONAL), - value("LT_SPOTLIGHT", Ogre::Light::LT_SPOTLIGHT) - ] - .def(constructor<>()) - .def("setRange", &OgreLightComponent::setRange) - .def_readonly("properties", &OgreLightComponent::m_properties) - ; -} + "new", sol::factories([](){ + return std::make_unique(); + }), + + COMPONENT_BINDINGS(OgreLightComponent), + "setRange", &OgreLightComponent::setRange, + "properties", sol::readonly(&OgreLightComponent::m_properties), + + "LightTypes", sol::var(lua.create_table_with( + "LT_POINT", Ogre::Light::LT_POINT, + "LT_DIRECTIONAL", Ogre::Light::LT_DIRECTIONAL, + "LT_SPOTLIGHT", Ogre::Light::LT_SPOTLIGHT + )) + ); +} void OgreLightComponent::load( @@ -108,14 +113,18 @@ REGISTER_COMPONENT(OgreLightComponent) // OgreLightSystem //////////////////////////////////////////////////////////////////////////////// -luabind::scope -OgreLightSystem::luaBindings() { - using namespace luabind; - return class_("OgreLightSystem") - .def(constructor<>()) - ; -} +void OgreLightSystem::luaBindings( + sol::state &lua +){ + lua.new_usertype("OgreLightSystem", + + sol::constructors>(), + + sol::base_classes, sol::bases(), + "init", &OgreLightSystem::init + ); +} struct OgreLightSystem::Implementation { @@ -142,12 +151,12 @@ OgreLightSystem::~OgreLightSystem() {} void OgreLightSystem::init( - GameState* gameState + GameStateData* gameState ) { System::initNamed("OgreLightSystem", gameState); assert(m_impl->m_sceneManager == nullptr && "Double init of system"); m_impl->m_sceneManager = gameState->sceneManager(); - m_impl->m_entities.setEntityManager(&gameState->entityManager()); + m_impl->m_entities.setEntityManager(gameState->entityManager()); } diff --git a/src/ogre/light_system.h b/src/ogre/light_system.h index f68467d7d74..c9ac3ce4afa 100644 --- a/src/ogre/light_system.h +++ b/src/ogre/light_system.h @@ -9,8 +9,8 @@ #include -namespace luabind { -class scope; +namespace sol { +class state; } namespace thrive { @@ -119,8 +119,7 @@ class OgreLightComponent : public Component { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); void load( @@ -173,8 +172,7 @@ class OgreLightSystem : public System { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -190,7 +188,7 @@ class OgreLightSystem : public System { * @brief Initializes the system * */ - void init(GameState* gameState) override; + void init(GameStateData* gameState) override; /** * @brief Shuts the system down diff --git a/src/ogre/membrane_generation_system.cpp b/src/ogre/membrane_generation_system.cpp index 41a89d676f1..ec40dcac5bb 100644 --- a/src/ogre/membrane_generation_system.cpp +++ b/src/ogre/membrane_generation_system.cpp @@ -6,7 +6,6 @@ #include "engine/entity.h" #include "engine/entity_filter.h" #include "engine/entity_manager.h" -#include "scripting/luabind.h" #include "engine/serialization.h" #include "OgreVector2.h" #include "util/make_unique.h" @@ -17,23 +16,6 @@ using namespace thrive; -luabind::scope -MembraneGenerationComponent::luaBindings() { - using namespace luabind; - return class_("MembraneGenerationComponent") - .enum_("ID") [ - value("TYPE_ID", MembraneGenerationComponent::TYPE_ID) - ] - .scope [ - def("TYPE_NAME", &MembraneGenerationComponent::TYPE_NAME) - ] - .def(constructor<>()) - //.def("dqwwqd", &MembraneGenerationComponent::dwqdqwd) - // .def_readonly("aasasas", &MembraneGenerationComponent::assasa) - ; -} - - void MembraneGenerationComponent::load( const StorageContainer& storage @@ -64,15 +46,6 @@ REGISTER_COMPONENT(MembraneGenerationComponent) -luabind::scope -MembraneGenerationSystem::luaBindings() { - using namespace luabind; - return class_("MembraneGenerationSystem") - .def(constructor<>()) - ; -} - - struct MembraneGenerationSystem::Implementation { int** table = new int*[256]; int* tableSizes; @@ -98,7 +71,7 @@ MembraneGenerationSystem::~MembraneGenerationSystem() {} void MembraneGenerationSystem::init( - GameState* gameState + GameStateData* gameState ) { System::init(gameState); diff --git a/src/ogre/membrane_generation_system.h b/src/ogre/membrane_generation_system.h index 8a6eb4ba5f6..8ba56801458 100644 --- a/src/ogre/membrane_generation_system.h +++ b/src/ogre/membrane_generation_system.h @@ -7,8 +7,8 @@ #include #include -namespace luabind { -class scope; +namespace sol { +class state; } namespace thrive { @@ -16,6 +16,8 @@ namespace thrive { /** * @brief A component for a Ogre scene nodes * +* @note This is currently broken because it wasn't in use when systems +* were moved to the new system */ class MembraneGenerationComponent : public Component { COMPONENT(MembraneGenerationComponent) @@ -31,8 +33,6 @@ class MembraneGenerationComponent : public Component { * * @return */ - static luabind::scope - luaBindings(); void load( @@ -84,8 +84,6 @@ class MembraneGenerationSystem : public System { * * @return */ - static luabind::scope - luaBindings(); /** * @brief Constructor @@ -101,7 +99,7 @@ class MembraneGenerationSystem : public System { * @brief Initializes the system * */ - void init(GameState* gameState) override; + void init(GameStateData* gameState) override; /** * @brief Shuts the system down diff --git a/src/ogre/mouse.cpp b/src/ogre/mouse.cpp index f347c6ed277..853f586716e 100644 --- a/src/ogre/mouse.cpp +++ b/src/ogre/mouse.cpp @@ -1,6 +1,6 @@ #include "ogre/mouse.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include @@ -21,20 +21,32 @@ struct Mouse::Implementation : public OIS::MouseListener { m_aggregator->injectMouseWheelChange(e.state.Z.rel/100); - + return true; } bool mousePressed (const OIS::MouseEvent&, OIS::MouseButtonID id){ switch(id){ case OIS::MB_Left: + #ifdef WIN32 m_aggregator->injectMouseButtonDown(CEGUI::MouseButton::LeftButton); + #elif + m_aggregator->injectMouseButtonDown(CEGUI::MouseButton::Left); + #endif break; case OIS::MB_Right: + #ifdef WIN32 m_aggregator->injectMouseButtonDown(CEGUI::MouseButton::RightButton); + #elif + m_aggregator->injectMouseButtonDown(CEGUI::MouseButton::Right); + #endif break; case OIS::MB_Middle: + #ifdef WIN32 m_aggregator->injectMouseButtonDown(CEGUI::MouseButton::MiddleButton); + #elif + m_aggregator->injectMouseButtonDown(CEGUI::MouseButton::Middle); + #endif break; default: break; @@ -46,20 +58,29 @@ struct Mouse::Implementation : public OIS::MouseListener { bool mouseReleased (const OIS::MouseEvent&, OIS::MouseButtonID id){ switch(id){ case OIS::MB_Left: + #ifdef WIN32 if(!m_aggregator->injectMouseButtonUp(CEGUI::MouseButton::LeftButton)){ - + #elif + if(!m_aggregator->injectMouseButtonUp(CEGUI::MouseButton::Left)){ + #endif m_nextClickedStates |= 0x1; } break; case OIS::MB_Right: + #ifdef WIN32 if(!m_aggregator->injectMouseButtonUp(CEGUI::MouseButton::RightButton)){ - + #elif + if(!m_aggregator->injectMouseButtonUp(CEGUI::MouseButton::Right)){ + #endif m_nextClickedStates |= 0x2; } break; case OIS::MB_Middle: + #ifdef WIN32 if(!m_aggregator->injectMouseButtonUp(CEGUI::MouseButton::MiddleButton)){ - + #elif + if(!m_aggregator->injectMouseButtonUp(CEGUI::MouseButton::Middle)){ + #endif m_nextClickedStates |= 0x4; } break; @@ -88,29 +109,31 @@ struct Mouse::Implementation : public OIS::MouseListener { }; -luabind::scope -Mouse::luaBindings() { - using namespace luabind; - return class_("Mouse") - .enum_("MouseButton") [ - value("MB_Left", OIS::MB_Left), - value("MB_Right", OIS::MB_Right), - value("MB_Middle", OIS::MB_Middle), - value("MB_Button3", OIS::MB_Button3), - value("MB_Button4", OIS::MB_Button4), - value("MB_Button5", OIS::MB_Button5), - value("MB_Button6", OIS::MB_Button6), - value("MB_Button7", OIS::MB_Button7) - ] - .def("isButtonDown", &Mouse::isButtonDown) - .def("wasButtonPressed", &Mouse::wasButtonPressed) - .def("normalizedPosition", &Mouse::normalizedPosition) - .def("scrollChange", &Mouse::scrollChange) - .def("position", &Mouse::position) - ; +void Mouse::luaBindings( + sol::state &lua +){ + lua.new_usertype("Mouse", + + "new", sol::no_constructor, + + // MB enum + "MB_Left", sol::var(OIS::MB_Left), + "MB_Right", sol::var(OIS::MB_Right), + "MB_Middle", sol::var(OIS::MB_Middle), + "MB_Button3", sol::var(OIS::MB_Button3), + "MB_Button4", sol::var(OIS::MB_Button4), + "MB_Button5", sol::var(OIS::MB_Button5), + "MB_Button6", sol::var(OIS::MB_Button6), + "MB_Button7", sol::var(OIS::MB_Button7), + + "isButtonDown", &Mouse::isButtonDown, + "wasButtonPressed", &Mouse::wasButtonPressed, + "normalizedPosition", &Mouse::normalizedPosition, + "scrollChange", &Mouse::scrollChange, + "position", &Mouse::position + ); } - Mouse::Mouse() : m_impl(new Implementation()) { diff --git a/src/ogre/mouse.h b/src/ogre/mouse.h index 9010b9eb70f..ee3ca0a5686 100644 --- a/src/ogre/mouse.h +++ b/src/ogre/mouse.h @@ -4,8 +4,8 @@ #include #include -namespace luabind { -class scope; +namespace sol { +class state; } namespace Ogre { @@ -39,8 +39,7 @@ class Mouse { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor diff --git a/src/ogre/render_system.cpp b/src/ogre/render_system.cpp index 78b3e591a85..e1961ebd906 100644 --- a/src/ogre/render_system.cpp +++ b/src/ogre/render_system.cpp @@ -1,21 +1,26 @@ #include "ogre/render_system.h" #include "engine/engine.h" +#include "game.h" #include "engine/game_state.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include using namespace thrive; -luabind::scope -RenderSystem::luaBindings() { - using namespace luabind; - return class_("RenderSystem") - .def(constructor<>()) - ; -} +void RenderSystem::luaBindings( + sol::state &lua +){ + lua.new_usertype("RenderSystem", + + sol::constructors>(), + + sol::base_classes, sol::bases(), + "init", &RenderSystem::init + ); +} struct RenderSystem::Implementation { @@ -35,10 +40,10 @@ RenderSystem::~RenderSystem() {} void RenderSystem::init( - GameState* gameState + GameStateData* gameState ) { System::initNamed("RenderSystem", gameState); - m_impl->m_root = this->engine()->ogreRoot(); + m_impl->m_root = Game::instance().engine().ogreRoot(); assert(m_impl->m_root != nullptr && "Root object is null. Initialize the Engine first."); } diff --git a/src/ogre/render_system.h b/src/ogre/render_system.h index 529d33dd807..6f44ae8274e 100644 --- a/src/ogre/render_system.h +++ b/src/ogre/render_system.h @@ -20,8 +20,7 @@ class RenderSystem : public System { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -39,7 +38,7 @@ class RenderSystem : public System { */ void init( - GameState* gameState + GameStateData* gameState ) override; /** diff --git a/src/ogre/scene_node_system.cpp b/src/ogre/scene_node_system.cpp index 71c4362c84d..19bd13becb5 100644 --- a/src/ogre/scene_node_system.cpp +++ b/src/ogre/scene_node_system.cpp @@ -6,7 +6,7 @@ #include "engine/entity_manager.h" #include "engine/game_state.h" #include "engine/serialization.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include "sound/sound_source_system.h" #include "sound/sound_manager.h" @@ -35,101 +35,110 @@ using namespace thrive; static Ogre::String OgreSceneNodeComponent_getMeshName( - const OgreSceneNodeComponent* self + const OgreSceneNodeComponent &self ) { - return self->m_meshName.get(); + return self.m_meshName.get(); } static void OgreSceneNodeComponent_setMeshName( - OgreSceneNodeComponent* self, + OgreSceneNodeComponent &self, const Ogre::String& meshName ) { - self->m_meshName = meshName; + self.m_meshName = meshName; } static bool OgreSceneNodeComponent_getVisible( - const OgreSceneNodeComponent* self + const OgreSceneNodeComponent &self ) { - return self->m_visible.get(); + return self.m_visible.get(); } static void OgreSceneNodeComponent_setVisible( - OgreSceneNodeComponent* self, + OgreSceneNodeComponent &self, bool visible ) { - self->m_visible = visible; // This should automatically call touch().w + self.m_visible = visible; // This should automatically call touch().w } static std::string OgreSceneNodeComponent_getPlaneTexture( - const OgreSceneNodeComponent* self + const OgreSceneNodeComponent &self ) { - return self->m_planeTexture.get(); + return self.m_planeTexture.get(); } static void OgreSceneNodeComponent_setPlaneTexture( - OgreSceneNodeComponent* self, + OgreSceneNodeComponent &self, std::string planeTexture ) { - self->m_planeTexture = planeTexture; // This should automatically call touch().w + self.m_planeTexture = planeTexture; // This should automatically call touch().w } static Entity OgreSceneNodeComponent_getParent( - const OgreSceneNodeComponent* self + const OgreSceneNodeComponent &self ) { - return Entity(self->m_parentId.get()); + return Entity(self.m_parentId.get(), Game::instance().engine(). + getCurrentGameStateFromLua()); } static void OgreSceneNodeComponent_setParent( - OgreSceneNodeComponent* self, + OgreSceneNodeComponent &self, const Entity& entity ) { - self->m_parentId = entity.id(); - self->m_parentId.touch(); -} - - -luabind::scope -OgreSceneNodeComponent::luaBindings() { - using namespace luabind; - return class_("OgreSceneNodeComponent") - .enum_("ID") [ - value("TYPE_ID", OgreSceneNodeComponent::TYPE_ID) - ] - .scope [ - def("TYPE_NAME", &OgreSceneNodeComponent::TYPE_NAME), - class_("Transform") - .def_readwrite("orientation", &Transform::orientation) - .def_readwrite("position", &Transform::position) - .def_readwrite("scale", &Transform::scale) - ] - .def(constructor<>()) - .def("playAnimation", &OgreSceneNodeComponent::playAnimation) - .def("stopAnimation", &OgreSceneNodeComponent::stopAnimation) - .def("stopAllAnimations", &OgreSceneNodeComponent::stopAllAnimations) - .def("setAnimationSpeed", &OgreSceneNodeComponent::setAnimationSpeed) - .def("attachObject", &OgreSceneNodeComponent::attachObject) - .def("attachSoundListener", &OgreSceneNodeComponent::attachSoundListener) - .def_readonly("transform", &OgreSceneNodeComponent::m_transform) - .def_readonly("entity", &OgreSceneNodeComponent::m_entity) - .property("parent", OgreSceneNodeComponent_getParent, OgreSceneNodeComponent_setParent) - .property("meshName", OgreSceneNodeComponent_getMeshName, OgreSceneNodeComponent_setMeshName) - .property("visible", OgreSceneNodeComponent_getVisible, OgreSceneNodeComponent_setVisible) - .property("planeTexture", OgreSceneNodeComponent_getPlaneTexture, OgreSceneNodeComponent_setPlaneTexture) - ; + self.m_parentId = entity.id(); + self.m_parentId.touch(); +} + +void OgreSceneNodeComponent::luaBindings( + sol::state &lua +){ + lua.new_usertype("OgreSceneNodeComponentTransform", + + sol::base_classes, sol::bases(), + + "orientation", &Transform::orientation, + "position", &Transform::position, + "scale", &Transform::scale + ); + + lua.new_usertype("OgreSceneNodeComponent", + + "new", sol::factories([](){ + return std::make_unique(); + }), + + COMPONENT_BINDINGS(OgreSceneNodeComponent), + + "playAnimation", &OgreSceneNodeComponent::playAnimation, + "stopAnimation", &OgreSceneNodeComponent::stopAnimation, + "stopAllAnimations", &OgreSceneNodeComponent::stopAllAnimations, + "setAnimationSpeed", &OgreSceneNodeComponent::setAnimationSpeed, + "attachObject", &OgreSceneNodeComponent::attachObject, + "attachSoundListener", &OgreSceneNodeComponent::attachSoundListener, + "transform", sol::readonly(&OgreSceneNodeComponent::m_transform), + "entity", sol::readonly(&OgreSceneNodeComponent::m_entity), + "parent", sol::property(OgreSceneNodeComponent_getParent, + OgreSceneNodeComponent_setParent), + "meshName", sol::property(OgreSceneNodeComponent_getMeshName, + OgreSceneNodeComponent_setMeshName), + "visible", sol::property(OgreSceneNodeComponent_getVisible, + OgreSceneNodeComponent_setVisible), + "planeTexture", sol::property(OgreSceneNodeComponent_getPlaneTexture, + OgreSceneNodeComponent_setPlaneTexture) + ); } bool OgreSceneNodeComponent::s_soundListenerAttached = false; @@ -219,15 +228,18 @@ REGISTER_COMPONENT(OgreSceneNodeComponent) //////////////////////////////////////////////////////////////////////////////// // OgreAddSceneNodeSystem //////////////////////////////////////////////////////////////////////////////// +void OgreAddSceneNodeSystem::luaBindings( + sol::state &lua +){ + lua.new_usertype("OgreAddSceneNodeSystem", -luabind::scope -OgreAddSceneNodeSystem::luaBindings() { - using namespace luabind; - return class_("OgreAddSceneNodeSystem") - .def(constructor<>()) - ; -} + sol::constructors>(), + + sol::base_classes, sol::bases(), + "init", &OgreAddSceneNodeSystem::init + ); +} struct OgreAddSceneNodeSystem::Implementation { @@ -248,12 +260,12 @@ OgreAddSceneNodeSystem::~OgreAddSceneNodeSystem() {} void OgreAddSceneNodeSystem::init( - GameState* gameState + GameStateData* gameState ) { System::initNamed("OgreAddSceneNodeSystem", gameState); assert(m_impl->m_sceneManager == nullptr && "Double init of system"); m_impl->m_sceneManager = gameState->sceneManager(); - m_impl->m_entities.setEntityManager(&gameState->entityManager()); + m_impl->m_entities.setEntityManager(gameState->entityManager()); } @@ -298,15 +310,18 @@ OgreAddSceneNodeSystem::update(int, int) { //////////////////////////////////////////////////////////////////////////////// // OgreRemoveSceneNodeSystem //////////////////////////////////////////////////////////////////////////////// +void OgreRemoveSceneNodeSystem::luaBindings( + sol::state &lua +){ + lua.new_usertype("OgreRemoveSceneNodeSystem", -luabind::scope -OgreRemoveSceneNodeSystem::luaBindings() { - using namespace luabind; - return class_("OgreRemoveSceneNodeSystem") - .def(constructor<>()) - ; -} + sol::constructors>(), + sol::base_classes, sol::bases(), + + "init", &OgreRemoveSceneNodeSystem::init + ); +} struct OgreRemoveSceneNodeSystem::Implementation { @@ -331,14 +346,14 @@ OgreRemoveSceneNodeSystem::~OgreRemoveSceneNodeSystem() {} void OgreRemoveSceneNodeSystem::init( - GameState* gameState + GameStateData* gameState ) { Ogre::Animation::setDefaultInterpolationMode(Ogre::Animation::IM_LINEAR); Ogre::Animation::setDefaultRotationInterpolationMode(Ogre::Animation::RIM_LINEAR); System::initNamed("OgreRemoveSceneNodeSystem", gameState); assert(m_impl->m_sceneManager == nullptr && "Double init of system"); m_impl->m_sceneManager = gameState->sceneManager(); - m_impl->m_entities.setEntityManager(&gameState->entityManager()); + m_impl->m_entities.setEntityManager(gameState->entityManager()); } @@ -384,13 +399,17 @@ OgreRemoveSceneNodeSystem::update(int, int) { //////////////////////////////////////////////////////////////////////////////// // OgreUpdateSceneNodeSystem //////////////////////////////////////////////////////////////////////////////// +void OgreUpdateSceneNodeSystem::luaBindings( + sol::state &lua +){ + lua.new_usertype("OgreUpdateSceneNodeSystem", + + sol::constructors>(), + + sol::base_classes, sol::bases(), -luabind::scope -OgreUpdateSceneNodeSystem::luaBindings() { - using namespace luabind; - return class_("OgreUpdateSceneNodeSystem") - .def(constructor<>()) - ; + "init", &OgreUpdateSceneNodeSystem::init + ); } @@ -416,11 +435,11 @@ OgreUpdateSceneNodeSystem::~OgreUpdateSceneNodeSystem() {} void OgreUpdateSceneNodeSystem::init( - GameState* gameState + GameStateData* gameState ) { System::initNamed("OgreUpdateSceneNodeSystem", gameState); m_impl->m_sceneManager = gameState->sceneManager(); - m_impl->m_entities.setEntityManager(&gameState->entityManager()); + m_impl->m_entities.setEntityManager(gameState->entityManager()); } @@ -505,7 +524,7 @@ OgreUpdateSceneNodeSystem::update( } if (component->m_planeTexture.get().length() != 0) { Ogre::Plane plane(Ogre::Vector3::UNIT_Z, 0); - std::string planeName("plane" + ++planeNameCounter); + std::string planeName("plane" + std::to_string(++planeNameCounter)); Ogre::MeshManager::getSingleton().createPlane(planeName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, plane, 10000, 10000); diff --git a/src/ogre/scene_node_system.h b/src/ogre/scene_node_system.h index 410c6abe184..fcfb8d1cd7d 100644 --- a/src/ogre/scene_node_system.h +++ b/src/ogre/scene_node_system.h @@ -3,7 +3,6 @@ #include "engine/component.h" #include "engine/system.h" #include "engine/touchable.h" -#include "luabind/object.hpp" #include #include @@ -13,8 +12,8 @@ #include -namespace luabind { -class scope; +namespace sol { +class state; } namespace Ogre { @@ -86,8 +85,8 @@ class OgreSceneNodeComponent : public Component { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); + void load( @@ -238,8 +237,7 @@ class OgreAddSceneNodeSystem : public System { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -255,7 +253,7 @@ class OgreAddSceneNodeSystem : public System { * @brief Initializes the system * */ - void init(GameState* gameState) override; + void init(GameStateData* gameState) override; /** * @brief Shuts the system down @@ -289,8 +287,7 @@ class OgreRemoveSceneNodeSystem : public System { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -306,7 +303,7 @@ class OgreRemoveSceneNodeSystem : public System { * @brief Initializes the system * */ - void init(GameState* gameState) override; + void init(GameStateData* gameState) override; /** * @brief Shuts the system down @@ -339,8 +336,7 @@ class OgreUpdateSceneNodeSystem : public System { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -356,7 +352,7 @@ class OgreUpdateSceneNodeSystem : public System { * @brief Initializes the system * */ - void init(GameState* gameState) override; + void init(GameStateData* gameState) override; /** * @brief Shuts the system down diff --git a/src/ogre/script_bindings.cpp b/src/ogre/script_bindings.cpp deleted file mode 100644 index cc5fb021538..00000000000 --- a/src/ogre/script_bindings.cpp +++ /dev/null @@ -1,647 +0,0 @@ -#include "ogre/script_bindings.h" - -#include "scripting/luabind.h" -#include "ogre/camera_system.h" -#include "ogre/colour_material.h" -#include "ogre/keyboard.h" -#include "ogre/light_system.h" -#include "ogre/mouse.h" -#include "ogre/render_system.h" -#include "ogre/scene_node_system.h" -#include "ogre/script_bindings.h" -#include "ogre/sky_system.h" -#include "scripting/luabind.h" - -#include "ogre/workspace_system.h" - - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace luabind; -using namespace Ogre; - - -static luabind::scope -axisAlignedBoxBindings() { - return class_("AxisAlignedBox") - .enum_("Extent") [ - value("EXTENT_NULL", AxisAlignedBox::EXTENT_NULL), - value("EXTENT_FINITE", AxisAlignedBox::EXTENT_FINITE), - value("EXTENT_INFINITE", AxisAlignedBox::EXTENT_INFINITE) - ] - .enum_("CornerEnum") [ - value("FAR_LEFT_BOTTOM", AxisAlignedBox::FAR_LEFT_BOTTOM), - value("FAR_LEFT_TOP", AxisAlignedBox::FAR_LEFT_TOP), - value("FAR_RIGHT_TOP", AxisAlignedBox::FAR_RIGHT_TOP), - value("FAR_RIGHT_BOTTOM", AxisAlignedBox::FAR_RIGHT_BOTTOM), - value("NEAR_RIGHT_BOTTOM", AxisAlignedBox::NEAR_RIGHT_BOTTOM), - value("NEAR_LEFT_BOTTOM", AxisAlignedBox::NEAR_LEFT_BOTTOM), - value("NEAR_LEFT_TOP", AxisAlignedBox::NEAR_LEFT_TOP), - value("NEAR_RIGHT_TOP", AxisAlignedBox::NEAR_RIGHT_TOP) - ] - .def(constructor<>()) - .def(constructor()) - .def(constructor()) - .def(constructor< - Real, Real, Real, - Real, Real, Real >() - ) - .def(const_self == other()) - .def("getMinimum", - static_cast(&AxisAlignedBox::getMinimum) - ) - .def("getMaximum", - static_cast(&AxisAlignedBox::getMaximum) - ) - .def("setMinimum", - static_cast(&AxisAlignedBox::setMinimum) - ) - .def("setMinimum", - static_cast(&AxisAlignedBox::setMinimum) - ) - .def("setMinimumX", &AxisAlignedBox::setMinimumX) - .def("setMinimumY", &AxisAlignedBox::setMinimumY) - .def("setMinimumZ", &AxisAlignedBox::setMinimumZ) - .def("setMaximum", - static_cast(&AxisAlignedBox::setMaximum) - ) - .def("setMaximum", - static_cast(&AxisAlignedBox::setMaximum) - ) - .def("setMaximumX", &AxisAlignedBox::setMaximumX) - .def("setMaximumY", &AxisAlignedBox::setMaximumY) - .def("setMaximumZ", &AxisAlignedBox::setMaximumZ) - .def("setExtents", - static_cast(&AxisAlignedBox::setExtents) - ) - .def("setExtents", - static_cast(&AxisAlignedBox::setExtents) - ) - .def("getCorner", &AxisAlignedBox::getCorner) - .def("merge", - static_cast(&AxisAlignedBox::merge) - ) - .def("merge", - static_cast(&AxisAlignedBox::merge) - ) - .def("setNull", &AxisAlignedBox::setNull) - .def("isNull", &AxisAlignedBox::isNull) - .def("isFinite", &AxisAlignedBox::isFinite) - .def("setInfinite", &AxisAlignedBox::setInfinite) - .def("isInfinite", &AxisAlignedBox::isInfinite) - .def("intersects", - static_cast(&AxisAlignedBox::intersects) - ) - .def("intersection", &AxisAlignedBox::intersection) - .def("volume", &AxisAlignedBox::volume) - .def("scale", &AxisAlignedBox::scale) - .def("intersects", - static_cast(&AxisAlignedBox::intersects) - ) - .def("intersects", - static_cast(&AxisAlignedBox::intersects) - ) - .def("intersects", - static_cast(&AxisAlignedBox::intersects) - ) - .def("getCenter", &AxisAlignedBox::getCenter) - .def("getSize", &AxisAlignedBox::getSize) - .def("getHalfSize", &AxisAlignedBox::getHalfSize) - .def("contains", - static_cast(&AxisAlignedBox::contains) - ) - .def("distance", &AxisAlignedBox::distance) - .def("contains", - static_cast(&AxisAlignedBox::contains) - ) - ; -} - - -static luabind::scope -colourValueBindings() { - return class_("ColourValue") - .def(constructor()) - .def(const_self == other()) - .def(const_self + other()) - .def(const_self - other()) - .def(const_self * other()) - .def(const_self * other()) - .def(const_self * float()) - .def("saturate", &ColourValue::saturate) - .def("setHSB", &ColourValue::setHSB) - .def("getHSB", &ColourValue::getHSB, - (pure_out_value(_2), pure_out_value(_3), pure_out_value(_4)) - ) - .def_readwrite("r", &ColourValue::r) - .def_readwrite("g", &ColourValue::g) - .def_readwrite("b", &ColourValue::b) - .def_readwrite("a", &ColourValue::a) - ; -} - - -static luabind::scope -degreeBindings() { - return class_("Degree") - .def(constructor()) - .def(constructor()) - .def(const_self == other()) - .def(const_self + other()) - .def(const_self - other()) - .def(const_self * other()) - .def(const_self * Real()) - .def(const_self / Real()) - .def(const_self < other()) - .def("valueDegrees", &Degree::valueDegrees) - ; -} - - -static void -SubEntity_setColour( - SubEntity* self, - const Ogre::ColourValue& colour -) { - auto material = thrive::getColourMaterial(colour); - self->setMaterial(material); -} - -static void -Entity_setColour( - Entity* self, - const Ogre::ColourValue& colour -) { - auto material = thrive::getColourMaterial(colour); - self->setMaterial(material); -} - -static void -SubEntity_setMaterial( - SubEntity* self, - const String& name -) { - Ogre::MaterialManager& manager = Ogre::MaterialManager::getSingleton(); - Ogre::MaterialPtr material = manager.getByName( - name - ); - self->setMaterial(material); -} - -static void -Entity_setMaterial( - Entity* self, - const String& name -) { - Ogre::MaterialManager& manager = Ogre::MaterialManager::getSingleton(); - Ogre::MaterialPtr material = manager.getByName( - name - ); - self->setMaterial(material); -} - -static void -SubEntity_tintColour( - SubEntity* self, - const String& groupName, - const String& materialName, - const Ogre::ColourValue& colour -) { - Ogre::MaterialPtr baseMaterial = Ogre::MaterialManager::getSingleton().getByName(materialName); - Ogre::MaterialPtr materialPtr = baseMaterial->clone(groupName); - materialPtr->compile(); - Ogre::TextureUnitState* ptus = materialPtr->getTechnique(0)->getPass(0)->getTextureUnitState(0); - ptus->setColourOperationEx(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_TEXTURE, colour); - self->setMaterial(materialPtr); -} - -static void -Entity_tintColour( - Entity* self, - const String& materialName, - const Ogre::ColourValue& colour -) { - Ogre::MaterialPtr baseMaterial = Ogre::MaterialManager::getSingleton().getByName(materialName); - Ogre::MaterialPtr materialPtr = baseMaterial->clone(materialName + std::to_string(static_cast(colour.r*256)) - + std::to_string(static_cast(colour.g*256)) + std::to_string(static_cast(colour.b*256))); - materialPtr->compile(); - Ogre::TextureUnitState* ptus = materialPtr->getTechnique(0)->getPass(0)->getTextureUnitState(0); - ptus->setAlphaOperation(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_TEXTURE, colour.a); - ptus->setColourOperationEx(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_TEXTURE, colour); - self->setMaterial(materialPtr); -} - -static int clonedIndex = 0; - -static void -Entity_cloneMaterial( - Entity* self, - const String& materialName -) { - Ogre::MaterialPtr baseMaterial = Ogre::MaterialManager::getSingleton().getByName(materialName); - Ogre::MaterialPtr materialPtr = baseMaterial->clone(materialName + std::to_string(clonedIndex)); - materialPtr->compile(); - self->setMaterialName(materialName + std::to_string(clonedIndex)); - clonedIndex++; -} - -static void -Entity_setMaterialColour( - Entity* self, - //const String& materialName, - const Ogre::ColourValue& colour -) { - //Ogre::MaterialPtr baseMaterial = Ogre::MaterialManager::getSingleton().getByName(materialName); - //Ogre::MaterialPtr materialPtr = baseMaterial->clone(materialName + std::to_string(clonedIndex)); - //materialPtr->compile(); - //self->setMaterialName(materialName + std::to_string(clonedIndex)); - //clonedIndex++; - - Ogre::SubMesh* sub = self->getMesh()->getSubMesh(0); - Ogre::MaterialPtr materialPtr = Ogre::MaterialManager::getSingleton().getByName(sub->getMaterialName()); - Ogre::TextureUnitState* ptus = materialPtr->getTechnique(0)->getPass(0)->getTextureUnitState(0); - ptus->setColourOperationEx(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_TEXTURE, colour); - ptus->setAlphaOperation(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_TEXTURE, colour.a); - //self->setMaterial(materialPtr); -} - -static luabind::scope -entityBindings() { - return ( - class_("OgreSubEntity") - .def("setColour", &SubEntity_setColour) - .def("setMaterial", &SubEntity_setMaterial) - .def("tintColour", &SubEntity_tintColour) - , - class_("OgreEntity") - .def("getSubEntity", static_cast(&Entity::getSubEntity)) - .def("getNumSubEntities", &Entity::getNumSubEntities) - .def("setColour", &Entity_setColour) - .def("setMaterial", &Entity_setMaterial) - .def("cloneMaterial", &Entity_cloneMaterial) - .def("setMaterialColour", &Entity_setMaterialColour) - .def("tintColour", &Entity_tintColour) - ); -} - - - -static luabind::scope -matrix3Bindings() { - return class_("Matrix3") - .def(constructor<>()) - .def(constructor< - Real, Real, Real, - Real, Real, Real, - Real, Real, Real>()) - .def(const_self == other()) - .def(const_self + other()) - .def(const_self - other()) - .def(const_self * other()) - .def(const_self * other()) - .def(const_self * Real()) - .def("GetColumn", &Matrix3::GetColumn) - .def("SetColumn", &Matrix3::SetColumn) - .def("FromAxes", &Matrix3::FromAxes) - .def("Transpose", &Matrix3::Transpose) - .def("Inverse", - static_cast(&Matrix3::Inverse), - pure_out_value(_2) - ) - .def("Determinant", &Matrix3::Determinant) - .def("SingularValueDecomposition", - &Matrix3::SingularValueDecomposition, - (pure_out_value(_2), pure_out_value(_3), pure_out_value(_4)) - ) - .def("SingularValueComposition", &Matrix3::SingularValueComposition) - .def("Orthonormalize", &Matrix3::Orthonormalize) - .def("QDUDecomposition", - &Matrix3::QDUDecomposition, - (pure_out_value(_2), pure_out_value(_3), pure_out_value(_4)) - ) - .def("SpectralNorm", &Matrix3::SpectralNorm) - .def("ToAngleAxis", - static_cast(&Matrix3::ToAngleAxis), - (pure_out_value(_2), pure_out_value(_3)) - ) - .def("FromAngleAxis", &Matrix3::FromAngleAxis) - .def("ToEulerAnglesXYZ", - &Matrix3::ToEulerAnglesXYZ, - (pure_out_value(_2), pure_out_value(_3), pure_out_value(_4)) - ) - .def("ToEulerAnglesXZY", - &Matrix3::ToEulerAnglesXZY, - (pure_out_value(_2), pure_out_value(_3), pure_out_value(_4)) - ) - .def("ToEulerAnglesYXZ", - &Matrix3::ToEulerAnglesYXZ, - (pure_out_value(_2), pure_out_value(_3), pure_out_value(_4)) - ) - .def("ToEulerAnglesYZX", - &Matrix3::ToEulerAnglesYZX, - (pure_out_value(_2), pure_out_value(_3), pure_out_value(_4)) - ) - .def("ToEulerAnglesZXY", - &Matrix3::ToEulerAnglesZXY, - (pure_out_value(_2), pure_out_value(_3), pure_out_value(_4)) - ) - .def("ToEulerAnglesZYX", - &Matrix3::ToEulerAnglesZYX, - (pure_out_value(_2), pure_out_value(_3), pure_out_value(_4)) - ) - .def("FromEulerAnglesXYZ", &Matrix3::FromEulerAnglesXYZ) - .def("FromEulerAnglesXZY", &Matrix3::FromEulerAnglesXZY) - .def("FromEulerAnglesYXZ", &Matrix3::FromEulerAnglesYXZ) - .def("FromEulerAnglesYZX", &Matrix3::FromEulerAnglesYZX) - .def("FromEulerAnglesZXY", &Matrix3::FromEulerAnglesZXY) - .def("FromEulerAnglesZYX", &Matrix3::FromEulerAnglesZYX) - .def("hasScale", &Matrix3::hasScale) - ; -} - - -static luabind::scope -movableObjectBindings() { - return class_("MovableObject"); -} - - -static luabind::scope -planeBindings() { - return class_("Plane") - .enum_("Side") [ - value("NO_SIDE", Plane::NO_SIDE), - value("POSITIVE_SIDE", Plane::POSITIVE_SIDE), - value("NEGATIVE_SIDE", Plane::NEGATIVE_SIDE), - value("BOTH_SIDE", Plane::BOTH_SIDE) - ] - .def(constructor<>()) - .def(constructor()) - .def(constructor()) - .def(constructor()) - .def(constructor()) - .def(const_self == other()) - .def("getSide", - static_cast(&Plane::getSide) - ) - .def("getSide", - static_cast(&Plane::getSide) - ) - .def("getSide", - static_cast(&Plane::getSide) - ) - .def("getDistance", &Plane::getDistance) - .def("redefine", - static_cast(&Plane::redefine) - ) - .def("redefine", - static_cast(&Plane::redefine) - ) - .def("projectVector", &Plane::projectVector) - .def("normalise", &Plane::normalise) - .def_readwrite("normal", &Plane::normal) - .def_readwrite("d", &Plane::d) - ; -} - - -static luabind::scope -quaternionBindings() { - return class_("Quaternion") - .def(constructor<>()) - .def(constructor()) - .def(constructor()) - .def(constructor()) - .def(constructor()) - .def(const_self + other()) - .def(const_self - other()) - .def(const_self * other()) - .def(const_self * Real()) - .def(const_self * other()) - .def(const_self == other()) - .def("FromRotationMatrix", &Quaternion::FromRotationMatrix) - .def("ToRotationMatrix", &Quaternion::ToRotationMatrix, pure_out_value(_2)) - .def("FromAngleAxis", &Quaternion::FromAngleAxis) - .def("ToAngleAxis", - static_cast(&Quaternion::ToAngleAxis), - (pure_out_value(_2), pure_out_value(_3)) - ) - .def("FromAxes", - static_cast(&Quaternion::FromAxes) - ) - .def("ToAxes", - static_cast(&Quaternion::ToAxes), - (pure_out_value(_2), pure_out_value(_3), pure_out_value(_4)) - ) - .def("xAxis", &Quaternion::xAxis) - .def("yAxis", &Quaternion::yAxis) - .def("zAxis", &Quaternion::zAxis) - .def("Dot", &Quaternion::Dot) - .def("Norm", &Quaternion::Norm) - .def("normalise", &Quaternion::normalise) - .def("Inverse", &Quaternion::Inverse) - .def("UnitInverse", &Quaternion::UnitInverse) - .def("Exp", &Quaternion::Exp) - .def("Log", &Quaternion::Log) - .def("getRoll", &Quaternion::getRoll) - .def("getPitch", &Quaternion::getPitch) - .def("getYaw", &Quaternion::getYaw) - .def("equals", &Quaternion::equals) - .def("isNaN", &Quaternion::isNaN) - ; -} - - -static luabind::scope -radianBindings() { - return class_("Radian") - .def(constructor()) - .def(constructor()) - .def(const_self == other()) - .def(const_self + other()) - .def(const_self - other()) - .def(const_self * other()) - .def(const_self * Real()) - .def(const_self / Real()) - .def(const_self < other()) - .def("valueDegrees", &Radian::valueDegrees) - .def("valueRadians", &Radian::valueRadians) - .def("valueAngleUnits", &Radian::valueAngleUnits) - ; -} - - -static bool -Ray_intersects( - const Ray* self, - const Plane& plane, - Real& t -) { - bool intersects = false; - std::tie(intersects, t) = self->intersects(plane); - return intersects; -} - -static luabind::scope -rayBindings() { - return class_("Ray") - .def(constructor<>()) - .def(constructor()) - .def(const_self * Real()) - .def("setOrigin", &Ray::setOrigin) - .def("getOrigin", &Ray::getOrigin) - .def("setDirection", &Ray::setDirection) - .def("getDirection", &Ray::getDirection) - .def("getPoint", &Ray::getPoint) - .def("intersects", Ray_intersects, pure_out_value(_3)) - ; -} - -static luabind::scope -sceneManagerBindings() { - return class_("SceneManager") - .enum_("PrefabType") [ - value("PT_PLANE", SceneManager::PT_PLANE), - value("PT_CUBE", SceneManager::PT_CUBE), - value("PT_SPHERE", SceneManager::PT_SPHERE) - ] - // Fails to compile after upgrade to 2.0 - // .def("createEntity", - // static_cast(&SceneManager::createEntity) - // ) - // .def("createEntity", - // static_cast(&SceneManager::createEntity) - // ) - .def("setAmbientLight", &SceneManager::setAmbientLight) - ; -} - - -static luabind::scope -sphereBindings() { - return class_("Sphere") - .def(constructor<>()) - .def(constructor()) - .def("getRadius", &Sphere::getRadius) - .def("setRadius", &Sphere::setRadius) - .def("getCenter", &Sphere::getCenter) - .def("setCenter", &Sphere::setCenter) - .def("intersects", - static_cast(&Sphere::intersects) - ) - .def("intersects", - static_cast(&Sphere::intersects) - ) - .def("intersects", - static_cast(&Sphere::intersects) - ) - .def("intersects", - static_cast(&Sphere::intersects) - ) - .def("merge", &Sphere::merge) - ; -} - - -static luabind::scope -vector3Bindings() { - return class_("Vector3") - .def(constructor<>()) - .def(constructor()) - .def(const_self == other()) - .def(const_self + other()) - .def(const_self - other()) - .def(const_self * Real()) - .def(Real() * const_self) - .def(const_self * other()) - .def(const_self / Real()) - .def(const_self / other()) - .def(const_self < other()) - .def(tostring(self)) - .def_readwrite("x", &Vector3::x) - .def_readwrite("y", &Vector3::y) - .def_readwrite("z", &Vector3::z) - .def("length", &Vector3::length) - .def("squaredLength", &Vector3::squaredLength) - .def("distance", &Vector3::distance) - .def("squaredDistance", &Vector3::squaredDistance) - .def("dotProduct", &Vector3::dotProduct) - .def("absDotProduct", &Vector3::absDotProduct) - .def("normalise", &Vector3::normalise) - .def("crossProduct", &Vector3::crossProduct) - .def("midPoint", &Vector3::midPoint) - .def("makeFloor", &Vector3::makeFloor) - .def("makeCeil", &Vector3::makeCeil) - .def("perpendicular", &Vector3::perpendicular) - .def("randomDeviant", &Vector3::randomDeviant) - .def("angleBetween", &Vector3::angleBetween) - .def("getRotationTo", &Vector3::getRotationTo) - .def("isZeroLength", &Vector3::isZeroLength) - .def("normalisedCopy", &Vector3::normalisedCopy) - .def("reflect", &Vector3::reflect) - .def("positionEquals", &Vector3::positionEquals) - .def("positionCloses", &Vector3::positionCloses) - .def("directionEquals", &Vector3::directionEquals) - .def("isNaN", &Vector3::isNaN) - .def("primaryAxis", &Vector3::primaryAxis) - ; -} - -luabind::scope -thrive::OgreBindings::luaBindings() { - return ( - // Math - axisAlignedBoxBindings(), - colourValueBindings(), - degreeBindings(), - matrix3Bindings(), - planeBindings(), - quaternionBindings(), - radianBindings(), - rayBindings(), - sphereBindings(), - vector3Bindings(), - // Scene Manager - sceneManagerBindings(), - movableObjectBindings(), - entityBindings(), - // Components - OgreCameraComponent::luaBindings(), - OgreLightComponent::luaBindings(), - OgreSceneNodeComponent::luaBindings(), - SkyPlaneComponent::luaBindings(), - OgreWorkspaceComponent::luaBindings(), - // Systems - OgreAddSceneNodeSystem::luaBindings(), - OgreCameraSystem::luaBindings(), - OgreLightSystem::luaBindings(), - OgreRemoveSceneNodeSystem::luaBindings(), - OgreUpdateSceneNodeSystem::luaBindings(), - thrive::RenderSystem::luaBindings(), // Fully qualified because of Ogre::RenderSystem - SkySystem::luaBindings(), - OgreWorkspaceSystem::luaBindings(), - // Other - Keyboard::luaBindings(), - Mouse::luaBindings() - ); -} diff --git a/src/ogre/script_bindings.h b/src/ogre/script_bindings.h deleted file mode 100644 index 1db02c1437e..00000000000 --- a/src/ogre/script_bindings.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -namespace luabind { -class scope; -} - -namespace thrive { - -/** -* @brief Helper for OGRE script bindings -*/ -struct OgreBindings { - - /** - * @brief Lua bindings for OGRE - * - * The exposed classes try to be as close to the C++ OGRE API as - * possible. - * - * The currently exported classes are - * - AxisAlignedBox - * - ColourValue - * - Matrix3 - * - Plane - * - Quaternion - * - Radian - * - Sphere - * - Vector3 - */ - static luabind::scope - luaBindings(); - -}; - -} diff --git a/src/ogre/sky_system.cpp b/src/ogre/sky_system.cpp index ac827e55073..4a5ec62e434 100644 --- a/src/ogre/sky_system.cpp +++ b/src/ogre/sky_system.cpp @@ -4,7 +4,7 @@ #include "engine/game_state.h" #include "engine/entity_filter.h" #include "engine/serialization.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include #include @@ -15,34 +15,37 @@ using namespace thrive; // SkyPlaneComponent //////////////////////////////////////////////////////////////////////////////// - -luabind::scope -SkyPlaneComponent::luaBindings() { - using namespace luabind; - return class_("SkyPlaneComponent") - .enum_("ID") [ - value("TYPE_ID", SkyPlaneComponent::TYPE_ID) - ] - .scope [ - def("TYPE_NAME", &SkyPlaneComponent::TYPE_NAME), - class_("Properties") - .def_readwrite("enabled", &Properties::enabled) - .def_readwrite("plane", &Properties::plane) - .def_readwrite("materialName", &Properties::materialName) - .def_readwrite("scale", &Properties::scale) - .def_readwrite("tiling", &Properties::tiling) - .def_readwrite("drawFirst", &Properties::drawFirst) - .def_readwrite("bow", &Properties::bow) - .def_readwrite("xsegments", &Properties::xsegments) - .def_readwrite("ysegments", &Properties::ysegments) - .def_readwrite("groupName", &Properties::groupName) - ] - .def(constructor<>()) - .def_readonly("properties", &SkyPlaneComponent::m_properties) - ; +void SkyPlaneComponent::luaBindings( + sol::state &lua +){ + lua.new_usertype("SkyPlaneComponentProperties", + + sol::base_classes, sol::bases(), + + "enabled", &Properties::enabled, + "plane", &Properties::plane, + "materialName", &Properties::materialName, + "scale", &Properties::scale, + "tiling", &Properties::tiling, + "drawFirst", &Properties::drawFirst, + "bow", &Properties::bow, + "xsegments", &Properties::xsegments, + "ysegments", &Properties::ysegments, + "groupName", &Properties::groupName + ); + + lua.new_usertype("SkyPlaneComponent", + + "new", sol::factories([](){ + return std::make_unique(); + }), + + COMPONENT_BINDINGS(SkyPlaneComponent), + + "properties", sol::readonly(&SkyPlaneComponent::m_properties) + ); } - void SkyPlaneComponent::load( const StorageContainer& storage @@ -84,14 +87,18 @@ REGISTER_COMPONENT(SkyPlaneComponent) // SkySystem //////////////////////////////////////////////////////////////////////////////// -luabind::scope -SkySystem::luaBindings() { - using namespace luabind; - return class_("SkySystem") - .def(constructor<>()) - ; -} +void SkySystem::luaBindings( + sol::state &lua +){ + lua.new_usertype("SkySystem", + sol::constructors>(), + + sol::base_classes, sol::bases(), + + "init", &SkySystem::init + ); +} struct SkySystem::Implementation { @@ -114,12 +121,12 @@ SkySystem::~SkySystem() {} void SkySystem::init( - GameState* gameState + GameStateData* gameState ) { System::initNamed("SkySystem", gameState); assert(m_impl->m_sceneManager == nullptr && "Double init of system"); m_impl->m_sceneManager = gameState->sceneManager(); - m_impl->m_skyPlanes.setEntityManager(&gameState->entityManager()); + m_impl->m_skyPlanes.setEntityManager(gameState->entityManager()); } diff --git a/src/ogre/sky_system.h b/src/ogre/sky_system.h index 20027a863f0..3a2c835ccbe 100644 --- a/src/ogre/sky_system.h +++ b/src/ogre/sky_system.h @@ -8,8 +8,8 @@ #include #include -namespace luabind { -class scope; +namespace sol { +class state; } namespace thrive { @@ -102,8 +102,7 @@ class SkyPlaneComponent : public Component { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); void load( @@ -137,8 +136,7 @@ class SkySystem : public System { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -154,7 +152,7 @@ class SkySystem : public System { * @brief Initializes the system * */ - void init(GameState* gameState) override; + void init(GameStateData* gameState) override; /** * @brief Shuts the system down diff --git a/src/ogre/tests/script_bindings.cpp b/src/ogre/tests/script_bindings.cpp index a64723a4ed2..03b8f82c79c 100644 --- a/src/ogre/tests/script_bindings.cpp +++ b/src/ogre/tests/script_bindings.cpp @@ -1,28 +1,28 @@ -#include "ogre/script_bindings.h" - -#include "scripting/lua_state.h" #include "scripting/script_initializer.h" +#include "scripting/luajit.h" + #include -#include #include using namespace Ogre; -using namespace luabind; using namespace thrive; TEST(OgreVector3, Lua) { - LuaState L; - initializeLua(L); - object globals = luabind::globals(L); - L.doString( + + sol::state lua; + + initializeLua(lua); + + lua.do_string( "a = Vector3(1, 2, 3)\n" "b = Vector3(10, 20, 30)\n" "sum = a + b\n" "dot = a:dotProduct(b)\n" ); - Vector3 sum = object_cast(globals["sum"]); - Real dot = object_cast(globals["dot"]); + + Vector3 sum = lua.get("sum"); + Real dot = lua.get("dot"); EXPECT_EQ(Vector3(11, 22, 33), sum); EXPECT_EQ(140, dot); } diff --git a/src/ogre/tests/sky_system.cpp b/src/ogre/tests/sky_system.cpp index 3226099f83c..fc67e333383 100644 --- a/src/ogre/tests/sky_system.cpp +++ b/src/ogre/tests/sky_system.cpp @@ -1,31 +1,35 @@ #include "ogre/sky_system.h" -#include "ogre/script_bindings.h" -#include "scripting/lua_state.h" -#include "scripting/tests/do_string_assertion.h" #include "scripting/script_initializer.h" + +#include "scripting/luajit.h" + #include "util/make_unique.h" #include -#include using namespace thrive; TEST(SkyPlaneComponent, ScriptBindings) { - LuaState L; - initializeLua(L); - luabind::object globals = luabind::globals(L); + sol::state lua; + + initializeLua(lua); + auto skyPlane = make_unique(); - globals["skyPlane"] = skyPlane.get(); + lua["skyPlane"] = skyPlane.get(); + + ; + // Enabled - EXPECT_TRUE(LuaSuccess(L, - "skyPlane.properties.enabled = false" - )); + EXPECT_TRUE( + lua.do_string("skyPlane.properties.enabled = false").valid() + ); + EXPECT_FALSE(skyPlane->m_properties.enabled); // Plane.d - EXPECT_TRUE(LuaSuccess(L, - "skyPlane.properties.plane.d = 42.0" - )); + EXPECT_TRUE( + lua.do_string("skyPlane.properties.plane.d = 42.0").valid() + ); EXPECT_EQ(42.0f, skyPlane->m_properties.plane.d); } diff --git a/src/ogre/text_overlay.cpp b/src/ogre/text_overlay.cpp deleted file mode 100644 index e730ab78368..00000000000 --- a/src/ogre/text_overlay.cpp +++ /dev/null @@ -1,288 +0,0 @@ -#include "ogre/text_overlay.h" - -#include "engine/component_factory.h" -#include "engine/game_state.h" -#include "engine/entity_filter.h" -#include "engine/serialization.h" -#include "scripting/luabind.h" - -#include -#include - -using namespace thrive; - -//////////////////////////////////////////////////////////////////////////////// -// TextOverlayComponent -//////////////////////////////////////////////////////////////////////////////// - - -luabind::scope -TextOverlayComponent::luaBindings() { - using namespace luabind; - return class_("TextOverlayComponent") - .enum_("HorizontalAlignment") [ - value("Left", Ogre::GHA_LEFT), - value("Center", Ogre::GHA_CENTER), - value("Right", Ogre::GHA_RIGHT) - ] - .enum_("VerticalAlignment") [ - value("Top", Ogre::GVA_TOP), - value("Center", Ogre::GVA_CENTER), - value("Bottom", Ogre::GVA_BOTTOM) - ] - .enum_("ID") [ - value("TYPE_ID", TextOverlayComponent::TYPE_ID) - ] - .scope [ - def("TYPE_NAME", &TextOverlayComponent::TYPE_NAME), - class_("Properties") - .def_readwrite("charHeight", &Properties::charHeight) - .def_readwrite("colour", &Properties::colour) - .def_readwrite("fontName", &Properties::fontName) - .def_readwrite("height", &Properties::height) - .def_readwrite("horizontalAlignment", &Properties::horizontalAlignment) - .def_readwrite("left", &Properties::left) - .def_readwrite("text", &Properties::text) - .def_readwrite("top", &Properties::top) - .def_readwrite("verticalAlignment", &Properties::verticalAlignment) - .def_readwrite("width", &Properties::width) - ] - .def(constructor()) - .def("name", &TextOverlayComponent::name) - .def_readonly("properties", &TextOverlayComponent::m_properties) - ; -} - -TextOverlayComponent::TextOverlayComponent( - Ogre::String name -) : m_name(name) -{ -} - - -TextOverlayComponent::TextOverlayComponent() {} - - -void -TextOverlayComponent::load( - const StorageContainer& storage -) { - Component::load(storage); - m_name = storage.get("name", ""); - m_properties.charHeight = storage.get("charHeight", 16.0f); - m_properties.colour = storage.get("colour", Ogre::ColourValue::White); - m_properties.fontName = storage.get("fontName", "Thrive"); - m_properties.height = storage.get("height", 100.0f); - m_properties.horizontalAlignment = static_cast( - storage.get("horizontalAlignment", Ogre::GHA_LEFT) - ); - m_properties.left = storage.get("left", 0.0f); - m_properties.text = storage.get("text", ""); - m_properties.top = storage.get("top", 0.0f); - m_properties.verticalAlignment = static_cast( - storage.get("verticalAlignment", Ogre::GVA_TOP) - ); - m_properties.width = storage.get("width", 100.0f); -} - - -StorageContainer -TextOverlayComponent::storage() const { - StorageContainer storage = Component::storage(); - storage.set("name", m_name); - storage.set("charHeight", m_properties.charHeight); - storage.set("colour", m_properties.colour); - storage.set("fontName", m_properties.fontName); - storage.set("height", m_properties.height); - storage.set("horizontalAlignment", m_properties.horizontalAlignment); - storage.set("left", m_properties.left); - storage.set("text", m_properties.text); - storage.set("top", m_properties.top); - storage.set("verticalAlignment", m_properties.verticalAlignment); - storage.set("width", m_properties.width); - return storage; -} - - -REGISTER_COMPONENT(TextOverlayComponent) - - -//////////////////////////////////////////////////////////////////////////////// -// TextOverlaySystem -//////////////////////////////////////////////////////////////////////////////// - -luabind::scope -TextOverlaySystem::luaBindings() { - using namespace luabind; - return class_("TextOverlaySystem") - .def(constructor<>()) - ; -} - - -struct TextOverlaySystem::Implementation { - - Implementation() { - m_overlayManager = Ogre::OverlayManager::getSingletonPtr(); - Ogre::Overlay* overlay = m_overlayManager->getByName("text_overlay"); - if (not overlay) { - overlay = m_overlayManager->create("text_overlay"); - } - m_overlay = overlay; - Ogre::OverlayElement* panelElement = nullptr; - if (m_overlayManager->hasOverlayElement("text_panel")) { - panelElement = m_overlayManager->getOverlayElement("text_panel"); - } - else { - panelElement = m_overlayManager->createOverlayElement("Panel", "text_panel"); - } - m_panel = static_cast(panelElement); - m_panel->setDimensions(1.0, 1.0); - m_panel->setPosition(0.0, 0.0); - m_overlay->add2D(m_panel); - } - - void - removeAllOverlays() { - for (const auto& item : m_entities) { - TextOverlayComponent* component = std::get<0>(item.second); - this->removeOverlayElement(component->name()); - component->m_overlayElement = nullptr; - } - m_textOverlays.clear(); - } - - void - removeOverlayElement( - const std::string& name - ) { - m_panel->removeChild(name); - m_overlayManager->destroyOverlayElement(name); - } - - void - restoreAllOverlays() { - for (const auto& item : m_entities) { - EntityId entityId = item.first; - TextOverlayComponent* component = std::get<0>(item.second); - this->restoreOverlayElement(entityId, component); - } - } - - void - restoreOverlayElement( - EntityId entityId, - TextOverlayComponent* component - ) { - if (component->m_overlayElement) { - // No need for restoring - return; - } - auto textOverlayElement = static_cast( - m_overlayManager->createOverlayElement( - "TextArea", - component->name() - ) - ); - component->m_overlayElement = textOverlayElement; - m_textOverlays[entityId] = textOverlayElement; - m_panel->addChild(textOverlayElement); - textOverlayElement->setMetricsMode(Ogre::GMM_PIXELS); - } - - EntityFilter< - TextOverlayComponent - > m_entities = {true}; - - Ogre::Overlay* m_overlay = nullptr; - - Ogre::OverlayManager* m_overlayManager = nullptr; - - Ogre::OverlayContainer* m_panel = nullptr; - - std::unordered_map m_textOverlays; -}; - - -TextOverlaySystem::TextOverlaySystem() - : m_impl(new Implementation()) -{ -} - - -TextOverlaySystem::~TextOverlaySystem() {} - - -void -TextOverlaySystem::activate() { - m_impl->restoreAllOverlays(); - m_impl->m_entities.clearChanges(); -} - - -void -TextOverlaySystem::deactivate() { - m_impl->removeAllOverlays(); -} - - -void -TextOverlaySystem::init( - GameState* gameState -) { - System::init(gameState); - m_impl->m_entities.setEntityManager(&gameState->entityManager()); - m_impl->m_overlay->show(); -} - - -void -TextOverlaySystem::shutdown() { - m_impl->m_overlay->hide(); - m_impl->m_entities.setEntityManager(nullptr); - System::shutdown(); -} - - -void -TextOverlaySystem::update(int, int) { - for (EntityId entityId : m_impl->m_entities.removedEntities()) { - Ogre::OverlayElement* textOverlay = m_impl->m_textOverlays[entityId]; - m_impl->removeOverlayElement(textOverlay->getName()); - m_impl->m_textOverlays.erase(entityId); - } - for (auto& value : m_impl->m_entities.addedEntities()) { - EntityId entityId = value.first; - TextOverlayComponent* component = std::get<0>(value.second); - m_impl->restoreOverlayElement( - entityId, - component - ); - } - m_impl->m_entities.clearChanges(); - for (auto& value : m_impl->m_entities) { - TextOverlayComponent* textOverlayComponent = std::get<0>(value.second); - auto& properties = textOverlayComponent->m_properties; - if (properties.hasChanges()) { - Ogre::TextAreaOverlayElement* textOverlay = textOverlayComponent->m_overlayElement; - textOverlay->setPosition( - properties.left, - properties.top - ); - textOverlay->setDimensions( - properties.width, - properties.height - ); - textOverlay->setCharHeight(properties.charHeight); - textOverlay->setColour(properties.colour); - textOverlay->setFontName(properties.fontName); - textOverlay->setCaption(properties.text); - textOverlay->setHorizontalAlignment(properties.horizontalAlignment); - textOverlay->setVerticalAlignment(properties.verticalAlignment); - // Untouch - properties.untouch(); - } - } -} - - diff --git a/src/ogre/text_overlay.h b/src/ogre/text_overlay.h deleted file mode 100644 index f85ffdfdcad..00000000000 --- a/src/ogre/text_overlay.h +++ /dev/null @@ -1,206 +0,0 @@ -#pragma once - -#include "engine/component.h" -#include "engine/system.h" -#include "engine/touchable.h" - -#include -#include - -namespace luabind { - class scope; -} - -namespace thrive { - -/** -* @brief A component for a text overlay -*/ -class TextOverlayComponent : public Component { - COMPONENT(TextOverlay) - -public: - - /** - * @brief Properties - */ - struct Properties : public Touchable { - - /** - * @brief The character height in pixels - */ - Ogre::Real charHeight = 16.0f; - - /** - * @brief Text colour - */ - Ogre::ColourValue colour = Ogre::ColourValue::White; - - /** - * @brief Font name - */ - Ogre::String fontName = "Thrive"; - - /** - * @brief Textbox height in pixels - */ - Ogre::Real height = 100.0f; - - /** - * @brief Horizontal alignment relative to screen - */ - Ogre::GuiHorizontalAlignment horizontalAlignment = Ogre::GHA_LEFT; - - /** - * @brief Offset relative to screen anchor in pixels. - * - * Positive is to the right. - */ - Ogre::Real left = 0.0; - - /** - * @brief Text to display - */ - Ogre::String text = ""; - - /** - * @brief Offset relative to screen anchor in pixels. - * - * Positive is downwards - */ - Ogre::Real top = 0.0; - - /** - * @brief Vertical alignment relative to screen - */ - Ogre::GuiVerticalAlignment verticalAlignment = Ogre::GVA_TOP; - - /** - * @brief Textbox width in pixels - */ - Ogre::Real width = 100.0f; - }; - - /** - * @brief Lua bindings - * - * Exposes: - * - TextOverlayComponent(std::string) - * - Properties - * - Properties::charHeight - * - Properties::colour - * - Properties::fontName - * - Properties::height - * - Properties::horizontalAlignment - * - Properties::left - * - Properties::text - * - Properties::top - * - Properties::verticalAlignment - * - Properties::width - * - * @return - */ - static luabind::scope - luaBindings(); - - /** - * @brief Constructor - * - * @param name - * The overlay's name, must be unique - */ - TextOverlayComponent( - Ogre::String name - ); - - TextOverlayComponent(); - - void - load( - const StorageContainer& storage - ) override; - - /** - * @brief The overlay's name - * - */ - Ogre::String - name() const { - return m_name; - } - - StorageContainer - storage() const override; - - /** - * @brief Pointer to internal overlay element - */ - Ogre::TextAreaOverlayElement* m_overlayElement = nullptr; - - /** - * @brief Properties - */ - Properties m_properties; - -private: - - Ogre::String m_name; -}; - - -/** -* @brief Creates, updates and removes text overlays -*/ -class TextOverlaySystem : public System { - -public: - - /** - * @brief Lua bindings - * - * Exposes: - * - TextOverlaySystem() - * - * @return - */ - static luabind::scope - luaBindings(); - - /** - * @brief Constructor - */ - TextOverlaySystem(); - - /** - * @brief Destructor - */ - ~TextOverlaySystem(); - - void activate() override; - - void deactivate() override; - - /** - * @brief Initializes the system - * - */ - void init(GameState* gameState) override; - - /** - * @brief Shuts the system down - */ - void shutdown() override; - - /** - * @brief Updates the system - */ - void update(int, int) override; - -private: - - struct Implementation; - std::unique_ptr m_impl; - -}; - -} diff --git a/src/ogre/viewport_system.cpp b/src/ogre/viewport_system.cpp deleted file mode 100644 index c49fc59b169..00000000000 --- a/src/ogre/viewport_system.cpp +++ /dev/null @@ -1,281 +0,0 @@ -#include "ogre/viewport_system.h" - -#include "engine/component_factory.h" -#include "engine/engine.h" -#include "engine/entity.h" -#include "engine/entity_filter.h" -#include "engine/entity_manager.h" -#include "engine/game_state.h" -#include "engine/serialization.h" -#include "game.h" -#include "ogre/camera_system.h" -#include "scripting/luabind.h" - -#include -#include -#include - -#include - -using namespace thrive; - -//////////////////////////////////////////////////////////////////////////////// -// OgreViewport -//////////////////////////////////////////////////////////////////////////////// - -static Entity -Properties_getCameraEntity( - const OgreViewportComponent::Properties* self -) { - return Entity(self->cameraEntity); -} - - -static void -Properties_setCameraEntity( - OgreViewportComponent::Properties* self, - const Entity& entity -) { - self->cameraEntity = entity.id(); -} - - -luabind::scope -OgreViewportComponent::luaBindings() { - using namespace luabind; - return class_("OgreViewportComponent") - .scope [ - class_("Properties") - .def_readwrite("backgroundColour", &Properties::backgroundColour) - .property("cameraEntity", Properties_getCameraEntity, Properties_setCameraEntity) - .def_readwrite("height", &Properties::height) - .def_readwrite("left", &Properties::left) - .def_readwrite("top", &Properties::top) - .def_readwrite("width", &Properties::width) - ] - .def(constructor()) - .def_readonly("properties", &OgreViewportComponent::m_properties) - .property("zOrder", &OgreViewportComponent::m_zOrder) - ; -} - -OgreViewportComponent::OgreViewportComponent( - int zOrder -) : m_zOrder(zOrder) -{ -} - - -void -OgreViewportComponent::load( - const StorageContainer& storage -) { - Component::load(storage); - m_properties.backgroundColour = storage.get("backgroundColour"); - m_properties.cameraEntity = storage.get("cameraEntity"); - m_properties.height = storage.get("height"); - m_properties.left = storage.get("left"); - m_properties.top = storage.get("top"); - m_properties.width = storage.get("width"); - m_zOrder = storage.get("zOrder"); -} - - -StorageContainer -OgreViewportComponent::storage() const { - StorageContainer storage = Component::storage(); - storage.set("backgroundColour", m_properties.backgroundColour); - storage.set("cameraEntity", m_properties.cameraEntity); - storage.set("height", m_properties.height); - storage.set("left", m_properties.left); - storage.set("top", m_properties.top); - storage.set("width", m_properties.width); - storage.set("zOrder", m_zOrder); - return storage; -} - - -int -OgreViewportComponent::zOrder() const { - return m_zOrder; -} - -REGISTER_COMPONENT(OgreViewportComponent) -//////////////////////////////////////////////////////////////////////////////// -// OgreViewportSystem -//////////////////////////////////////////////////////////////////////////////// - - -luabind::scope -OgreViewportSystem::luaBindings() { - using namespace luabind; - return class_("OgreViewportSystem") - .def(constructor<>()) - ; -} - - -struct OgreViewportSystem::Implementation { - - - Implementation( - OgreViewportSystem& system - ) : m_system(system) - { - } - - - void - removeAllViewports() { - for (const auto& item : m_entities) { - OgreViewportComponent* viewportComponent = std::get<0>(item.second); - viewportComponent->m_viewport = nullptr; - } - for (const auto& pair : m_viewports) { - this->removeViewport(pair.second); - } - m_viewports.clear(); - } - - void - removeViewport( - Ogre::Viewport* viewport - ) { - m_renderWindow->removeViewport( - viewport->getZOrder() - ); - } - - - void - restoreAllViewports() { - for (const auto& item : m_entities) { - EntityId entityId = item.first; - OgreViewportComponent* component = std::get<0>(item.second); - this->restoreViewport(entityId, component); - } - } - - void - restoreViewport( - EntityId entityId, - OgreViewportComponent* component - ) { - if (component->m_viewport) { - // No need to restore - return; - } - // Find camera (if any) - Ogre::Camera* camera = nullptr; - auto cameraComponent = m_system.entityManager()->getComponent( - component->m_properties.cameraEntity - ); - if (cameraComponent) { - camera = cameraComponent->m_camera; - } - // Create viewport - Ogre::Viewport* viewport = m_renderWindow->addViewport( - camera, - component->zOrder() - ); - component->m_viewport = viewport; - m_viewports.emplace( - entityId, - viewport - ); - } - - EntityFilter m_entities = {true}; - - Ogre::RenderWindow* m_renderWindow = nullptr; - - OgreViewportSystem& m_system; - - std::unordered_map m_viewports; - -}; - - -OgreViewportSystem::OgreViewportSystem() - : m_impl(new Implementation(*this)) -{ -} - - -OgreViewportSystem::~OgreViewportSystem() {} - - -void -OgreViewportSystem::activate() { - m_impl->restoreAllViewports(); - m_impl->m_entities.clearChanges(); -} - - -void -OgreViewportSystem::deactivate() { - m_impl->removeAllViewports(); -} - - -void -OgreViewportSystem::init( - GameState* gameState -) { - System::init(gameState); - m_impl->m_renderWindow = this->engine()->renderWindow(); - m_impl->m_entities.setEntityManager(&gameState->entityManager()); -} - - - - -void -OgreViewportSystem::shutdown() { - m_impl->m_entities.setEntityManager(nullptr); - m_impl->m_renderWindow = nullptr; - System::shutdown(); -} - - -void -OgreViewportSystem::update(int, int) { - for (EntityId id : m_impl->m_entities.removedEntities()) { - Ogre::Viewport* viewport = m_impl->m_viewports[id]; - m_impl->removeViewport(viewport); - } - for (const auto& item : m_impl->m_entities.addedEntities()) { - EntityId entityId = item.first; - OgreViewportComponent* component = std::get<0>(item.second); - m_impl->restoreViewport(entityId, component); - } - m_impl->m_entities.clearChanges(); - for (const auto& item : m_impl->m_entities) { - OgreViewportComponent* viewportComponent = std::get<0>(item.second); - auto& properties = viewportComponent->m_properties; - if (properties.hasChanges()) { - Ogre::Viewport* viewport = viewportComponent->m_viewport; - auto cameraComponent = this->entityManager()->getComponent( - properties.cameraEntity - ); - if (cameraComponent) { - viewport->setCamera(cameraComponent->m_camera); - } - else { - viewport->setCamera(nullptr); - } - viewport->setDimensions( - properties.left, - properties.top, - properties.width, - properties.height - ); - viewport->setBackgroundColour( - properties.backgroundColour - ); - properties.untouch(); - } - } -} - - diff --git a/src/ogre/viewport_system.h b/src/ogre/viewport_system.h deleted file mode 100644 index a006a95d68c..00000000000 --- a/src/ogre/viewport_system.h +++ /dev/null @@ -1,209 +0,0 @@ -#pragma once - -#include "engine/component.h" -#include "engine/system.h" -#include "engine/touchable.h" - -#include -#include -#include - -namespace luabind { -class scope; -} - -namespace Ogre { -class Viewport; -} - -namespace thrive { - -/** -* @brief A proxy for Ogre::Viewport -* -*/ -class OgreViewportComponent : public Component { - COMPONENT(OgreViewport) - -public: - - /** - * @brief Properties - */ - struct Properties : public Touchable { - - /** - * @brief The viewport's background colour - */ - Ogre::ColourValue backgroundColour; - - /** - * @brief The camera entity to use - * - * If the given entity has no OgreCameraComponent, the viewport - * will stay black - */ - EntityId cameraEntity = NULL_ENTITY; - - /** - * @brief The viewport's height relative to the window - * - * The coordinate system is relative, i.e. 0.5 is half height, - * 1.0 is full height. - */ - Ogre::Real height = 1.0f; - - /** - * @brief Left edge of the viewport within the window - * - * The coordinate system is relative, i.e. 0.0 is leftmost, - * 1.0 is rightmost. - */ - Ogre::Real left = 0.0f; - - /** - * @brief Top edge of the viewport within the window - * - * The coordinate system is relative, i.e. 0.0 is topmost, - * 1.0 is bottommost. - */ - Ogre::Real top = 0.0f; - - /** - * @brief The viewport's width relative to the window - * - * The coordinate system is relative, i.e. 0.5 is half width, - * 1.0 is full width. - */ - Ogre::Real width = 1.0f; - - }; - - /** - * @brief Lua bindings - * - * Exposes: - * - OgreViewport(int) - * - @link m_properties properties @endlink - * - Properties - * - Properties::backgroundColour - * - Properties::cameraEntity - * - Properties::height - * - Properties::left - * - Properties::top - * - Properties::width - * - Properties::zOrder - * - * @return - */ - static luabind::scope - luaBindings(); - - /** - * @brief Constructor - * - * @param zOrder - * The lower, the further to the front - */ - OgreViewportComponent( - int zOrder = 0 - ); - - void - load( - const StorageContainer& storage - ) override; - - StorageContainer - storage() const override; - - /** - * @brief The viewport's z order - * - * Higher z orders lay on top of lower ones - * - */ - int - zOrder() const; - - /** - * @brief Properties - */ - Properties - m_properties; - - /** - * @brief Pointer to internal Ogre::Viewport - */ - Ogre::Viewport* m_viewport = nullptr; - -private: - - /** - * @brief The viewport's zOrder - */ - int32_t m_zOrder = 0; - - -}; - - -/** -* @brief Creates, updates and removes viewports -*/ -class OgreViewportSystem : public System { - -public: - - /** - * @brief Lua bindings - * - * Exposes: - * - OgreViewportSystem() - * - * @return - */ - static luabind::scope - luaBindings(); - - /** - * @brief Constructor - */ - OgreViewportSystem(); - - /** - * @brief Destructor - */ - ~OgreViewportSystem(); - - void - activate() override; - - void - deactivate() override; - - /** - * @brief Initializes the system - * - * @param gameState - */ - void init(GameState* gameState) override; - - /** - * @brief Shuts the system down - */ - void shutdown() override; - - /** - * @brief Updates the system - */ - void update(int, int) override; - -private: - - struct Implementation; - std::unique_ptr m_impl; -}; - -} - diff --git a/src/ogre/workspace_system.cpp b/src/ogre/workspace_system.cpp index 2c77afaffe8..ff7b3ac24bf 100644 --- a/src/ogre/workspace_system.cpp +++ b/src/ogre/workspace_system.cpp @@ -9,7 +9,7 @@ #include "engine/serialization.h" #include "game.h" #include "ogre/camera_system.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include #include @@ -22,7 +22,6 @@ #include #include #include -#include using namespace thrive; @@ -33,33 +32,42 @@ using namespace thrive; static Entity Properties_getCameraEntity( - const OgreWorkspaceComponent::Properties* self + const OgreWorkspaceComponent::Properties &self ) { - return Entity(self->cameraEntity); + return Entity(self.cameraEntity, Game::instance().engine(). + getCurrentGameStateFromLua()); } static void Properties_setCameraEntity( - OgreWorkspaceComponent::Properties* self, + OgreWorkspaceComponent::Properties &self, const Entity& entity ) { - self->cameraEntity = entity.id(); + self.cameraEntity = entity.id(); } +void OgreWorkspaceComponent::luaBindings( + sol::state &lua +){ + lua.new_usertype("OgreWorkspaceComponentProperties", -luabind::scope -OgreWorkspaceComponent::luaBindings() { - using namespace luabind; - return class_("OgreWorkspaceComponent") - .scope [ - class_("Properties") - .property("cameraEntity", Properties_getCameraEntity, Properties_setCameraEntity) - .def_readwrite("position", &Properties::position) - ] - .def(constructor()) - .def_readonly("properties", &OgreWorkspaceComponent::m_properties) - ; + sol::base_classes, sol::bases(), + + "cameraEntity", sol::property(Properties_getCameraEntity, Properties_setCameraEntity), + "position", &Properties::position + ); + + lua.new_usertype("OgreWorkspaceComponent", + + "new", sol::factories([](const std::string &name){ + return std::make_unique(name); + }), + + COMPONENT_BINDINGS(OgreWorkspaceComponent), + + "properties", sol::readonly(&OgreWorkspaceComponent::m_properties) + ); } OgreWorkspaceComponent::OgreWorkspaceComponent( @@ -98,15 +106,18 @@ REGISTER_COMPONENT(OgreWorkspaceComponent) // OgreWorkspaceSystem //////////////////////////////////////////////////////////////////////////////// +void OgreWorkspaceSystem::luaBindings( + sol::state &lua +){ + lua.new_usertype("OgreWorkspaceSystem", -luabind::scope -OgreWorkspaceSystem::luaBindings() { - using namespace luabind; - return class_("OgreWorkspaceSystem") - .def(constructor<>()) - ; -} + sol::constructors>(), + + sol::base_classes, sol::bases(), + "init", &OgreWorkspaceSystem::init + ); +} struct OgreWorkspaceSystem::Implementation { @@ -304,12 +315,12 @@ OgreWorkspaceSystem::deactivate() { void OgreWorkspaceSystem::init( - GameState* gameState + GameStateData* gameState ) { System::initNamed("OgreWorkspaceSystem", gameState); - m_impl->m_renderWindow = this->engine()->renderWindow(); + m_impl->m_renderWindow = Game::instance().engine().renderWindow(); m_impl->m_sceneManager = gameState->sceneManager(); - m_impl->m_entities.setEntityManager(&gameState->entityManager()); + m_impl->m_entities.setEntityManager(gameState->entityManager()); } void diff --git a/src/ogre/workspace_system.h b/src/ogre/workspace_system.h index f32027c67f4..ab16675aeb0 100644 --- a/src/ogre/workspace_system.h +++ b/src/ogre/workspace_system.h @@ -6,8 +6,8 @@ #include -namespace luabind { - class scope; +namespace sol { +class state; } namespace Ogre { @@ -66,8 +66,7 @@ class OgreWorkspaceComponent : public Component { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** @brief Constructor @@ -133,8 +132,7 @@ class OgreWorkspaceSystem : public System { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -157,7 +155,7 @@ class OgreWorkspaceSystem : public System { * * @param gameState */ - void init(GameState* gameState) override; + void init(GameStateData* gameState) override; /** * @brief Shuts the system down diff --git a/src/scripting/CMakeLists.txt b/src/scripting/CMakeLists.txt index b7a9adc1674..08f77fdb80e 100644 --- a/src/scripting/CMakeLists.txt +++ b/src/scripting/CMakeLists.txt @@ -1,13 +1,13 @@ add_sources( - "${CMAKE_CURRENT_SOURCE_DIR}/lua_state.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/lua_state.h" - "${CMAKE_CURRENT_SOURCE_DIR}/luabind.h" - "${CMAKE_CURRENT_SOURCE_DIR}/script_bindings.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/script_bindings.h" + "${CMAKE_CURRENT_SOURCE_DIR}/luajit.h" "${CMAKE_CURRENT_SOURCE_DIR}/script_entity_filter.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/script_entity_filter.h" "${CMAKE_CURRENT_SOURCE_DIR}/script_initializer.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/script_initializer.h" + "${CMAKE_CURRENT_SOURCE_DIR}/script_wrapper.h" + "${CMAKE_CURRENT_SOURCE_DIR}/wrapper_classes.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/wrapper_classes.h" + "${CMAKE_CURRENT_SOURCE_DIR}/script_helpers.h" ) add_test_sources( diff --git a/src/scripting/lua_state.cpp b/src/scripting/lua_state.cpp deleted file mode 100644 index 43232e4d488..00000000000 --- a/src/scripting/lua_state.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include "scripting/lua_state.h" - -#include - -#include "lauxlib.h" -#include "lualib.h" - -using namespace thrive; - -LuaState::LuaState() - : m_state(luaL_newstate()) -{ - luaL_openlibs(m_state); -} - - -LuaState::~LuaState() { - lua_close(m_state); -} - - -LuaState::LuaState( - LuaState&& other -) : m_state(other.m_state) -{ - other.m_state = nullptr; -} - - -LuaState& -LuaState::operator= ( - LuaState&& other -) { - assert(this != &other); - m_state = other.m_state; - other.m_state = nullptr; - return *this; -} - - -LuaState::operator lua_State* () { - return m_state; -} - - -bool -LuaState::doFile( - const std::string& filename -) { - return not luaL_dofile(m_state, filename.c_str()); -} - - -bool -LuaState::doString( - const std::string& string -) { - return not luaL_dostring(m_state, string.c_str()); -} diff --git a/src/scripting/lua_state.h b/src/scripting/lua_state.h deleted file mode 100644 index bd206862be5..00000000000 --- a/src/scripting/lua_state.h +++ /dev/null @@ -1,98 +0,0 @@ -#pragma once - -#include - -class lua_State; - -namespace thrive { - -/** -* @brief RAII class for lua_State data structures -*/ -class LuaState { - -public: - - /** - * @brief Constructor - * - * Calls \c luaL_newstate and \c luaL_openlibs. - */ - LuaState(); - - /** - * @brief Non-copyable - * - */ - LuaState(const LuaState&) = delete; - - /** - * @brief Move constructor - * - * @param other - */ - LuaState(LuaState&& other); - - /** - * @brief Destructor - */ - ~LuaState(); - - /** - * @brief Non-copyable - * - */ - LuaState& - operator= (const LuaState&) = delete; - - /** - * @brief Move-assign operator - * - * @param other - * - * @return - */ - LuaState& - operator= (LuaState&& other); - - /** - * @brief Implicit cast to lua_State* - */ - operator lua_State* (); - - /** - * @brief Runs the file in the Lua state - * - * Calls \c luaL_dofile - * - * @param filename - * The file to load and run - * - * @return \c true if successful, \c false if there were errors - */ - bool - doFile( - const std::string& filename - ); - - /** - * @brief Runs the chunk in the Lua state - * - * Calls \c luaL_dostring - * - * @param string - * The script chunk to run - * - * @return \c true if successful, \c false if there were errors - */ - bool - doString( - const std::string& string - ); - -private: - - lua_State* m_state; -}; - -} diff --git a/src/scripting/luabind.h b/src/scripting/luabind.h deleted file mode 100644 index a61ace9acfd..00000000000 --- a/src/scripting/luabind.h +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace luabind { namespace detail { namespace has_get_pointer_ { - - template - inline T* - get_pointer( - const std::unique_ptr& ptr - ) { - return ptr.get(); - } - - - template - inline T* - get_pointer( - std::unique_ptr& ptr - ) { - return ptr.get(); - } - - - template - inline T* - get_pointer( - const std::shared_ptr& ptr - ) { - return ptr.get(); - } - - - template - inline T* - get_pointer( - std::shared_ptr& ptr - ) { - return ptr.get(); - } - -}}} - -#if (BOOST_VERSION / 100 % 1000) < 53 - -namespace boost { - - template - inline T* - get_pointer( - const std::unique_ptr& ptr - ) { - return ptr.get(); - } - - - template - inline T* - get_pointer( - const std::shared_ptr& ptr - ) { - return ptr.get(); - } - -} - -#endif // Boost version - -#include - -inline void -printLuaError(const luabind::error& e) { - luabind::object error_msg(luabind::from_stack( - e.state(), - -1 - )); - std::cerr<< error_msg << std::endl; -} - diff --git a/src/scripting/luajit.h b/src/scripting/luajit.h new file mode 100644 index 00000000000..8f52064580e --- /dev/null +++ b/src/scripting/luajit.h @@ -0,0 +1,49 @@ +#pragma once + +// Do not include this in headers! +// Use a forward declaration like this: +// namespace sol { +// class state; +// } + +#include "luajit/src/lua.hpp" + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" +#pragma GCC diagnostic ignored "-Wfloat-equal" +#pragma GCC diagnostic ignored "-Wcast-qual" +#pragma GCC diagnostic ignored "-Wold-style-cast" +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" +#pragma GCC diagnostic ignored "-Wswitch-default" +#endif + +#include "sol.hpp" + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +// Helper macros + +// For boost iterators +// TODO: check http://sol2.readthedocs.io/en/latest/api/containers.html#for-handling-std-vector-map-set-and-others +// for alternate solutions +#define THRIVE_BIND_ITERATOR_TO_TABLE(getList) sol::state_view lua(s); \ + const auto list = getList; \ + sol::table table = lua.create_table(); \ + \ + auto iter = list.begin(); \ + for(int i = 1; iter != list.end(); ++i, ++iter){ \ + table[i] = *iter; \ + } \ + \ + return table; \ + + +// For "castFrom" functions +#define LUA_CAST_FROM(className, baseType) \ +"castFrom", [](baseType* baseptr){ \ + return dynamic_cast(baseptr); \ +} + diff --git a/src/scripting/script_bindings.cpp b/src/scripting/script_bindings.cpp deleted file mode 100644 index f95825eccd6..00000000000 --- a/src/scripting/script_bindings.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "scripting/script_bindings.h" - -#include "scripting/luabind.h" -#include "scripting/script_entity_filter.h" - -luabind::scope -thrive::ScriptBindings::luaBindings() { - return ( - ScriptEntityFilter::luaBindings() - ); -} - diff --git a/src/scripting/script_bindings.h b/src/scripting/script_bindings.h deleted file mode 100644 index 382701a767d..00000000000 --- a/src/scripting/script_bindings.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -namespace luabind { -class scope; -} - -namespace thrive { - -/** -* @brief Helper for script bindings -*/ -struct ScriptBindings { - - /** - * @brief Exports relevant script bindings to Lua - * - * @return - */ - static luabind::scope - luaBindings(); - -}; - -} - diff --git a/src/scripting/script_entity_filter.cpp b/src/scripting/script_entity_filter.cpp index 202801f731f..a2457168b39 100644 --- a/src/scripting/script_entity_filter.cpp +++ b/src/scripting/script_entity_filter.cpp @@ -5,26 +5,24 @@ #include "engine/entity_manager.h" #include "engine/game_state.h" #include "game.h" -#include "scripting/luabind.h" - -#include using namespace thrive; struct ScriptEntityFilter::Implementation { Implementation( - luabind::object componentTypes, + sol::table componentTypes, bool recordChanges ) : m_recordChanges(recordChanges) { - using namespace luabind; - if (luabind::type(componentTypes) != LUA_TTABLE) { - throw std::runtime_error("ScriptEntityFilter constructor expects a list (table) of component types"); + if (componentTypes.get_type() != sol::type::table) { + throw std::runtime_error("ScriptEntityFilter constructor expects a list " + "(table) of component types"); } - for (luabind::iterator iter(componentTypes), end; iter != end; ++iter) { - luabind::object ret = (*iter)["TYPE_ID"]; - ComponentTypeId typeId = luabind::object_cast(ret); + for (const auto& pair : componentTypes) { + ComponentTypeId typeId = pair.second.as().get< + ComponentTypeId>("TYPE_ID"); + m_requiredComponents.insert(typeId); } } @@ -137,26 +135,25 @@ struct ScriptEntityFilter::Implementation { }; +void ScriptEntityFilter::luaBindings( + sol::state &lua +){ + lua.new_usertype("EntityFilter", -luabind::scope -ScriptEntityFilter::luaBindings() { - using namespace luabind; - return class_("EntityFilter") - .def(constructor()) - .def(constructor()) - .def("addedEntities", &ScriptEntityFilter::addedEntities, return_stl_iterator) - .def("clearChanges", &ScriptEntityFilter::clearChanges) - .def("containsEntity", &ScriptEntityFilter::containsEntity) - .def("entities", &ScriptEntityFilter::entities, return_stl_iterator) - .def("init", &ScriptEntityFilter::init) - .def("removedEntities", &ScriptEntityFilter::removedEntities, return_stl_iterator) - .def("shutdown", &ScriptEntityFilter::shutdown) - ; -} + sol::constructors, sol::types>(), + "addedEntities", &ScriptEntityFilter::addedEntities, + "clearChanges", &ScriptEntityFilter::clearChanges, + "containsEntity", &ScriptEntityFilter::containsEntity, + "entities", &ScriptEntityFilter::entities, + "init", &ScriptEntityFilter::init, + "removedEntities", &ScriptEntityFilter::removedEntities, + "shutdown", &ScriptEntityFilter::shutdown + ); +} ScriptEntityFilter::ScriptEntityFilter( - luabind::object componentTypes, + sol::table componentTypes, bool recordChanges ) : m_impl(new Implementation(componentTypes, recordChanges)) { @@ -164,7 +161,7 @@ ScriptEntityFilter::ScriptEntityFilter( ScriptEntityFilter::ScriptEntityFilter( - luabind::object componentTypes + sol::table componentTypes ) : m_impl(new Implementation(componentTypes, false)) { } @@ -210,10 +207,10 @@ ScriptEntityFilter::entities() { void ScriptEntityFilter::init( - GameState* gameState + GameStateData* gameState ) { m_impl->setEntityManager( - &gameState->entityManager() + gameState->entityManager() ); } diff --git a/src/scripting/script_entity_filter.h b/src/scripting/script_entity_filter.h index 609d0397ac4..89c0b499b56 100644 --- a/src/scripting/script_entity_filter.h +++ b/src/scripting/script_entity_filter.h @@ -1,15 +1,14 @@ #pragma once #include "engine/typedefs.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" -#include #include #include namespace thrive { -class GameState; +class GameStateData; /** * @brief Script version of the EntityFilter @@ -30,8 +29,7 @@ class ScriptEntityFilter { * - ScriptEntityFilter::shutdown * */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -44,7 +42,7 @@ class ScriptEntityFilter { * and removed during a frame. */ ScriptEntityFilter( - luabind::object componentTypes, + sol::table componentTypes, bool recordChanges ); @@ -59,7 +57,7 @@ class ScriptEntityFilter { * that should be filtered for */ ScriptEntityFilter( - luabind::object componentTypes + sol::table componentTypes ); /** @@ -109,7 +107,7 @@ class ScriptEntityFilter { */ void init( - GameState* gameState + GameStateData* gameState ); /** diff --git a/src/scripting/script_helpers.h b/src/scripting/script_helpers.h new file mode 100644 index 00000000000..60ce0243ef7 --- /dev/null +++ b/src/scripting/script_helpers.h @@ -0,0 +1,35 @@ +#pragma once + +#include "luajit.h" + +#include + +//! \file Utility functions for helping interacting with Lua + +namespace thrive{ + +/** +* @brief Creates an std::vector from a Lua table. Ignores invalid types +* +* @note The values will be returned in random order +*/ +template +auto +createVectorFromLuaTable(sol::table array){ + + std::vector result; + + for(const auto& pair : array){ + + if(pair.second.is()) + result.push_back(pair.second.as()); + } + + return result; +} + + + + +} + diff --git a/src/scripting/script_initializer.cpp b/src/scripting/script_initializer.cpp index bd8ff0110ac..ecd95478163 100644 --- a/src/scripting/script_initializer.cpp +++ b/src/scripting/script_initializer.cpp @@ -1,73 +1,1125 @@ #include "scripting/script_initializer.h" -#include "bullet/script_bindings.h" #include "engine/engine.h" #include "engine/rng.h" -#include "engine/script_bindings.h" -#include "general/script_bindings.h" #include "game.h" -#include "microbe_stage/script_bindings.h" -#include "gui/script_bindings.h" -#include "ogre/script_bindings.h" -#include "scripting/luabind.h" -#include "scripting/script_bindings.h" -#include "sound/script_bindings.h" +#include "scripting/luajit.h" +#include "scripting/wrapper_classes.h" +#include "scripting/script_entity_filter.h" #include "engine/rolling_grid.h" + + +#include "engine/entity_manager.h" +#include "engine/component.h" +#include "engine/component_factory.h" +#include "engine/engine.h" +#include "engine/entity.h" +#include "engine/game_state.h" +#include "engine/serialization.h" +#include "engine/system.h" +#include "engine/touchable.h" +#include "engine/player_data.h" +#include "engine/rng.h" + +#include "bullet/bullet_ogre_conversion.h" +#include "bullet/bullet_to_ogre_system.h" +#include "bullet/collision_filter.h" +#include "bullet/collision_shape.h" +#include "bullet/collision_system.h" +#include "bullet/debug_drawing.h" +#include "bullet/rigid_body_system.h" +#include "bullet/update_physics_system.h" +#include "bullet/physical_world.h" + +#include +#include +#include +#include + +#include "gui/script_wrappers.h" +#include "general/timed_life_system.h" +#include "general/locked_map.h" +#include "general/powerup_system.h" + +#include "gui/CEGUIWindow.h" +#include "gui/CEGUIVideoPlayer.h" + +#include "ogre/camera_system.h" +#include "ogre/colour_material.h" +#include "ogre/keyboard.h" +#include "ogre/light_system.h" +#include "ogre/mouse.h" +#include "ogre/render_system.h" +#include "ogre/scene_node_system.h" +#include "ogre/sky_system.h" + +#include "ogre/workspace_system.h" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +#include "microbe_stage/compound.h" +#include "microbe_stage/compound_absorber_system.h" +#include "microbe_stage/compound_emitter_system.h" +#include "microbe_stage/compound_registry.h" +#include "microbe_stage/bio_process_registry.h" +#include "microbe_stage/membrane_system.h" +#include "microbe_stage/compound_cloud_system.h" +#include "microbe_stage/process_system.h" +#include "microbe_stage/agent_cloud_system.h" +#include "microbe_stage/species_component.h" + + +#include "sound/sound_source_system.h" + + #include #include -#include +using namespace thrive; + +/** +* @brief Fills a stringstream with the lua callstack +*/ +void readLuaCallstack(lua_State* L, lua_Debug &d, std::stringstream &traceback); + +void readLuaCallstack(lua_State* L, lua_Debug &d, std::stringstream &traceback){ -static int -constructTraceback( - lua_State* L -) { - lua_Debug d; - std::stringstream traceback; - // Error message - traceback << lua_tostring(L, -1) << ":" << std::endl; - lua_pop(L, 1); - // Stacktrace for ( - int stacklevel = 0; + // Starting at 0 always prints [C]:-1 so we start at 1 to get + // the first actual stack frame + int stacklevel = 1; lua_getstack(L, stacklevel, &d); stacklevel++ ) { - lua_getinfo(L, "Sln", &d); - traceback << " " << d.short_src << ":" << d.currentline; - if (d.name != nullptr) { - traceback << " (" << d.namewhat << " " << d.name << ")"; - } - traceback << std::endl; + if(lua_getinfo(L, "Sln", &d) == 0){ + + traceback << " " << "error getting stack frame" << std::endl; + continue; + } + + traceback << " " << d.short_src << ":" << d.currentline; + + if (d.name != nullptr) { + traceback << " (" << d.namewhat << " " << d.name << ")"; + } + traceback << std::endl; + } +} + +/** +* @brief Thrive lua panic handler +*/ +int thriveLuaPanic(lua_State* L); + +int thriveLuaPanic(lua_State* L){ + + std::string err = "An unexpected error occurred and forced the lua state to call atpanic"; + + if(lua_isstring(L, -1)){ + + const char* message = lua_tostring(L, -1); + std::string err = message; + lua_pop(L, 1); } - lua_pushstring(L, traceback.str().c_str()); - std::cout << traceback.str().c_str() << std::endl; + + lua_Debug d; + std::stringstream traceback; + // Error message + traceback << err << ":" << std::endl; + + readLuaCallstack(L, d, traceback); + + // TODO: check if we should push this string and is throwing from here a good idea + // looks like throwing from here is a good idea + //lua_pushstring(L, traceback.str().c_str()); + + // Print error // + + std::cout << "Lua panic! " << traceback.str() << std::endl; + throw sol::error(traceback.str()); return 1; } -void -thrive::initializeLua( - lua_State* L + + +/** +* @brief Thrive lua error handler +*/ +std::string thriveLuaOnError(sol::this_state lua, std::string err); + +std::string thriveLuaOnError(sol::this_state lua, std::string err){ + + lua_State* L = sol::state_view(lua).lua_state(); + + //const char* message = lua_tostring(L, -1); + //std::string err = message ? message : + // "An unexpected error occurred and forced the lua state to call atpanic"; + //lua_pop(L, 1); + + if(err.empty()) + err = "An unexpected error occurred and forced the lua state to call onerror"; + + lua_Debug d; + std::stringstream traceback; + // Error message + traceback << err << ":" << std::endl; + + // Stacktrace + readLuaCallstack(L, d, traceback); + + // Print error // + std::cout << "Lua error detected! " << traceback.str() << std::endl; + + // Return as the error code + return traceback.str(); +} + + +//! \brief Binds all classes usable from Lua +//! +//! Needs to be called after global variables are bound. +//! \exception std::runtime_error if fails +void bindClassesToLua(sol::state &lua); + +// Forward declare some binding functions +static void listboxItemBindings(sol::state &lua); +static void itemEntryluaBindings(sol::state &lua); +static void ogreLuaBindings(sol::state &lua); + +void thrive::initializeLua(sol::state &lua){ + + // Open lua modules // + // see: http://www.lua.org/manual/5.3/manual.html#6 for documentation + // about what these modules do + lua.open_libraries( + sol::lib::base, + sol::lib::jit, + + sol::lib::debug, + sol::lib::coroutine, + sol::lib::string, + sol::lib::math, + sol::lib::table, + sol::lib::package, + sol::lib::io, + sol::lib::os + + // These aren't currently used + // sol::lib::bit32, + // sol::lib::ffi + ); + + lua.set_panic(&thriveLuaPanic); + + // Class type registering // + bindClassesToLua(lua); + + // Global objects // + lua["Engine"] = &(Game::instance().engine()); + lua["rng"] = &(Game::instance().engine().rng()); + + // Bind a custom traceback printer + // Could probably also be print(debug.traceback()) + lua["thrivePanic"] = thriveLuaOnError; +} + +void bindClassesToLua(sol::state &lua){ + + // Engine bindings + { + StorageContainer::luaBindings(lua); + StorageList::luaBindings(lua); + + System::luaBindings(lua); + Component::luaBindings(lua); + ComponentWrapper::luaBindings(lua); + ComponentFactory::luaBindings(lua); + + EntityManager::luaBindings(lua); + Entity::luaBindings(lua); + + Touchable::luaBindings(lua); + GameStateData::luaBindings(lua); + RNG::luaBindings(lua); + PlayerData::luaBindings(lua); + + + ScriptEntityFilter::luaBindings(lua); + + Engine::luaBindings(lua); + Game::luaBindings(lua); + + } + + // General bindings + { + // Components + TimedLifeComponent::luaBindings(lua); + LockedMap::luaBindings(lua); + PowerupComponent::luaBindings(lua); + // Systems + TimedLifeSystem::luaBindings(lua); + PowerupSystem::luaBindings(lua); + // Other + } + + // Ogre bindings + ogreLuaBindings(lua); + + // Bullet bindings + { + // Shapes + CollisionShape::luaBindings(lua); + BoxShape::luaBindings(lua); + CapsuleShape::luaBindings(lua); + CompoundShape::luaBindings(lua); + ConeShape::luaBindings(lua); + CylinderShape::luaBindings(lua); + EmptyShape::luaBindings(lua); + SphereShape::luaBindings(lua); + // Components + RigidBodyComponent::luaBindings(lua); + CollisionComponent::luaBindings(lua); + // Systems + BulletToOgreSystem::luaBindings(lua); + RigidBodyInputSystem::luaBindings(lua); + RigidBodyOutputSystem::luaBindings(lua); + BulletDebugDrawSystem::luaBindings(lua); + UpdatePhysicsSystem::luaBindings(lua); + CollisionSystem::luaBindings(lua); + // Other + PhysicalWorld::luaBindings(lua); + CollisionFilter::luaBindings(lua); + Collision::luaBindings(lua); + } + + // Script bindings + { + + } + + // Microbe stage bindings + { + // Components + CompoundComponent::luaBindings(lua); + ProcessorComponent::luaBindings(lua); + CompoundBagComponent::luaBindings(lua); + CompoundAbsorberComponent::luaBindings(lua); + CompoundEmitterComponent::luaBindings(lua); + TimedCompoundEmitterComponent::luaBindings(lua); + MembraneComponent::luaBindings(lua); + CompoundCloudComponent::luaBindings(lua); + AgentCloudComponent::luaBindings(lua); + SpeciesComponent::luaBindings(lua); + // Systems + CompoundMovementSystem::luaBindings(lua); + CompoundAbsorberSystem::luaBindings(lua); + CompoundEmitterSystem::luaBindings(lua); + MembraneSystem::luaBindings(lua); + CompoundCloudSystem::luaBindings(lua); + ProcessSystem::luaBindings(lua); + AgentCloudSystem::luaBindings(lua); + // Other + CompoundRegistry::luaBindings(lua); + BioProcessRegistry::luaBindings(lua); + } + + // Gui bindings + { + // Other + listboxItemBindings(lua); + itemEntryluaBindings(lua); + CEGUIWindow::luaBindings(lua); + CEGUIVideoPlayer::luaBindings(lua); + + StandardItemWrapper::luaBindings(lua); + } + + // Sound bindings + { + Sound::luaBindings(lua); + SoundSourceSystem::luaBindings(lua); + SoundSourceComponent::luaBindings(lua); + } + + RollingGrid::luaBindings(lua); +} + + + +static void ListboxItem_setColour( + CEGUI::ListboxTextItem &self, + float r, + float g, + float b +) { + self.setTextColours(CEGUI::Colour(r,g,b)); +} + +static void ListboxItem_setText( + CEGUI::ListboxTextItem &self, + const std::string& text +) { + self.setText(text); +} + +static void listboxItemBindings(sol::state &lua) { + + lua.new_usertype("ListboxItem", + + sol::constructors>(), + + "setTextColours", &ListboxItem_setColour, + "setText", &ListboxItem_setText + ); +} + +static void ItemEntry_setText( + CEGUI::ItemEntry &self, + const std::string& text ) { - luabind::set_pcall_callback(constructTraceback); - luabind::open(L); - luabind::bind_class_info(L); - luabind::module(L) [ - EngineBindings::luaBindings(), - GeneralBindings::luaBindings(), - OgreBindings::luaBindings(), - BulletBindings::luaBindings(), - ScriptBindings::luaBindings(), - MicrobeBindings::luaBindings(), - GuiBindings::luaBindings(), - SoundBindings::luaBindings(), - RollingGrid::luaBindings() - ]; - luabind::object globals = luabind::globals(L); - globals["Engine"] = &(Game::instance().engine()); - globals["rng"] = &(Game::instance().engine().rng()); + self.setText(text); +} + +static bool ItemEntry_isSelected( + CEGUI::ItemEntry &self +) { + return self.isSelected(); +} + +static void ItemEntry_select( + CEGUI::ItemEntry &self +) { + self.select(); +} + +static void ItemEntry_deselect( + CEGUI::ItemEntry &self +) { + self.deselect(); +} + +static void ItemEntry_setSelectable( + CEGUI::ItemEntry &self, + bool setting +) { + self.setSelectable(setting); +} + +static void itemEntryluaBindings(sol::state &lua){ + + lua.new_usertype("ItemEntry", + + sol::constructors>(), + + "isSelected", &ItemEntry_isSelected, + "select", &ItemEntry_select, + "deselect", &ItemEntry_deselect, + "setSelectable", &ItemEntry_setSelectable, + "setText", &ItemEntry_setText + ); +} + +static void axisAlignedBoxBindings(sol::state &lua) { + + using namespace Ogre; + + lua.new_usertype("BoxShape", + + sol::constructors, sol::types, + sol::types, sol::types< + Ogre::Real, Ogre::Real, Ogre::Real, + Ogre::Real, Ogre::Real, Ogre::Real >>(), + + sol::meta_function::equal_to, &Ogre::AxisAlignedBox::operator==, + + "Extent", sol::var(lua.create_table_with( + "EXTENT_NULL", Ogre::AxisAlignedBox::EXTENT_NULL, + "EXTENT_FINITE", Ogre::AxisAlignedBox::EXTENT_FINITE, + "EXTENT_INFINITE", Ogre::AxisAlignedBox::EXTENT_INFINITE + )), + + "CornerEnum", sol::var(lua.create_table_with( + "FAR_LEFT_BOTTOM", Ogre::AxisAlignedBox::FAR_LEFT_BOTTOM, + "FAR_LEFT_TOP", Ogre::AxisAlignedBox::FAR_LEFT_TOP, + "FAR_RIGHT_TOP", Ogre::AxisAlignedBox::FAR_RIGHT_TOP, + "FAR_RIGHT_BOTTOM", Ogre::AxisAlignedBox::FAR_RIGHT_BOTTOM, + "NEAR_RIGHT_BOTTOM", Ogre::AxisAlignedBox::NEAR_RIGHT_BOTTOM, + "NEAR_LEFT_BOTTOM", Ogre::AxisAlignedBox::NEAR_LEFT_BOTTOM, + "NEAR_LEFT_TOP", Ogre::AxisAlignedBox::NEAR_LEFT_TOP, + "NEAR_RIGHT_TOP", Ogre::AxisAlignedBox::NEAR_RIGHT_TOP + )), + + "getMinimum", + static_cast( + &AxisAlignedBox::getMinimum), + + "getMaximum", + static_cast( + &AxisAlignedBox::getMaximum), + + "setMinimum", sol::overload( + static_cast( + &AxisAlignedBox::setMinimum), + static_cast( + &AxisAlignedBox::setMinimum)), + + "setMinimumX", &AxisAlignedBox::setMinimumX, + "setMinimumY", &AxisAlignedBox::setMinimumY, + "setMinimumZ", &AxisAlignedBox::setMinimumZ, + + "setMaximum", sol::overload( + static_cast( + &AxisAlignedBox::setMaximum), + static_cast( + &AxisAlignedBox::setMaximum)), + + "setMaximumX", &AxisAlignedBox::setMaximumX, + "setMaximumY", &AxisAlignedBox::setMaximumY, + "setMaximumZ", &AxisAlignedBox::setMaximumZ, + "setExtents", sol::overload( + static_cast(&AxisAlignedBox::setExtents), + static_cast(&AxisAlignedBox::setExtents)), + + "getCorner", &AxisAlignedBox::getCorner, + "merge", sol::overload( + static_cast( + &AxisAlignedBox::merge), + static_cast( + &AxisAlignedBox::merge)), + + "setNull", &AxisAlignedBox::setNull, + "isNull", &AxisAlignedBox::isNull, + "isFinite", &AxisAlignedBox::isFinite, + "setInfinite", &AxisAlignedBox::setInfinite, + "isInfinite", &AxisAlignedBox::isInfinite, + "intersects", sol::overload( + static_cast( + &AxisAlignedBox::intersects), + static_cast( + &AxisAlignedBox::intersects), + static_cast( + &AxisAlignedBox::intersects), + static_cast( + &AxisAlignedBox::intersects)), + + "intersection", &AxisAlignedBox::intersection, + "volume", &AxisAlignedBox::volume, + "scale", &AxisAlignedBox::scale, + + "getCenter", &AxisAlignedBox::getCenter, + "getSize", &AxisAlignedBox::getSize, + "getHalfSize", &AxisAlignedBox::getHalfSize, + "contains", sol::overload( + static_cast( + &AxisAlignedBox::contains), + static_cast( + &AxisAlignedBox::contains)), + + "distance", &AxisAlignedBox::distance + ); +} + +static void colourValueBindings(sol::state &lua) { + + using namespace Ogre; + + lua.new_usertype("ColourValue", + + sol::constructors>(), + + sol::meta_function::equal_to, &ColourValue::operator==, + + sol::meta_function::addition, &ColourValue::operator+, + + + sol::meta_function::multiplication, sol::overload( + static_cast( + &ColourValue::operator*), + static_cast( + &ColourValue::operator*) + ), + + sol::meta_function::subtraction, &ColourValue::operator-, + + sol::call_constructor, [](float r, float g, float b, float a){ + + return Ogre::ColourValue(r, g, b, a); + + }, + + "saturate", &ColourValue::saturate, + "setHSB", &ColourValue::setHSB, + "getHSB", &ColourValue::getHSB, + + "r", &ColourValue::r, + "g", &ColourValue::g, + "b", &ColourValue::b, + "a", &ColourValue::a + ); +} + +static void degreeBindings(sol::state &lua) { + + lua.new_usertype("Degree", + + sol::constructors, sol::types>(), + + sol::meta_function::equal_to, &Ogre::Degree::operator==, + + sol::meta_function::less_than, &Ogre::Degree::operator<, + + sol::meta_function::addition, static_cast(&Ogre::Degree::operator+), + + sol::meta_function::subtraction, static_cast(&Ogre::Degree::operator-), + + sol::meta_function::multiplication, sol::overload( + static_cast( + &Ogre::Degree::operator*), + static_cast( + &Ogre::Degree::operator*) + ), + + sol::meta_function::division, &Ogre::Degree::operator/, + + // Support for table call syntax + sol::call_constructor, [](Ogre::Real val){ + + return Ogre::Degree(val); + + }, + + "valueDegrees", &Ogre::Degree::valueDegrees + ); +} + + +static void + SubEntity_setColour( + Ogre::SubEntity &self, + const Ogre::ColourValue& colour + ) { + auto material = thrive::getColourMaterial(colour); + self.setMaterial(material); +} + +static void + Entity_setColour( + Ogre::Entity &self, + const Ogre::ColourValue& colour + ) { + auto material = thrive::getColourMaterial(colour); + self.setMaterial(material); +} + +static void + SubEntity_setMaterial( + Ogre::SubEntity &self, + const Ogre::String& name + ) { + Ogre::MaterialManager& manager = Ogre::MaterialManager::getSingleton(); + Ogre::MaterialPtr material = manager.getByName( + name + ); + self.setMaterial(material); +} + +static void + Entity_setMaterial( + Ogre::Entity &self, + const Ogre::String& name + ) { + Ogre::MaterialManager& manager = Ogre::MaterialManager::getSingleton(); + Ogre::MaterialPtr material = manager.getByName( + name + ); + self.setMaterial(material); +} + +static void + SubEntity_tintColour( + Ogre::SubEntity &self, + const Ogre::String& groupName, + const Ogre::String& materialName, + const Ogre::ColourValue& colour + ) { + Ogre::MaterialPtr baseMaterial = Ogre::MaterialManager::getSingleton().getByName(materialName); + Ogre::MaterialPtr materialPtr = baseMaterial->clone(groupName); + materialPtr->compile(); + Ogre::TextureUnitState* ptus = materialPtr->getTechnique(0)->getPass(0)->getTextureUnitState(0); + ptus->setColourOperationEx(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_TEXTURE, colour); + self.setMaterial(materialPtr); +} + +static void + Entity_tintColour( + Ogre::Entity &self, + const Ogre::String& materialName, + const Ogre::ColourValue& colour + ) { + Ogre::MaterialPtr baseMaterial = Ogre::MaterialManager::getSingleton().getByName(materialName); + Ogre::MaterialPtr materialPtr = baseMaterial->clone(materialName + std::to_string(static_cast(colour.r*256)) + + std::to_string(static_cast(colour.g*256)) + std::to_string(static_cast(colour.b*256))); + materialPtr->compile(); + Ogre::TextureUnitState* ptus = materialPtr->getTechnique(0)->getPass(0)->getTextureUnitState(0); + ptus->setAlphaOperation(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_TEXTURE, colour.a); + ptus->setColourOperationEx(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_TEXTURE, colour); + self.setMaterial(materialPtr); +} + +static int clonedIndex = 0; + +static void + Entity_cloneMaterial( + Ogre::Entity &self, + const Ogre::String& materialName + ) { + Ogre::MaterialPtr baseMaterial = Ogre::MaterialManager::getSingleton().getByName(materialName); + Ogre::MaterialPtr materialPtr = baseMaterial->clone(materialName + std::to_string(clonedIndex)); + materialPtr->compile(); + self.setMaterialName(materialName + std::to_string(clonedIndex)); + clonedIndex++; +} + +static void + Entity_setMaterialColour( + Ogre::Entity &self, + //const String& materialName, + const Ogre::ColourValue& colour + ) { + //Ogre::MaterialPtr baseMaterial = Ogre::MaterialManager::getSingleton().getByName(materialName); + //Ogre::MaterialPtr materialPtr = baseMaterial->clone(materialName + std::to_string(clonedIndex)); + //materialPtr->compile(); + //self.setMaterialName(materialName + std::to_string(clonedIndex)); + //clonedIndex++; + + Ogre::SubMesh* sub = self.getMesh()->getSubMesh(0); + Ogre::MaterialPtr materialPtr = Ogre::MaterialManager::getSingleton().getByName(sub->getMaterialName()); + Ogre::TextureUnitState* ptus = materialPtr->getTechnique(0)->getPass(0)->getTextureUnitState(0); + ptus->setColourOperationEx(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_TEXTURE, colour); + ptus->setAlphaOperation(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_TEXTURE, colour.a); + //self.setMaterial(materialPtr); } +static void ogreEntityBindings(sol::state &lua) { + + lua.new_usertype("OgreSubEntity", + + "setColour", &SubEntity_setColour, + "setMaterial", &SubEntity_setMaterial, + "tintColour", &SubEntity_tintColour + ); + + lua.new_usertype("OgreEntity", + + "getSubEntity", static_cast( + &Ogre::Entity::getSubEntity), + "getNumSubEntities", &Ogre::Entity::getNumSubEntities, + "setColour", &Entity_setColour, + "setMaterial", &Entity_setMaterial, + "cloneMaterial", &Entity_cloneMaterial, + "setMaterialColour", &Entity_setMaterialColour, + "tintColour", &Entity_tintColour + ); + + lua.new_usertype("MovableObject", + + sol::base_classes, sol::bases() + ); +} + +static void matrix3Bindings(sol::state &lua) { + + using namespace Ogre; + + lua.new_usertype("Matrix3", + + sol::constructors, sol::types< + Ogre::Real, Ogre::Real, Ogre::Real, + Ogre::Real, Ogre::Real, Ogre::Real, + Ogre::Real, Ogre::Real, Ogre::Real>>(), + + sol::meta_function::equal_to, &Ogre::Matrix3::operator==, + + sol::meta_function::addition, &Ogre::Matrix3::operator+, + + sol::meta_function::subtraction, static_cast(&Ogre::Matrix3::operator-), + + sol::meta_function::multiplication, sol::overload( + static_cast( + &Ogre::Matrix3::operator*), + static_cast( + &Ogre::Matrix3::operator*), + static_cast( + &Ogre::Matrix3::operator*) + ), + + "GetColumn", &Matrix3::GetColumn, + "SetColumn", &Matrix3::SetColumn, + "FromAxes", &Matrix3::FromAxes, + "Transpose", &Matrix3::Transpose, + "Inverse", + static_cast(&Matrix3::Inverse), + + "Determinant", &Matrix3::Determinant, + "SingularValueDecomposition", &Matrix3::SingularValueDecomposition, + "SingularValueComposition", &Matrix3::SingularValueComposition, + "Orthonormalize", &Matrix3::Orthonormalize, + "QDUDecomposition", &Matrix3::QDUDecomposition, + "SpectralNorm", &Matrix3::SpectralNorm, + "ToAngleAxis", static_cast( + &Matrix3::ToAngleAxis), + + "FromAngleAxis", &Matrix3::FromAngleAxis, + "ToEulerAnglesXYZ", &Matrix3::ToEulerAnglesXYZ, + "ToEulerAnglesXZY", &Matrix3::ToEulerAnglesXZY, + "ToEulerAnglesYXZ", &Matrix3::ToEulerAnglesYXZ, + "ToEulerAnglesYZX", &Matrix3::ToEulerAnglesYZX, + "ToEulerAnglesZXY", &Matrix3::ToEulerAnglesZXY, + "ToEulerAnglesZYX", &Matrix3::ToEulerAnglesZYX, + "FromEulerAnglesXYZ", &Matrix3::FromEulerAnglesXYZ, + "FromEulerAnglesXZY", &Matrix3::FromEulerAnglesXZY, + "FromEulerAnglesYXZ", &Matrix3::FromEulerAnglesYXZ, + "FromEulerAnglesYZX", &Matrix3::FromEulerAnglesYZX, + "FromEulerAnglesZXY", &Matrix3::FromEulerAnglesZXY, + "FromEulerAnglesZYX", &Matrix3::FromEulerAnglesZYX, + "hasScale", &Matrix3::hasScale + ); +} + +static void planeBindings(sol::state &lua) { + + using namespace Ogre; + + lua.new_usertype("Plane", + + sol::constructors, sol::types, + sol::types, sol::types, + sol::types>(), + + //sol::meta_function::equal_to, &Ogre::Plane::operator==, + + "Side", sol::var(lua.create_table_with( + "NO_SIDE", Plane::NO_SIDE, + "POSITIVE_SIDE", Plane::POSITIVE_SIDE, + "NEGATIVE_SIDE", Plane::NEGATIVE_SIDE, + "BOTH_SIDE", Plane::BOTH_SIDE + )), + + "getSide", sol::overload( + static_cast(&Plane::getSide), + static_cast(&Plane::getSide), + static_cast( + &Plane::getSide) + ), + + "getDistance", &Plane::getDistance, + + "redefine", sol::overload( + static_cast(&Plane::redefine), + static_cast( + &Plane::redefine) + ), + + "projectVector", &Plane::projectVector, + "normalise", &Plane::normalise, + "normal", &Plane::normal, + "d", &Plane::d + ); +} + +static void quaternionBindings(sol::state &lua) { + + using namespace Ogre; + + lua.new_usertype("Quaternion", + + sol::constructors, sol::types, + sol::types, sol::types, + sol::types>(), + + //sol::meta_function::equal_to, &Ogre::Quaternion::operator==, + + sol::meta_function::addition, &Ogre::Quaternion::operator+, + + sol::meta_function::subtraction, static_cast(&Ogre::Quaternion::operator-), + + sol::meta_function::multiplication, sol::overload( + static_cast( + &Ogre::Quaternion::operator*), + static_cast( + &Ogre::Quaternion::operator*), + static_cast( + &Ogre::Quaternion::operator*) + ), + + "FromRotationMatrix", &Quaternion::FromRotationMatrix, + "ToRotationMatrix", &Quaternion::ToRotationMatrix, + "FromAngleAxis", &Quaternion::FromAngleAxis, + "ToAngleAxis", static_cast( + &Quaternion::ToAngleAxis), + "FromAxes", static_cast(&Quaternion::FromAxes), + "ToAxes", static_cast( + &Quaternion::ToAxes), + "xAxis", &Quaternion::xAxis, + "yAxis", &Quaternion::yAxis, + "zAxis", &Quaternion::zAxis, + "Dot", &Quaternion::Dot, + "Norm", &Quaternion::Norm, + "normalise", &Quaternion::normalise, + "Inverse", &Quaternion::Inverse, + "UnitInverse", &Quaternion::UnitInverse, + "Exp", &Quaternion::Exp, + "Log", &Quaternion::Log, + "getRoll", &Quaternion::getRoll, + "getPitch", &Quaternion::getPitch, + "getYaw", &Quaternion::getYaw, + "equals", &Quaternion::equals, + "isNaN", &Quaternion::isNaN + ); +} + + +static void radianBindings(sol::state &lua) { + + using namespace Ogre; + + lua.new_usertype("Radian", + + sol::constructors, sol::types>(), + + //sol::meta_function::equal_to, &Ogre::Radian::operator==, + + sol::meta_function::less_than, &Ogre::Radian::operator<, + + sol::meta_function::addition, static_cast(&Ogre::Radian::operator+), + + sol::meta_function::subtraction, static_cast(&Ogre::Radian::operator-), + + sol::meta_function::multiplication, sol::overload( + static_cast( + &Ogre::Radian::operator*), + static_cast( + &Ogre::Radian::operator*) + ), + + sol::meta_function::division, static_cast(&Ogre::Radian::operator/), + + + // Support for table call syntax + sol::call_constructor, [](Ogre::Real val){ + + return Ogre::Radian(val); + + }, + + "valueDegrees", &Radian::valueDegrees, + "valueRadians", &Radian::valueRadians, + "valueAngleUnits", &Radian::valueAngleUnits + ); +} + +static void rayBindings(sol::state &lua) { + + using namespace Ogre; + + lua.new_usertype("Ray", + + sol::constructors, sol::types>(), + + sol::meta_function::multiplication, static_cast(&Ogre::Ray::operator*), + + "setOrigin", &Ray::setOrigin, + "getOrigin", &Ray::getOrigin, + "setDirection", &Ray::setDirection, + "getDirection", &Ray::getDirection, + "getPoint", &Ray::getPoint, + // returns a tuple now + "intersects", static_cast (Ogre::Ray::*)( + const Ogre::Plane&) const>(&Ray::intersects) + ); +} + + +static void sceneManagerBindings(sol::state &lua) { + + using namespace Ogre; + + lua.new_usertype("SceneManager", + + "PrefabType", sol::var(lua.create_table_with( + "PT_PLANE", SceneManager::PT_PLANE, + "PT_CUBE", SceneManager::PT_CUBE, + "PT_SPHERE", SceneManager::PT_SPHERE + )), + + "setAmbientLight", &SceneManager::setAmbientLight + ); +} + +static void sphereBindings(sol::state &lua) { + + using namespace Ogre; + + lua.new_usertype("Sphere", + + sol::constructors, sol::types>(), + + "getRadius", &Sphere::getRadius, + "setRadius", &Sphere::setRadius, + "getCenter", &Sphere::getCenter, + "setCenter", &Sphere::setCenter, + + "intersects", sol::overload( + static_cast(&Sphere::intersects), + static_cast(&Sphere::intersects), + static_cast(&Sphere::intersects), + static_cast(&Sphere::intersects) + ), + + "merge", &Sphere::merge + ); +} + +static void vector3Bindings(sol::state &lua) { + + using namespace Ogre; + + lua.new_usertype("Vector3", + + sol::constructors, sol::types>(), + + //sol::meta_function::equal_to, &Ogre::Vector3::operator==, + + sol::meta_function::less_than, &Ogre::Vector3::operator <, + + sol::meta_function::addition, static_cast(&Ogre::Vector3::operator+), + + sol::meta_function::subtraction, static_cast(&Ogre::Vector3::operator-), + + sol::meta_function::multiplication, sol::overload( + static_cast( + &Ogre::Vector3::operator*), + static_cast( + &Ogre::Vector3::operator*), + [](const Ogre::Real f, const Ogre::Vector3 &vec) -> Ogre::Vector3{ + + return f * vec; + } + ), + + + sol::meta_function::division, sol::overload( + static_cast( + &Ogre::Vector3::operator/), + static_cast( + &Ogre::Vector3::operator/) + ), + + // Support for table call syntax + sol::call_constructor, [](const Ogre::Real x, const Ogre::Real y, const Ogre::Real z){ + + return Ogre::Vector3(x, y, z); + + }, + + //.def(tostring(self)) + + "x", &Vector3::x, + "y", &Vector3::y, + "z", &Vector3::z, + + "length", &Vector3::length, + "squaredLength", &Vector3::squaredLength, + "distance", &Vector3::distance, + "squaredDistance", &Vector3::squaredDistance, + "dotProduct", &Vector3::dotProduct, + "absDotProduct", &Vector3::absDotProduct, + "normalise", &Vector3::normalise, + "crossProduct", &Vector3::crossProduct, + "midPoint", &Vector3::midPoint, + "makeFloor", &Vector3::makeFloor, + "makeCeil", &Vector3::makeCeil, + "perpendicular", &Vector3::perpendicular, + "randomDeviant", &Vector3::randomDeviant, + "angleBetween", &Vector3::angleBetween, + "getRotationTo", &Vector3::getRotationTo, + "isZeroLength", &Vector3::isZeroLength, + "normalisedCopy", &Vector3::normalisedCopy, + "reflect", &Vector3::reflect, + "positionEquals", &Vector3::positionEquals, + "positionCloses", &Vector3::positionCloses, + "directionEquals", &Vector3::directionEquals, + "isNaN", &Vector3::isNaN, + "primaryAxis", &Vector3::primaryAxis + ); +} + +static void ogreLuaBindings(sol::state &lua){ + + // Math + axisAlignedBoxBindings(lua); + colourValueBindings(lua); + degreeBindings(lua); + matrix3Bindings(lua); + planeBindings(lua); + quaternionBindings(lua); + radianBindings(lua); + rayBindings(lua); + sphereBindings(lua); + vector3Bindings(lua); + // Scene Manager + sceneManagerBindings(lua); + ogreEntityBindings(lua); + // Components + OgreCameraComponent::luaBindings(lua); + OgreLightComponent::luaBindings(lua); + OgreSceneNodeComponent::luaBindings(lua); + SkyPlaneComponent::luaBindings(lua); + OgreWorkspaceComponent::luaBindings(lua); + // Systems + OgreAddSceneNodeSystem::luaBindings(lua); + OgreCameraSystem::luaBindings(lua); + OgreLightSystem::luaBindings(lua); + OgreRemoveSceneNodeSystem::luaBindings(lua); + OgreUpdateSceneNodeSystem::luaBindings(lua); + thrive::RenderSystem::luaBindings(lua); // Fully qualified because of Ogre::RenderSystem + SkySystem::luaBindings(lua); + OgreWorkspaceSystem::luaBindings(lua); + // Other + Keyboard::luaBindings(lua); + Mouse::luaBindings(lua); +} diff --git a/src/scripting/script_initializer.h b/src/scripting/script_initializer.h index b470deb2cbb..e0421f8b535 100644 --- a/src/scripting/script_initializer.h +++ b/src/scripting/script_initializer.h @@ -1,6 +1,8 @@ #pragma once -class lua_State; +namespace sol { +class state; +} namespace thrive { @@ -8,13 +10,7 @@ namespace thrive { * @brief Initializes a Lua state for use with the script engine * * This will register the known classes in the Lua state -* -* @param L -* The state to initialize */ -void -initializeLua( - lua_State* L -); +void initializeLua(sol::state &lua); } diff --git a/src/scripting/script_wrapper.h b/src/scripting/script_wrapper.h new file mode 100644 index 00000000000..a43b4db59c3 --- /dev/null +++ b/src/scripting/script_wrapper.h @@ -0,0 +1,25 @@ +#pragma once + +#include "luajit.h" + +namespace thrive { + +//! \brief Base class for classes that support "inheriting" from in Lua +class ScriptWrapper{ +public: + ScriptWrapper(sol::table obj) : m_luaObject(obj){ + + } + +protected: + + //! This is the lua table that contains the overridden functions + //! + //! This might also contain the regular functions bound from C++. + //! Which isn't optimal because they will have an overhead when + //! calling them through Lua + sol::table m_luaObject; +}; + + +} diff --git a/src/scripting/tests/do_string_assertion.h b/src/scripting/tests/do_string_assertion.h deleted file mode 100644 index 60eba0c304d..00000000000 --- a/src/scripting/tests/do_string_assertion.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -static ::testing::AssertionResult -LuaSuccess( - lua_State* L, - const std::string& string -) { - if (luaL_dostring(L, string.c_str())) { - luabind::object error_msg( - luabind::from_stack(L, -1) - ); - return ::testing::AssertionFailure() << error_msg; - } - else { - return ::testing::AssertionSuccess(); - } -} - diff --git a/src/scripting/wrapper_classes.cpp b/src/scripting/wrapper_classes.cpp new file mode 100644 index 00000000000..0b02a555b60 --- /dev/null +++ b/src/scripting/wrapper_classes.cpp @@ -0,0 +1,88 @@ +#include "wrapper_classes.h" + +#include "engine/component_factory.h" +#include "engine/engine.h" +#include "engine/serialization.h" +#include "engine/system.h" +#include "game.h" + +using namespace thrive; + +void +ComponentWrapper::luaBindings(sol::state &lua){ + + lua.new_usertype("ComponentWrapper", + + sol::constructors>(), + + LUA_CAST_FROM(ComponentWrapper, Component), + + "castFromUnsafe", [](Component* component){ + return static_cast(component); + }, + + "luaObj", sol::readonly(&ComponentWrapper::m_luaObject) + ); +} + +ComponentWrapper::ComponentWrapper( + sol::table obj +) : ScriptWrapper(obj) +{ +} + +void +ComponentWrapper::load( + const StorageContainer& storage +) { + auto func = m_luaObject.get("load"); + + Component::load(storage); + + if(!func){ + + return; + } + + func(m_luaObject, &storage); +} + +ComponentTypeId +ComponentWrapper::typeId( +) const{ + + return Game::instance().engine().componentFactory().getTypeId( + this->typeName() + ); +} + +std::string +ComponentWrapper::typeName( +) const{ + + // This needs to be set on the Lua side for each Component + return m_luaObject["TYPE_NAME"]; +} + +StorageContainer +ComponentWrapper::storage( +) const{ + + auto func = m_luaObject.get("storage"); + + auto stored = Component::storage(); + + if(!func){ + + return stored; + } + + const auto result = func(m_luaObject, &stored); + + if(!result.valid()) + throw std::runtime_error("lua component failed to return storage object"); + + return stored; +} + + diff --git a/src/scripting/wrapper_classes.h b/src/scripting/wrapper_classes.h new file mode 100644 index 00000000000..1b5ff9deb7b --- /dev/null +++ b/src/scripting/wrapper_classes.h @@ -0,0 +1,52 @@ +//! \file This file contains classes that are "inheritable" in Lua +#pragma once + +#include "scripting/script_wrapper.h" + + +#include "engine/component.h" +#include "engine/system.h" + + +namespace CEGUI { + +class StandardItem; +} + +namespace thrive { +/** +* @brief Wrapper class to enable subclassing Component in Lua +*/ +class ComponentWrapper : public Component, public ScriptWrapper { +public: + + /** + * @brief Lua bindings + * + * Exposes: + * - ComponentWrapper + * + * @return + */ + static void + luaBindings(sol::state &lua); + + ComponentWrapper( + sol::table obj + ); + + void load( + const StorageContainer& storage + ) override; + + ComponentTypeId + typeId() const override; + + std::string + typeName() const override; + + StorageContainer + storage() const override; +}; + +} diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index beec72fdf3c..e4f7a026979 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -1,6 +1,4 @@ add_sources( - "${CMAKE_CURRENT_SOURCE_DIR}/script_bindings.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/script_bindings.h" "${CMAKE_CURRENT_SOURCE_DIR}/sound_source_system.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/sound_source_system.h" "${CMAKE_CURRENT_SOURCE_DIR}/caudio_include.h" diff --git a/src/sound/script_bindings.cpp b/src/sound/script_bindings.cpp deleted file mode 100644 index 7ce5e6bc615..00000000000 --- a/src/sound/script_bindings.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "sound/script_bindings.h" - -#include "scripting/luabind.h" -#include "sound/sound_source_system.h" - -using namespace luabind; -using namespace thrive; - -luabind::scope -thrive::SoundBindings::luaBindings() { - return ( - Sound::luaBindings(), - SoundSourceSystem::luaBindings(), - SoundSourceComponent::luaBindings() - ); -} - - diff --git a/src/sound/script_bindings.h b/src/sound/script_bindings.h deleted file mode 100644 index f8a83fb9798..00000000000 --- a/src/sound/script_bindings.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -namespace luabind { -class scope; -} - -namespace thrive { - -/** -* @brief Helper for sound script bindings -*/ -struct SoundBindings { - - /** - * @brief Lua bindings for sound systems - * - */ - static luabind::scope - luaBindings(); - -}; - -} - diff --git a/src/sound/sound_source_system.cpp b/src/sound/sound_source_system.cpp index ccf4ce0ad0d..c496c5ea013 100644 --- a/src/sound/sound_source_system.cpp +++ b/src/sound/sound_source_system.cpp @@ -9,7 +9,7 @@ #include "sound/sound_emitter.h" #include "sound/sound_manager.h" #include "ogre/scene_node_system.h" -#include "scripting/luabind.h" +#include "scripting/luajit.h" #include "util/make_unique.h" #include "game.h" @@ -26,32 +26,38 @@ static const int FADE_TIME = 5000; //5 seconds // Sound //////////////////////////////////////////////////////////////////////////////// -luabind::scope -Sound::luaBindings() { - using namespace luabind; - return class_("Sound") - .scope [ - class_("Properties") - .def_readwrite("playState", &Properties::playState) - .def_readwrite("loop", &Properties::loop) - .def_readwrite("volume", &Properties::volume) - .def_readwrite("maxDistance", &Properties::maxDistance) - .def_readwrite("rolloffFactor", &Properties::rolloffFactor) - .def_readwrite("referenceDistance", &Properties::referenceDistance) - .def_readwrite("priority", &Properties::priority) - ] - .enum_("PlayState") [ - value("Play", PlayState::Play), - value("Pause", PlayState::Pause), - value("Stop", PlayState::Stop) - ] - .def(constructor()) - .def("name", &Sound::name) - .def("pause", &Sound::pause) - .def("play", &Sound::play) - .def("stop", &Sound::stop) - .def_readonly("properties", &Sound::m_properties) - ; +void Sound::luaBindings(sol::state &lua) { + + lua.new_usertype("SoundProperties", + + sol::base_classes, sol::bases(), + + "playState", &Properties::playState, + "loop", &Properties::loop, + "volume", &Properties::volume, + "maxDistance", &Properties::maxDistance, + "rolloffFactor", &Properties::rolloffFactor, + "referenceDistance", &Properties::referenceDistance, + "priority", &Properties::priority + ); + + lua.new_usertype("Sound", + + sol::constructors>(), + + "PlayState", sol::var(lua.create_table_with( + "Play", PlayState::Play, + "Pause", PlayState::Pause, + "Stop", PlayState::Stop + )), + + "name", &Sound::name, + "pause", &Sound::pause, + "play", &Sound::play, + "stop", &Sound::stop, + + "properties", sol::readonly(&Sound::m_properties) + ); } @@ -144,71 +150,77 @@ Sound::storage() const { //Luabind helper functions static bool SoundSourceComponent_getAmbientSoundSource( - const SoundSourceComponent* self + const SoundSourceComponent &self ) { - return self->m_ambientSoundSource; + return self.m_ambientSoundSource; } static void SoundSourceComponent_setAmbientSoundSource( - SoundSourceComponent* self, + SoundSourceComponent &self, bool value ) { - self->m_ambientSoundSource = value; + self.m_ambientSoundSource = value; } static bool SoundSourceComponent_getAutoLoop( - const SoundSourceComponent* self + const SoundSourceComponent &self ) { - return self->m_autoLoop; + return self.m_autoLoop; } static void SoundSourceComponent_setAutoLoop( - SoundSourceComponent* self, + SoundSourceComponent &self, bool value ) { - self->m_autoLoop = value; + self.m_autoLoop = value; } static float SoundSourceComponent_getVolumeMultiplier( - const SoundSourceComponent* self + const SoundSourceComponent &self ) { - return self->m_volumeMultiplier; + return self.m_volumeMultiplier; } static void SoundSourceComponent_setVolumeMultiplier( - SoundSourceComponent* self, + SoundSourceComponent &self, float value ) { - self->m_volumeMultiplier = value; -} - -luabind::scope -SoundSourceComponent::luaBindings() { - using namespace luabind; - return class_("SoundSourceComponent") - .enum_("ID") [ - value("TYPE_ID", SoundSourceComponent::TYPE_ID) - ] - .scope [ - def("TYPE_NAME", &SoundSourceComponent::TYPE_NAME) - ] - .def(constructor<>()) - .def("addSound", &SoundSourceComponent::addSound) - .def("removeSound", &SoundSourceComponent::removeSound) - .def("playSound", &SoundSourceComponent::playSound) - .def("stopSound", &SoundSourceComponent::stopSound) - .def("queueSound", &SoundSourceComponent::queueSound) - .def("interpose", &SoundSourceComponent::interpose) - .def("interruptPlaying", &SoundSourceComponent::interruptPlaying) - .property("ambientSoundSource", SoundSourceComponent_getAmbientSoundSource, SoundSourceComponent_setAmbientSoundSource) - .property("autoLoop", SoundSourceComponent_getAutoLoop, SoundSourceComponent_setAutoLoop) - .property("volumeMultiplier", SoundSourceComponent_getVolumeMultiplier, SoundSourceComponent_setVolumeMultiplier) - ; + self.m_volumeMultiplier = value; +} + + + +void SoundSourceComponent::luaBindings( + sol::state &lua +){ + lua.new_usertype("SoundSourceComponent", + + "new", sol::factories([](){ + return std::make_unique(); + }), + + COMPONENT_BINDINGS(SoundSourceComponent), + + "addSound", &SoundSourceComponent::addSound, + "removeSound", &SoundSourceComponent::removeSound, + "playSound", &SoundSourceComponent::playSound, + "stopSound", &SoundSourceComponent::stopSound, + "queueSound", &SoundSourceComponent::queueSound, + "interpose", &SoundSourceComponent::interpose, + "interruptPlaying", &SoundSourceComponent::interruptPlaying, + + "ambientSoundSource", sol::property(&SoundSourceComponent_getAmbientSoundSource, + &SoundSourceComponent_setAmbientSoundSource), + "autoLoop", sol::property(&SoundSourceComponent_getAutoLoop, + &SoundSourceComponent_setAutoLoop), + "volumeMultiplier", sol::property(&SoundSourceComponent_getVolumeMultiplier, + &SoundSourceComponent_setVolumeMultiplier) + ); } Sound* @@ -313,15 +325,18 @@ REGISTER_COMPONENT(SoundSourceComponent) // SoundSourceSystem //////////////////////////////////////////////////////////////////////////////// -luabind::scope -SoundSourceSystem::luaBindings() { - using namespace luabind; - return class_("SoundSourceSystem") - .def(constructor<>()) - ; -} +void SoundSourceSystem::luaBindings(sol::state &lua) { + + lua.new_usertype("SoundSourceSystem", + + sol::constructors>(), + sol::base_classes, sol::bases(), + "init", &SoundSourceSystem::init + ); +} + struct SoundSourceSystem::Implementation { //Destroys all sounds, freeing up memory @@ -394,16 +409,15 @@ struct SoundSourceSystem::Implementation { Sound* sound, bool ambient, bool autoLoop, - GameState* gameState + GameStateData* gameState ) { static const bool STREAM = true; //Streaming sound from file - //3D sounds should not be attempted loaded before scenenodes are created - if (not ambient && (not sceneNodeComponent || not sceneNodeComponent->m_sceneNode)){ - return; - } + //if (not ambient && (not sceneNodeComponent || not sceneNodeComponent->m_sceneNode)){ + // return; + //} std::ostringstream soundName; - soundName << Game::instance().engine().currentGameState()->name() << sound->name() << entityId; + soundName << gameState->name() << sound->name() << entityId; auto soundManager = SoundManager::getSingleton(); auto ogreSound = soundManager->createSound( soundName.str(), @@ -455,7 +469,7 @@ struct SoundSourceSystem::Implementation { std::unordered_map > m_sounds; - GameState* m_gameState = nullptr; + GameStateData* m_gameState = nullptr; }; @@ -487,7 +501,10 @@ SoundSourceSystem::activate() { void SoundSourceSystem::deactivate() { - if (this->engine()->isSystemTimedShutdown(*this)) { + + + // TODO: avoid going through Lua Engine here for performance ... + if (this->gameState()->engine()->isSystemTimedShutdown(this)) { System::deactivate(); m_impl->removeAllSounds(); } @@ -495,17 +512,17 @@ SoundSourceSystem::deactivate() { for (auto& value : m_impl->m_entities) { std::get<0>(value.second)->m_autoSoundCountdown = 1500; } - this->engine()->timedSystemShutdown(*this, 1500); + this->gameState()->engine()->timedSystemShutdown(this, 1500); } } void SoundSourceSystem::init( - GameState* gameState + GameStateData* gameState ) { System::initNamed("SoundSourceSystem", gameState); - m_impl->m_entities.setEntityManager(&gameState->entityManager()); + m_impl->m_entities.setEntityManager(gameState->entityManager()); m_impl->m_gameState = gameState; } @@ -549,6 +566,9 @@ SoundSourceSystem::update( soundSourceComponent->m_autoLoop, this->gameState() ); + + if(!sound->m_sound) + throw std::runtime_error("Failed to restoreSound for new sound object"); } } } @@ -561,6 +581,26 @@ SoundSourceSystem::update( assert(sound->m_sound && "Sound was not intialized"); if (sound->m_properties.hasChanges()) { const auto& properties = sound->m_properties; + + if(!sound->m_sound){ + + std::cout << "invalid/uninitialized sound: " << + static_cast(sound) << " initialized now TODO: fix loading game" + << std::endl; + + m_impl->restoreSound( + value.first, + sceneNodeComponent, + sound, + soundSourceComponent->m_ambientSoundSource, + soundSourceComponent->m_autoLoop, + this->gameState() + ); + + if(!sound->m_sound) + throw std::runtime_error("Failed to restoreSound on invalid sound"); + } + auto ogreSound = sound->m_sound; assert(ogreSound && "Sound was not intialized properly"); ogreSound->loop(properties.loop and not soundSourceComponent->m_autoLoop); diff --git a/src/sound/sound_source_system.h b/src/sound/sound_source_system.h index 72866b12b37..4dcbab8a6a4 100644 --- a/src/sound/sound_source_system.h +++ b/src/sound/sound_source_system.h @@ -7,8 +7,8 @@ #include #include -namespace luabind { -class scope; +namespace sol { +class state; } namespace thrive { @@ -49,8 +49,7 @@ class Sound { * * @return */ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Play mode of the sound @@ -185,8 +184,7 @@ class SoundSourceComponent : public Component { * * @return **/ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Adds a new sound @@ -335,8 +333,7 @@ class SoundSourceSystem : public System { * * @return **/ - static luabind::scope - luaBindings(); + static void luaBindings(sol::state &lua); /** * @brief Constructor @@ -358,7 +355,7 @@ class SoundSourceSystem : public System { * @brief Initializes the system * */ - void init(GameState* gameState) override; + void init(GameStateData* gameState) override; /** * @brief Shuts the system down