From 8055e8541bc9ef4ac1c9e58d56d89a1f03513503 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henri=20Hyyryl=C3=A4inen?= Date: Fri, 5 May 2017 22:18:26 +0300 Subject: [PATCH] New Lua bindings and library (#511) * Updated setup script * Removed lua and luabind. Replaced with luajit and sol. Didn't change the code to use it yet * Added luajit to cmake * Moved individual script_bindings files' contents to script_initializer * Changed luabind forward declarations to sol forward declarations * Now ignoring a bunch of warnings so that sol.hpp can be included * Started fixing things to use sol, again this time not moving binding methods to a single file * System wrapper for lua. First few bindings done * More bindings * Collision filter fixed. .collisions now returns a table and works a bit differently * More wrapper updates * Tried to made wrappers more ready to use default values * Moving component stuff to use the new lua wrapper * Fixed some more wrappers * Hooked up engine to new lua stuff. More basic wrappers * Possibly not-optimal Component bindings * Created new compound registry bindings * Working on final script bindings Only some Ogre classes haven't been updated yet * Finished the largest file with new bindings, perhaps could be split * Thrive main library now compiles. tests still need fixing * Updated ogre tests, everything now compiles * Played around a bit with error reporting from lua * Fixed the first few classes for the new bindings * Added SystemWrapper bindings * Added system class creation helper * Fixing lua scripts for new things * Engine now more carefully casts things to Systems * Added a new Bullet physics wrapper * Started adding Lua replacements of C++ GameState and Engine * Lua fixes * Added luabindings for Game * Removed stuff that is now in lua from the C++ side * Started moving stuff from C++ to Lua and creating wrappers for C++ code to use Fixing lua scripts and creating wrappers for C++ to use * Renamed GameState to GameStateData * Moved stuff from engine.cpp to lua engine Also fixed compiling entity.cpp * Updated to new GameStateData * C++ now compiles. Lua files are still a mess * Finished reimplementing the removed c++ stuff in lua Switched lua classes to use "create" method as a constructor so now "init" can be used like before * First Lua systems can now be created without errors There are still bunch of lua scripts that need fixing * Updated sol library * Exposed ComponentWrapper to Lua * Fixed engine binding things as sol::var when they should have been sol::property * Fixed Component registering from Lua * Rewrote microbe ai classes for new sol bindings * Added notes about changed things Fixed species_system.lua. There was an improperly formatted function call in this file, I added an explanation to the notes on how to fix this * Lua stacktraces now don't include the top most entry the entry was always [C]:-1 so it wasn't very helpful * Fixed Component::TYPE_ID access from Lua * Removed some old systems code * Fixed indentation * Updated examples * Updated more Lua files to use new classes * Added missing call to .new on EntityFilter * Added missing call to ScriptEntityFilter bindings * The engine now stops loading Lua scripts after the first failed file * Exposed correct constructor for PowerupSystem * More fixes to Lua files * Added cmake argument LUA_CHECKS which enables more lua debug checks Also the linuxrelease refuses to build if LUA_CHECKS is on * Updated Entity documentation * Exposed EntityManager to Lua * Updated systems to have a proper init method and added base classes to some systems * Added some lua class checks and some notes about usage * Rewrote some more Lua scripts to use new classes * Some random formatting change * Added get method for current GameState to Engine * Fixed C++ systems that relied on broken Entity constructors * Added table call constructors for some Ogre types * Changed the lua error functions slightly * Fixed some lua bindings being wrong * Still fixing lua scripts * Removed old system that doesn't even work with Ogre 2.0 * Added missing Touchable bases to RigidBodyComponent * shutdown is now called even if an error occurs * cleanup * Replaced entity addComponent luabindings * C++ components now expose a factory to lua. Also updated entity to accept the factory constructed c++ stuff * Renamed factory functions to be just 'new' * Lua fixed class calls * Added an unwrap function to lua * Collision shapes now properly use factories to create shared_ptrs * Components now share a macro for binding common things. + Added the component "castFrom" function * Fixed Microbe not casting accessed Components to their subclasses * All setup code now runs. But the game crashes just after entering the main loop * Fixed moving temporary prevents copy elision * Fixed engine shutdown causing a crash CEGUIWIndow is now a factory, because probably CEGUI will delete the window with its parent GameStateData owning the SceneManager checks is ogre still valid before destructing * Formatting change. Main loop now starts * Fixed reading thrive version when the file was one folder up * Fixed startup message thrive version * Exposed rootGuiWindow again * Added processRemovals to EntityManager Lua bindings * Exposed paused Engine property to Lua * Thrive now starts and shows the menu correctly! * Made FPS counter actually accurate * Made Game time utilities take things by reference * Added frame time counting to FPS counter * Added a convenience getComponent lua function * Switched fixes to use the new convenience getComponent * Made Components use cheaper casts when accessed from Lua * Various lua binding fixes and lua updates to use new classes * setup now attempts to set LUAJIT_ENABLE_LUA52COMPAT on in luajit makefile * Fixed microbe spawn function not correctly attempting to spawn a cell Also removed slightly confusing call constructor that isn't actually used all that often * Microbe editor can now be entered * Added a workaround for crash after loading save * Fixed container bindings to accept "get" without default value * Exposed EntityManager methods required for saving/loading * Restored intro video * Systems no longer have an enabled property, GameState already manages which ones to run Fixed saving and loading * Changed to use the new class syntax * Everything now mostly work There's just 3 cells just after splitting and all the compounds drain out of cells immediately (and there's a workaround to a crash in restoring sounds after loading game) * Fixed bug venting everything Current bugs: 3 cells spawn after dividing when tutorial is completed and after that (but not when tutorial is skipped) If tutorial is complete and the game is started again from the main menu and the tutorial is skipped the game crashes. Also other way around works: if you first play normally and then play the tutorial the game crashes when exiting the editor. * Fixed including sol directly * Removed unneeded lua link creation * Fixed packaging script and included librtmp in releases * Updated SOL CEGUIWindow is now a basic usertype, which can be used as an example if others need to be converted * Updated CEGUI version * Added a few more libraries Narotiza mentioned being missing * Windows support for luajit * Fixed setup system not being configured to pull updates * Updated sol to fix compile errors * Updated CEGUI version also some cleanup on CEGUIVideoPlayer * Added option to profile Lua memory usage * Split some really long lines * Lua now automatically sets the version number in the GUI * Removed Cg program manager from CMakeLists and added a better error for missing Ogre plugins * Removed more references to CgProgramManager plugin * Added a cscope indexing script * Added a commented out debugging line * Fixed Lua errors caused by the earlier merge also removed some process speed things from bio_process_registry.cpp * Workaround for compile errors due to disagreement regarding cegui version --- .gitignore | 5 + .gitmodules | 6 +- CMakeLists.txt | 104 +- SetupThrive.rb | 54 +- contrib/lua/CMakeLists.txt | 86 - contrib/lua/building.txt | 6 + contrib/lua/lua/README | 6 - contrib/lua/lua/doc/contents.html | 533 - contrib/lua/lua/doc/logo.gif | Bin 4232 -> 0 bytes contrib/lua/lua/doc/lua.1 | 116 - contrib/lua/lua/doc/lua.css | 83 - contrib/lua/lua/doc/luac.1 | 118 - contrib/lua/lua/doc/manual.css | 26 - contrib/lua/lua/doc/manual.html | 10507 ------------ contrib/lua/lua/doc/osi-certified-72x60.png | Bin 3774 -> 0 bytes contrib/lua/lua/doc/readme.html | 412 - contrib/lua/lua/src/lapi.c | 1284 -- contrib/lua/lua/src/lapi.h | 24 - contrib/lua/lua/src/lauxlib.c | 959 -- contrib/lua/lua/src/lauxlib.h | 212 - contrib/lua/lua/src/lbaselib.c | 458 - contrib/lua/lua/src/lbitlib.c | 211 - contrib/lua/lua/src/lcode.c | 881 - contrib/lua/lua/src/lcode.h | 83 - contrib/lua/lua/src/lcorolib.c | 155 - contrib/lua/lua/src/lctype.c | 52 - contrib/lua/lua/src/lctype.h | 95 - contrib/lua/lua/src/ldblib.c | 398 - contrib/lua/lua/src/ldebug.c | 580 - contrib/lua/lua/src/ldebug.h | 34 - contrib/lua/lua/src/ldo.c | 673 - contrib/lua/lua/src/ldo.h | 46 - contrib/lua/lua/src/ldump.c | 173 - contrib/lua/lua/src/lfunc.c | 161 - contrib/lua/lua/src/lfunc.h | 33 - contrib/lua/lua/src/lgc.c | 1213 -- contrib/lua/lua/src/lgc.h | 157 - contrib/lua/lua/src/linit.c | 67 - contrib/lua/lua/src/liolib.c | 665 - contrib/lua/lua/src/llex.c | 527 - contrib/lua/lua/src/llex.h | 78 - contrib/lua/lua/src/llimits.h | 309 - contrib/lua/lua/src/lmathlib.c | 279 - contrib/lua/lua/src/lmem.c | 99 - contrib/lua/lua/src/lmem.h | 57 - contrib/lua/lua/src/loadlib.c | 725 - contrib/lua/lua/src/lobject.c | 287 - contrib/lua/lua/src/lobject.h | 607 - contrib/lua/lua/src/lopcodes.c | 107 - contrib/lua/lua/src/lopcodes.h | 288 - contrib/lua/lua/src/loslib.c | 323 - contrib/lua/lua/src/lparser.c | 1638 -- contrib/lua/lua/src/lparser.h | 119 - contrib/lua/lua/src/lstate.c | 322 - contrib/lua/lua/src/lstate.h | 228 - contrib/lua/lua/src/lstring.c | 185 - contrib/lua/lua/src/lstring.h | 46 - contrib/lua/lua/src/lstrlib.c | 1019 -- contrib/lua/lua/src/ltable.c | 588 - contrib/lua/lua/src/ltable.h | 41 - contrib/lua/lua/src/ltablib.c | 283 - contrib/lua/lua/src/ltm.c | 77 - contrib/lua/lua/src/ltm.h | 57 - contrib/lua/lua/src/lua.c | 497 - contrib/lua/lua/src/lua.h | 444 - contrib/lua/lua/src/lua.hpp | 9 - contrib/lua/lua/src/luac.c | 432 - contrib/lua/lua/src/luaconf.h | 551 - contrib/lua/lua/src/lualib.h | 55 - contrib/lua/lua/src/lundump.c | 258 - contrib/lua/lua/src/lundump.h | 28 - contrib/lua/lua/src/lvm.c | 867 - contrib/lua/lua/src/lvm.h | 44 - contrib/lua/lua/src/lzio.c | 76 - contrib/lua/lua/src/lzio.h | 65 - contrib/lua/luajit | 1 + contrib/lua/sol.hpp | 14018 ++++++++++++++++ contrib/lua/sol_changes.txt | 8 + contrib/luabind | 1 - cpack/PackageProject.rb | 14 +- linux_setup/RubySetupSystem.rb | 106 +- linux_setup/RunCodeIndexing.rb | 26 + mingw_setup/boost/install.ps1 | 60 +- mingw_setup/cAudio/install.ps1 | 6 + mingw_setup/cegui/install.ps1 | 2 +- mingw_setup/luajit/install.ps1 | 50 + mingw_setup/mingw/install.ps1 | 6 +- mingw_setup/ogre/install.ps1 | 8 +- mingw_setup/ogre_dependencies/install.ps1 | 1 + mingw_setup/setup.ps1 | 9 +- scripts/class.lua | 101 + scripts/colours.lua | 5 +- scripts/console.lua | 233 +- scripts/console_commands.lua | 28 +- scripts/examples/component.lua | 34 +- scripts/examples/system.lua | 47 +- scripts/game.lua | 85 + scripts/lua_engine/game_state.lua | 247 + scripts/{ => lua_engine}/keymap.lua | 20 +- scripts/lua_engine/lua_engine.lua | 460 + scripts/lua_engine/manifest.txt | 9 + scripts/lua_engine/system.lua | 63 + scripts/lua_notes.md | 178 + scripts/main_menu/main_menu_hud.lua | 147 +- scripts/main_menu/setup.lua | 67 +- scripts/manifest.txt | 13 +- scripts/microbe_editor/microbe_editor.lua | 115 +- scripts/microbe_editor/microbe_editor_hud.lua | 176 +- scripts/microbe_editor/setup.lua | 78 +- scripts/microbe_stage/agent_vacuole.lua | 50 +- scripts/microbe_stage/biome.lua | 15 +- scripts/microbe_stage/camera.lua | 31 +- scripts/microbe_stage/configs.lua | 4 +- scripts/microbe_stage/microbe.lua | 453 +- scripts/microbe_stage/microbe_ai.lua | 134 +- scripts/microbe_stage/microbe_control.lua | 35 +- scripts/microbe_stage/microbe_replacement.lua | 73 +- scripts/microbe_stage/microbe_stage_hud.lua | 114 +- scripts/microbe_stage/movement_organelle.lua | 72 +- scripts/microbe_stage/nucleus_organelle.lua | 127 +- scripts/microbe_stage/organelle.lua | 148 +- scripts/microbe_stage/organelle_component.lua | 49 +- scripts/microbe_stage/patch_system.lua | 59 +- scripts/microbe_stage/process_organelle.lua | 38 +- scripts/microbe_stage/setup.lua | 242 +- scripts/microbe_stage/spawn_system.lua | 91 +- scripts/microbe_stage/species_system.lua | 134 +- scripts/microbe_stage/storage_organelle.lua | 41 +- .../switch_game_state_system.lua | 13 +- .../microbe_stage_tutorial_hud.lua | 116 +- scripts/microbe_stage_tutorial/setup.lua | 139 +- scripts/quick_save.lua | 47 +- scripts/sandbox/game_state.lua | 22 - scripts/util.lua | 108 +- src/bullet/CMakeLists.txt | 4 +- src/bullet/bullet_to_ogre_system.cpp | 23 +- src/bullet/bullet_to_ogre_system.h | 9 +- src/bullet/collision_filter.cpp | 42 +- src/bullet/collision_filter.h | 11 +- src/bullet/collision_shape.cpp | 184 +- src/bullet/collision_shape.h | 67 +- src/bullet/collision_system.cpp | 75 +- src/bullet/collision_system.h | 15 +- src/bullet/debug_drawing.cpp | 22 +- src/bullet/debug_drawing.h | 5 +- src/bullet/physical_world.cpp | 59 + src/bullet/physical_world.h | 46 + src/bullet/rigid_body_system.cpp | 149 +- src/bullet/rigid_body_system.h | 17 +- src/bullet/script_bindings.cpp | 48 - src/bullet/script_bindings.h | 25 - src/bullet/update_physics_system.cpp | 26 +- src/bullet/update_physics_system.h | 5 +- src/engine/CMakeLists.txt | 2 - src/engine/component.cpp | 106 +- src/engine/component.h | 22 +- src/engine/component_factory.cpp | 58 +- src/engine/component_factory.h | 7 +- src/engine/engine.cpp | 594 +- src/engine/engine.h | 159 +- src/engine/entity.cpp | 167 +- src/engine/entity.h | 39 +- src/engine/entity_manager.cpp | 31 + src/engine/entity_manager.h | 18 +- src/engine/game_state.cpp | 290 +- src/engine/game_state.h | 240 +- src/engine/player_data.cpp | 48 +- src/engine/player_data.h | 13 +- src/engine/rng.cpp | 24 +- src/engine/rng.h | 7 +- src/engine/rolling_grid.cpp | 20 +- src/engine/rolling_grid.h | 7 +- src/engine/script_bindings.cpp | 31 - src/engine/script_bindings.h | 24 - src/engine/serialization.cpp | 115 +- src/engine/serialization.h | 33 +- src/engine/system.cpp | 161 +- src/engine/system.h | 36 +- src/engine/tests/entity.cpp | 83 +- src/engine/touchable.cpp | 19 +- src/engine/touchable.h | 7 +- src/game.cpp | 94 +- src/game.h | 18 + src/general/CMakeLists.txt | 2 - src/general/locked_map.cpp | 25 +- src/general/locked_map.h | 9 +- src/general/powerup_system.cpp | 59 +- src/general/powerup_system.h | 15 +- src/general/script_bindings.cpp | 22 - src/general/script_bindings.h | 26 - src/general/timed_life_system.cpp | 50 +- src/general/timed_life_system.h | 13 +- src/gui/CEGUIVideoPlayer.cpp | 76 +- src/gui/CEGUIVideoPlayer.h | 8 +- src/gui/CEGUIWindow.cpp | 143 +- src/gui/CEGUIWindow.h | 16 +- src/gui/CMakeLists.txt | 2 - src/gui/script_bindings.cpp | 99 - src/gui/script_bindings.h | 26 - src/gui/script_wrappers.cpp | 17 +- src/gui/script_wrappers.h | 15 +- src/microbe_stage/CMakeLists.txt | 2 - src/microbe_stage/agent_cloud_system.cpp | 60 +- src/microbe_stage/agent_cloud_system.h | 12 +- src/microbe_stage/bio_process_registry.cpp | 87 +- src/microbe_stage/bio_process_registry.h | 11 +- src/microbe_stage/compound.cpp | 56 +- src/microbe_stage/compound.h | 14 +- .../compound_absorber_system.cpp | 70 +- src/microbe_stage/compound_absorber_system.h | 10 +- src/microbe_stage/compound_cloud_system.cpp | 154 +- src/microbe_stage/compound_cloud_system.h | 12 +- src/microbe_stage/compound_emitter_system.cpp | 114 +- src/microbe_stage/compound_emitter_system.h | 13 +- src/microbe_stage/compound_registry.cpp | 197 +- src/microbe_stage/compound_registry.h | 18 +- src/microbe_stage/membrane_system.cpp | 68 +- src/microbe_stage/membrane_system.h | 14 +- src/microbe_stage/process_system.cpp | 95 +- src/microbe_stage/process_system.h | 18 +- src/microbe_stage/script_bindings.cpp | 41 - src/microbe_stage/script_bindings.h | 26 - src/microbe_stage/species_component.cpp | 78 +- src/microbe_stage/species_component.h | 11 +- src/ogre/CMakeLists.txt | 2 - src/ogre/camera_system.cpp | 81 +- src/ogre/camera_system.h | 12 +- src/ogre/keyboard.cpp | 337 +- src/ogre/keyboard.h | 7 +- src/ogre/light_system.cpp | 93 +- src/ogre/light_system.h | 12 +- src/ogre/membrane_generation_system.cpp | 29 +- src/ogre/membrane_generation_system.h | 12 +- src/ogre/mouse.cpp | 75 +- src/ogre/mouse.h | 7 +- src/ogre/render_system.cpp | 25 +- src/ogre/render_system.h | 5 +- src/ogre/scene_node_system.cpp | 171 +- src/ogre/scene_node_system.h | 24 +- src/ogre/script_bindings.cpp | 647 - src/ogre/script_bindings.h | 35 - src/ogre/sky_system.cpp | 79 +- src/ogre/sky_system.h | 12 +- src/ogre/tests/script_bindings.cpp | 22 +- src/ogre/tests/sky_system.cpp | 32 +- src/ogre/text_overlay.cpp | 288 - src/ogre/text_overlay.h | 206 - src/ogre/viewport_system.cpp | 281 - src/ogre/viewport_system.h | 209 - src/ogre/workspace_system.cpp | 67 +- src/ogre/workspace_system.h | 12 +- src/scripting/CMakeLists.txt | 10 +- src/scripting/lua_state.cpp | 59 - src/scripting/lua_state.h | 98 - src/scripting/luabind.h | 81 - src/scripting/luajit.h | 49 + src/scripting/script_bindings.cpp | 12 - src/scripting/script_bindings.h | 25 - src/scripting/script_entity_filter.cpp | 55 +- src/scripting/script_entity_filter.h | 14 +- src/scripting/script_helpers.h | 35 + src/scripting/script_initializer.cpp | 1150 +- src/scripting/script_initializer.h | 12 +- src/scripting/script_wrapper.h | 25 + src/scripting/tests/do_string_assertion.h | 23 - src/scripting/wrapper_classes.cpp | 88 + src/scripting/wrapper_classes.h | 52 + src/sound/CMakeLists.txt | 2 - src/sound/script_bindings.cpp | 18 - src/sound/script_bindings.h | 24 - src/sound/sound_source_system.cpp | 202 +- src/sound/sound_source_system.h | 15 +- 272 files changed, 21793 insertions(+), 39215 deletions(-) delete mode 100644 contrib/lua/CMakeLists.txt create mode 100644 contrib/lua/building.txt delete mode 100644 contrib/lua/lua/README delete mode 100644 contrib/lua/lua/doc/contents.html delete mode 100644 contrib/lua/lua/doc/logo.gif delete mode 100644 contrib/lua/lua/doc/lua.1 delete mode 100644 contrib/lua/lua/doc/lua.css delete mode 100644 contrib/lua/lua/doc/luac.1 delete mode 100644 contrib/lua/lua/doc/manual.css delete mode 100644 contrib/lua/lua/doc/manual.html delete mode 100644 contrib/lua/lua/doc/osi-certified-72x60.png delete mode 100644 contrib/lua/lua/doc/readme.html delete mode 100644 contrib/lua/lua/src/lapi.c delete mode 100644 contrib/lua/lua/src/lapi.h delete mode 100644 contrib/lua/lua/src/lauxlib.c delete mode 100644 contrib/lua/lua/src/lauxlib.h delete mode 100644 contrib/lua/lua/src/lbaselib.c delete mode 100644 contrib/lua/lua/src/lbitlib.c delete mode 100644 contrib/lua/lua/src/lcode.c delete mode 100644 contrib/lua/lua/src/lcode.h delete mode 100644 contrib/lua/lua/src/lcorolib.c delete mode 100644 contrib/lua/lua/src/lctype.c delete mode 100644 contrib/lua/lua/src/lctype.h delete mode 100644 contrib/lua/lua/src/ldblib.c delete mode 100644 contrib/lua/lua/src/ldebug.c delete mode 100644 contrib/lua/lua/src/ldebug.h delete mode 100644 contrib/lua/lua/src/ldo.c delete mode 100644 contrib/lua/lua/src/ldo.h delete mode 100644 contrib/lua/lua/src/ldump.c delete mode 100644 contrib/lua/lua/src/lfunc.c delete mode 100644 contrib/lua/lua/src/lfunc.h delete mode 100644 contrib/lua/lua/src/lgc.c delete mode 100644 contrib/lua/lua/src/lgc.h delete mode 100644 contrib/lua/lua/src/linit.c delete mode 100644 contrib/lua/lua/src/liolib.c delete mode 100644 contrib/lua/lua/src/llex.c delete mode 100644 contrib/lua/lua/src/llex.h delete mode 100644 contrib/lua/lua/src/llimits.h delete mode 100644 contrib/lua/lua/src/lmathlib.c delete mode 100644 contrib/lua/lua/src/lmem.c delete mode 100644 contrib/lua/lua/src/lmem.h delete mode 100644 contrib/lua/lua/src/loadlib.c delete mode 100644 contrib/lua/lua/src/lobject.c delete mode 100644 contrib/lua/lua/src/lobject.h delete mode 100644 contrib/lua/lua/src/lopcodes.c delete mode 100644 contrib/lua/lua/src/lopcodes.h delete mode 100644 contrib/lua/lua/src/loslib.c delete mode 100644 contrib/lua/lua/src/lparser.c delete mode 100644 contrib/lua/lua/src/lparser.h delete mode 100644 contrib/lua/lua/src/lstate.c delete mode 100644 contrib/lua/lua/src/lstate.h delete mode 100644 contrib/lua/lua/src/lstring.c delete mode 100644 contrib/lua/lua/src/lstring.h delete mode 100644 contrib/lua/lua/src/lstrlib.c delete mode 100644 contrib/lua/lua/src/ltable.c delete mode 100644 contrib/lua/lua/src/ltable.h delete mode 100644 contrib/lua/lua/src/ltablib.c delete mode 100644 contrib/lua/lua/src/ltm.c delete mode 100644 contrib/lua/lua/src/ltm.h delete mode 100644 contrib/lua/lua/src/lua.c delete mode 100644 contrib/lua/lua/src/lua.h delete mode 100644 contrib/lua/lua/src/lua.hpp delete mode 100644 contrib/lua/lua/src/luac.c delete mode 100644 contrib/lua/lua/src/luaconf.h delete mode 100644 contrib/lua/lua/src/lualib.h delete mode 100644 contrib/lua/lua/src/lundump.c delete mode 100644 contrib/lua/lua/src/lundump.h delete mode 100644 contrib/lua/lua/src/lvm.c delete mode 100644 contrib/lua/lua/src/lvm.h delete mode 100644 contrib/lua/lua/src/lzio.c delete mode 100644 contrib/lua/lua/src/lzio.h create mode 160000 contrib/lua/luajit create mode 100755 contrib/lua/sol.hpp create mode 100644 contrib/lua/sol_changes.txt delete mode 160000 contrib/luabind create mode 100755 linux_setup/RunCodeIndexing.rb create mode 100644 mingw_setup/luajit/install.ps1 create mode 100644 scripts/class.lua create mode 100644 scripts/game.lua create mode 100644 scripts/lua_engine/game_state.lua rename scripts/{ => lua_engine}/keymap.lua (76%) create mode 100644 scripts/lua_engine/lua_engine.lua create mode 100644 scripts/lua_engine/manifest.txt create mode 100644 scripts/lua_engine/system.lua create mode 100644 scripts/lua_notes.md delete mode 100644 scripts/sandbox/game_state.lua create mode 100644 src/bullet/physical_world.cpp create mode 100644 src/bullet/physical_world.h delete mode 100644 src/bullet/script_bindings.cpp delete mode 100644 src/bullet/script_bindings.h delete mode 100644 src/engine/script_bindings.cpp delete mode 100644 src/engine/script_bindings.h delete mode 100644 src/general/script_bindings.cpp delete mode 100644 src/general/script_bindings.h delete mode 100644 src/gui/script_bindings.cpp delete mode 100644 src/gui/script_bindings.h delete mode 100644 src/microbe_stage/script_bindings.cpp delete mode 100644 src/microbe_stage/script_bindings.h delete mode 100644 src/ogre/script_bindings.cpp delete mode 100644 src/ogre/script_bindings.h delete mode 100644 src/ogre/text_overlay.cpp delete mode 100644 src/ogre/text_overlay.h delete mode 100644 src/ogre/viewport_system.cpp delete mode 100644 src/ogre/viewport_system.h delete mode 100644 src/scripting/lua_state.cpp delete mode 100644 src/scripting/lua_state.h delete mode 100644 src/scripting/luabind.h create mode 100644 src/scripting/luajit.h delete mode 100644 src/scripting/script_bindings.cpp delete mode 100644 src/scripting/script_bindings.h create mode 100644 src/scripting/script_helpers.h create mode 100644 src/scripting/script_wrapper.h delete mode 100644 src/scripting/tests/do_string_assertion.h create mode 100644 src/scripting/wrapper_classes.cpp create mode 100644 src/scripting/wrapper_classes.h delete mode 100644 src/sound/script_bindings.cpp delete mode 100644 src/sound/script_bindings.h 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 2f5e4ac2e742fbb7675e739879211553758aea9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4232 zcmeH``9G8i;K!fm@ywWE@XWZzZ5SF?A>^uN#>^O6HI%DVL*tw8h1>$H%uPC0$QQ=txe!o}PX)Ev+jn>*nFZ-TC=<^76WcLZL(=DJm)| zEiIKwrInSHXU?3duCC_u@5try#>U2`rlw1mF15F}U%!66tE;QKyIUmcDJ<+QF77*W zFJd#&)VAl)kJ6K zi<>tmZ{3>g>+2gB7#JQNe(>OdLh;A=`1q42PbMZNCMPF*dXxhLZw3aYhlZwyhu@Bj z%#4n{d-Q1b$&i4QMce4L#8^!oMdw{PDnm4D66&3*dxX=-YIX6DQL_g`jbzkd4k zZDCoLf=%jL&vIeE zO=XcZ9fxt`f}-DQ^%H*PHMUs(JN%UWkI|Y8h9#6~I$Cw@{RqzO4&P-x;jHCPJ6Ks2 zoU%foi)nXd_sdkiuJa@@5J4RrreKfWSnz5>eMa5yTP=)16uu)TIdx~Fhho))6jZl) z($*i>QrIX4u}u3>m{WSn_ehkUGQ& zs})aUlTH1Cj1g3ZE3=MPXsSniEwJ{e6C3N#HjD=B4`8rWIsz!a7ecYpec?WuH+y?Wsm18^$cS4WmHhH3_=r zh*ILlm*X1dB^E5($KVl&zT524%l}vpHg%;Y+LezV_&TAJCmH`idhuj-n$4FZ)UE|jXLayXa-&O3Q z?Iyo!x*$5hD_HfFnDfGYj-RD|eIb7I?%>Y_kf%}Nbd`BXb4l1(Pc+}zoUR|9%_!7f zum2T;wbx&pohtI+&@~wm3nH9xLbOYkg*`phY~TK5iC#3tZNXo9s`cahx+8j2)rh5C zQgZh6D7Ekgib|hpdhxYf{r!PTJc z!vsYG@{hA}l5kL)g)0N_)(nC<*L0qdUi*3fD5<0sn58>zklX@6Tyv3*X^}m=Cqc40 zQ6GfjG@kd1mFIm`qaubWunm_?P>WUZ`9|f_z%gGHi{n|uu(N8!L=aw5(qAcDj$-QK zu;D#j6e42OXTQD>)i zlvM$LX`$n9EEjxM$_QDF&a z7cme_rat}aXmiN&7`6Q98}dh4Z@8L_uAb#nK&GQiZOOUnA9kAEVb-csuN1AWL=sXt z{z9GCN%%l0N9QvJM;tl1nf?rrhT{*sE%4WqR?{0~aIrfCcCPxf4eh_*jjQ=`$p53Y z@_|Rsx2i}|3dNFetMQQ5y8agTK-E0D&7;@3-LUxfvZ7 z7~!p@&mFe^oca2^F|CBt+4Ly?^ViUVSAhAH>JH1GN{^TQb3QnM*x0ZiZgDyNI@_c3 z@{}(WH4*e3T~}n_^0}da4ElIxAf9B!IaL7z9X0Icvj@cIkE*~W--17&WN`Ea5)Gn> z#gpfRb#44;jVTOS{FuaZgd(-ZD848=fQzgST2MxR>wSLc1P=2HDvByz$B$IsNCC6L zCM?nK*OHj6JA9gz4|b<~2%RqelN^1Y)jIqnRs!mDKV^BQTfo@hOtz7*Ug}Ee^cbsj zNNlumRgAmt`1$b5MO;&X#5-EP<}AaY;52ihIpem&MTea$?3!DrwbYa?V`NjEfWF3z zUq5JY8Ch;L{kx&J<1K&Fe_Vn;8gk{%c;n?nA2(%(f%DCRHko3uT~VI7RE^JWEqaCq z)i|%nfj(*4|V*XhY3W%M# z*yn6SN4eUOHFxAD7B&9E_PO`G5bqgs^@J{9bk>&;PlUAiqo`j3rjQDgD!}mqLUtb` zCB}ZD@m@s#pf7bV4jreOC*JVfHZ|hyHkX!rauVdd_I9FL45d{gWH!DNYu;i(|8wVx z!)eLY6YXxZ2{Coae0xuTnxo1ACb5wtED?VJAz&@114$Ao6uG9YSy*!K;m5_mj=0^j zw%?b%AOs}ql@$TGC-!^^*_#RT5+y_kTzQG9?LPPZNAtt6cJ%d2$q(I)ws21*?xF%p zN+NeGnWRQ<5w70Rc(bl|S0Xr&5@WrmdurS|IgPB|EyuZO#=tf!35)G!HJ`E1jh^lH zTBu~rL#DhQO*XAWtBt}JHH$lc>3%r0yD|maW_(W=B_J+y164F>O4dO|@&@N3Z3p=B zmVl{|^Z&#atHY|9n&la)SBo}=3AFIF=_~LDJk6MTlA73CXtX+4bnn+c!}N}IPa5pp zwyqbqIkN|I3j_3vD6$zlu{Ps(N-J|*qzEt<$5Soh;s^AuKv_ z-Tz+O1_~6*9CJh4r}`}mbUtjbf#fX58RIIkP6&@*y9kI|5fK*_eZ%jv3U$5*x<>D_ za2M(TV8?XY+9xy>0En#Te<6X4$0&dbyd(go$~eq4u(u)EA2msyF<5ssLZ zDP|I}=~Bi_q)whWv=Ri~L1TYaNrR;5cMB@s78HF1{w&r(6GJ;_2@bD?#1p&P4n_?n0#9Vx~$qjMX=Lk?*!@aKo8m&$iPO7S{g3sFUwr`*<53(68xx7?z`2xf# zGSicy_zI(PJ|%qc2VxT+6bOE--a{k&aq7$<<= zFt)C<@|TPs`+eycPGoGL1Wn9|Ed&a2JyAmjnkm3DQBECX&`bt~odH9cUPq4M{#$-q?G3!)qO-it*&YHw+j-O* zYy78V*`4Q=kQ@^Yz*b6Tal4(Me7BGeS^;phWAW8+L^5A(=D)t?k!rLIwVAKtq=f7h z&^n&VX1-T$ScvN~639QLZ^d@niMaS{C-Q)8oHHBhwD*r~-1Ze#Q)GFOFptW32a-uF z;M@ux%i%a25NwIgXt*=GHX$3~aZfwovGL!}sf?j9TsVo^cn(%&a<--0mIXYqGe>c PWz_J}_#7St0k8iB@FZjZ 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.) - - - -

    - -
  • "add": -the + operation. - - - -

    -The function getbinhandler below defines how Lua chooses a handler -for a binary operation. -First, Lua tries the first operand. -If its type does not define a handler for the operation, -then Lua tries the second operand. - -

    -     function getbinhandler (op1, op2, event)
    -       return metatable(op1)[event] or metatable(op2)[event]
    -     end
    -

    -By using this function, -the behavior of the op1 + op2 is - -

    -     function add_event (op1, op2)
    -       local o1, o2 = tonumber(op1), tonumber(op2)
    -       if o1 and o2 then  -- both operands are numeric?
    -         return o1 + o2   -- '+' here is the primitive 'add'
    -       else  -- at least one of the operands is not numeric
    -         local h = getbinhandler(op1, op2, "__add")
    -         if h then
    -           -- call the handler with both operands
    -           return (h(op1, op2))
    -         else  -- no handler available: default behavior
    -           error(···)
    -         end
    -       end
    -     end
    -

    -

  • - -
  • "sub": -the - operation. - -Behavior similar to the "add" operation. -
  • - -
  • "mul": -the * operation. - -Behavior similar to the "add" operation. -
  • - -
  • "div": -the / operation. - -Behavior similar to the "add" operation. -
  • - -
  • "mod": -the % operation. - -Behavior similar to the "add" operation, -with the operation -o1 - floor(o1/o2)*o2 as the primitive operation. -
  • - -
  • "pow": -the ^ (exponentiation) operation. - -Behavior similar to the "add" operation, -with the function pow (from the C math library) -as the primitive operation. -
  • - -
  • "unm": -the unary - operation. - - -
    -     function unm_event (op)
    -       local o = tonumber(op)
    -       if o then  -- operand is numeric?
    -         return -o  -- '-' here is the primitive 'unm'
    -       else  -- the operand is not numeric.
    -         -- Try to get a handler from the operand
    -         local h = metatable(op).__unm
    -         if h then
    -           -- call the handler with the operand
    -           return (h(op))
    -         else  -- no handler available: default behavior
    -           error(···)
    -         end
    -       end
    -     end
    -

    -

  • - -
  • "concat": -the .. (concatenation) operation. - - -
    -     function concat_event (op1, op2)
    -       if (type(op1) == "string" or type(op1) == "number") and
    -          (type(op2) == "string" or type(op2) == "number") then
    -         return op1 .. op2  -- primitive string concatenation
    -       else
    -         local h = getbinhandler(op1, op2, "__concat")
    -         if h then
    -           return (h(op1, op2))
    -         else
    -           error(···)
    -         end
    -       end
    -     end
    -

    -

  • - -
  • "len": -the # operation. - - -
    -     function len_event (op)
    -       if type(op) == "string" then
    -         return strlen(op)      -- primitive string length
    -       else
    -         local h = metatable(op).__len
    -         if h then
    -           return (h(op))       -- call handler with the operand
    -         elseif type(op) == "table" then
    -           return #op              -- primitive table length
    -         else  -- no handler available: error
    -           error(···)
    -         end
    -       end
    -     end
    -

    -See §3.4.6 for a description of the length of a table. -

  • - -
  • "eq": -the == operation. - -The function getequalhandler defines how Lua chooses a metamethod -for equality. -A metamethod is selected only when both values -being compared have the same type -and the same metamethod for the selected operation, -and the values are either tables or full userdata. - -
    -     function getequalhandler (op1, op2)
    -       if type(op1) ~= type(op2) or
    -          (type(op1) ~= "table" and type(op1) ~= "userdata") then
    -         return nil     -- different values
    -       end
    -       local mm1 = metatable(op1).__eq
    -       local mm2 = metatable(op2).__eq
    -       if mm1 == mm2 then return mm1 else return nil end
    -     end
    -

    -The "eq" event is defined as follows: - -

    -     function eq_event (op1, op2)
    -       if op1 == op2 then   -- primitive equal?
    -         return true   -- values are equal
    -       end
    -       -- try metamethod
    -       local h = getequalhandler(op1, op2)
    -       if h then
    -         return not not h(op1, op2)
    -       else
    -         return false
    -       end
    -     end
    -

    -Note that the result is always a boolean. -

  • - -
  • "lt": -the < operation. - - -
    -     function lt_event (op1, op2)
    -       if type(op1) == "number" and type(op2) == "number" then
    -         return op1 < op2   -- numeric comparison
    -       elseif type(op1) == "string" and type(op2) == "string" then
    -         return op1 < op2   -- lexicographic comparison
    -       else
    -         local h = getbinhandler(op1, op2, "__lt")
    -         if h then
    -           return not not h(op1, op2)
    -         else
    -           error(···)
    -         end
    -       end
    -     end
    -

    -Note that the result is always a boolean. -

  • - -
  • "le": -the <= operation. - - -
    -     function le_event (op1, op2)
    -       if type(op1) == "number" and type(op2) == "number" then
    -         return op1 <= op2   -- numeric comparison
    -       elseif type(op1) == "string" and type(op2) == "string" then
    -         return op1 <= op2   -- lexicographic comparison
    -       else
    -         local h = getbinhandler(op1, op2, "__le")
    -         if h then
    -           return not not h(op1, op2)
    -         else
    -           h = getbinhandler(op1, op2, "__lt")
    -           if h then
    -             return not h(op2, op1)
    -           else
    -             error(···)
    -           end
    -         end
    -       end
    -     end
    -

    -Note that, in the absence of a "le" metamethod, -Lua tries the "lt", assuming that a <= b is -equivalent to not (b < a). - - -

    -As with the other comparison operators, -the result is always a boolean. -

  • - -
  • "index": -The indexing access table[key]. -Note that the metamethod is tried only -when key is not present in table. -(When table is not a table, -no key is ever present, -so the metamethod is always tried.) - - -
    -     function gettable_event (table, key)
    -       local h
    -       if type(table) == "table" then
    -         local v = rawget(table, key)
    -         -- if key is present, return raw value
    -         if v ~= nil then return v end
    -         h = metatable(table).__index
    -         if h == nil then return nil end
    -       else
    -         h = metatable(table).__index
    -         if h == nil then
    -           error(···)
    -         end
    -       end
    -       if type(h) == "function" then
    -         return (h(table, key))     -- call the handler
    -       else return h[key]           -- or repeat operation on it
    -       end
    -     end
    -

    -

  • - -
  • "newindex": -The indexing assignment table[key] = value. -Note that the metamethod is tried only -when key is not present in table. - - -
    -     function settable_event (table, key, value)
    -       local h
    -       if type(table) == "table" then
    -         local v = rawget(table, key)
    -         -- if key is present, do raw assignment
    -         if v ~= nil then rawset(table, key, value); return end
    -         h = metatable(table).__newindex
    -         if h == nil then rawset(table, key, value); return end
    -       else
    -         h = metatable(table).__newindex
    -         if h == nil then
    -           error(···)
    -         end
    -       end
    -       if type(h) == "function" then
    -         h(table, key,value)           -- call the handler
    -       else h[key] = value             -- or repeat operation on it
    -       end
    -     end
    -

    -

  • - -
  • "call": -called when Lua calls a value. - - -
    -     function function_event (func, ...)
    -       if type(func) == "function" then
    -         return func(...)   -- primitive call
    -       else
    -         local h = metatable(func).__call
    -         if h then
    -           return h(func, ...)
    -         else
    -           error(···)
    -         end
    -       end
    -     end
    -

    -

  • - -
- - - - -

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: - -

    - -
  • -All three control expressions are evaluated only once, -before the loop starts. -They must all result in numbers. -
  • - -
  • -var, limit, and step are invisible variables. -The names shown here are for explanatory purposes only. -
  • - -
  • -If the third expression (the step) is absent, -then a step of 1 is used. -
  • - -
  • -You can use break to exit a for loop. -
  • - -
  • -The loop variable v is local to the loop; -you cannot use its value after the for ends or is broken. -If you need this value, -assign it to another variable before breaking or exiting the loop. -
  • - -
- -

-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: - -

    - -
  • -explist is evaluated only once. -Its results are an iterator function, -a state, -and an initial value for the first iterator variable. -
  • - -
  • -f, s, and var are invisible variables. -The names are here for explanatory purposes only. -
  • - -
  • -You can use break to exit a for loop. -
  • - -
  • -The loop variables var_i are local to the loop; -you cannot use their values after the for ends. -If you need these values, -then assign them to other variables before breaking or exiting the loop. -
  • - -
- - - - -

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: - -

    -
  • LUA_RIDX_MAINTHREAD: At this index the registry has -the main thread of the state. -(The main thread is the one created together with the state.) -
  • - -
  • LUA_RIDX_GLOBALS: At this index the registry has -the global environment. -
  • -
- - - - -

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_OPEQ: compares for equality (==)
  • -
  • LUA_OPLT: compares for less than (<)
  • -
  • LUA_OPLE: compares for less or equal (<=)
  • - -
- - - - -

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: - -

    - -
  • LUA_GCSTOP: -stops the garbage collector. -
  • - -
  • LUA_GCRESTART: -restarts the garbage collector. -
  • - -
  • LUA_GCCOLLECT: -performs a full garbage-collection cycle. -
  • - -
  • LUA_GCCOUNT: -returns the current amount of memory (in Kbytes) in use by Lua. -
  • - -
  • LUA_GCCOUNTB: -returns the remainder of dividing the current amount of bytes of -memory in use by Lua by 1024. -
  • - -
  • LUA_GCSTEP: -performs an incremental step of garbage collection. -The step "size" is controlled by data -(larger values mean more steps) in a non-specified way. -If you want to control the step size -you must experimentally tune the value of data. -The function returns 1 if the step finished a -garbage-collection cycle. -
  • - -
  • LUA_GCSETPAUSE: -sets data as the new value -for the pause of the collector (see §2.5). -The function returns the previous value of the pause. -
  • - -
  • LUA_GCSETSTEPMUL: -sets data as the new value for the step multiplier of -the collector (see §2.5). -The function returns the previous value of the step multiplier. -
  • - -
  • LUA_GCISRUNNING: -returns a boolean that tells whether the collector is running -(i.e., not stopped). -
  • - -
  • LUA_GCGEN: -changes the collector to generational mode -(see §2.5). -
  • - -
  • LUA_GCINC: -changes the collector to incremental mode. -This is the default mode. -
  • - -
- -

-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: - -

    - -
  • LUA_OK: no errors;
  • - -
  • LUA_ERRSYNTAX: -syntax error during precompilation;
  • - -
  • LUA_ERRMEM: -memory allocation error;
  • - -
  • LUA_ERRGCMM: -error while running a __gc metamethod. -(This error has no relation with the chunk being loaded. -It is generated by the garbage collector.) -
  • - -
- -

-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_OK (0): -success.
  • - -
  • LUA_ERRRUN: -a runtime error. -
  • - -
  • LUA_ERRMEM: -memory allocation error. -For such errors, Lua does not call the message handler. -
  • - -
  • LUA_ERRERR: -error while running the message handler. -
  • - -
  • LUA_ERRGCMM: -error while running a __gc metamethod. -(This error typically has no relation with the function being called. -It is generated by the garbage collector.) -
  • - -
- - - - -

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: - -

    - -
  • -You do not have to allocate space for the result: -the result is a Lua string and Lua takes care of memory allocation -(and deallocation, through garbage collection). -
  • - -
  • -The conversion specifiers are quite restricted. -There are no flags, widths, or precisions. -The conversion specifiers can only be -'%%' (inserts a '%' in the string), -'%s' (inserts a zero-terminated string, with no size restrictions), -'%f' (inserts a lua_Number), -'%p' (inserts a pointer as a hexadecimal numeral), -'%d' (inserts an int), and -'%c' (inserts an int as a byte). -
  • - -
- - - - -

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: - -

    - -
  • source: -the source of the chunk that created the function. -If source starts with a '@', -it means that the function was defined in a file where -the file name follows the '@'. -If source starts with a '=', -the remainder of its contents describe the source in a user-dependent manner. -Otherwise, -the function was defined in a string where -source is that string. -
  • - -
  • short_src: -a "printable" version of source, to be used in error messages. -
  • - -
  • linedefined: -the line number where the definition of the function starts. -
  • - -
  • lastlinedefined: -the line number where the definition of the function ends. -
  • - -
  • what: -the string "Lua" if the function is a Lua function, -"C" if it is a C function, -"main" if it is the main part of a chunk. -
  • - -
  • currentline: -the current line where the given function is executing. -When no line information is available, -currentline is set to -1. -
  • - -
  • name: -a reasonable name for the given function. -Because functions in Lua are first-class values, -they do not have a fixed name: -some functions can be the value of multiple global variables, -while others can be stored only in a table field. -The lua_getinfo function checks how the function was -called to find a suitable name. -If it cannot find a name, -then name is set to NULL. -
  • - -
  • namewhat: -explains the name field. -The value of namewhat can be -"global", "local", "method", -"field", "upvalue", or "" (the empty string), -according to how the function was called. -(Lua uses the empty string when no other option seems to apply.) -
  • - -
  • istailcall: -true if this function invocation was called by a tail call. -In this case, the caller of this level is not in the stack. -
  • - -
  • nups: -the number of upvalues of the function. -
  • - -
  • nparams: -the number of fixed parameters of the function -(always 0 for C functions). -
  • - -
  • isvararg: -true if the function is a vararg function -(always true for C functions). -
  • - -
- - - - -

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: - -

    - -
  • 'n': fills in the field name and namewhat; -
  • - -
  • 'S': -fills in the fields source, short_src, -linedefined, lastlinedefined, and what; -
  • - -
  • 'l': fills in the field currentline; -
  • - -
  • 't': fills in the field istailcall; -
  • - -
  • 'u': fills in the fields -nups, nparams, and isvararg; -
  • - -
  • 'f': -pushes onto the stack the function that is -running at the given level; -
  • - -
  • 'L': -pushes onto the stack a table whose indices are the -numbers of the lines that are valid on the function. -(A valid line is a line with some associated code, -that is, a line where you can put a break point. -Non-valid lines include empty lines and comments.) -
  • - -
- -

-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: - -

    - -
  • The call hook: is called when the interpreter calls a function. -The hook is called just after Lua enters the new function, -before the function gets its arguments. -
  • - -
  • The return hook: is called when the interpreter returns from a function. -The hook is called just before Lua leaves the function. -There is no standard way to access the values -to be returned by the function. -
  • - -
  • The line hook: is called when the interpreter is about to -start the execution of a new line of code, -or when it jumps back in the code (even to the same line). -(This event only happens while Lua is executing a Lua function.) -
  • - -
  • The count hook: is called after the interpreter executes every -count instructions. -(This event only happens while Lua is executing a Lua function.) -
  • - -
- -

-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: - -

    - -
  • First declare a variable b of type luaL_Buffer.
  • - -
  • Then initialize it with a call luaL_buffinit(L, &b).
  • - -
  • -Then add string pieces to the buffer calling any of -the luaL_add* functions. -
  • - -
  • -Finish by calling luaL_pushresult(&b). -This call leaves the final string on the top of the stack. -
  • - -
- -

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

    - -
  • First declare a variable b of type luaL_Buffer.
  • - -
  • Then initialize it and preallocate a space of -size sz with a call luaL_buffinitsize(L, &b, sz).
  • - -
  • Then copy the string into that space.
  • - -
  • -Finish by calling luaL_pushresultsize(&b, sz), -where sz is the total size of the resulting string -copied into that space. -
  • - -
- -

-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: - -

    - -
  • basic library (§6.1);
  • - -
  • coroutine library (§6.2);
  • - -
  • package library (§6.3);
  • - -
  • string manipulation (§6.4);
  • - -
  • table manipulation (§6.5);
  • - -
  • mathematical functions (§6.6) (sin, log, etc.);
  • - -
  • bitwise operations (§6.7);
  • - -
  • input and output (§6.8);
  • - -
  • operating system facilities (§6.9);
  • - -
  • debug facilities (§6.10).
  • - -

-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: - -

    - -
  • "collect": -performs a full garbage-collection cycle. -This is the default option. -
  • - -
  • "stop": -stops automatic execution of the garbage collector. -The collector will run only when explicitly invoked, -until a call to restart it. -
  • - -
  • "restart": -restarts automatic execution of the garbage collector. -
  • - -
  • "count": -returns the total memory in use by Lua (in Kbytes) and -a second value with the total memory in bytes modulo 1024. -The first value has a fractional part, -so the following equality is always true: - -
    -     k, b = collectgarbage("count")
    -     assert(k*1024 == math.floor(k)*1024 + b)
    -

    -(The second result is useful when Lua is compiled -with a non floating-point type for numbers.) -

  • - -
  • "step": -performs a garbage-collection step. -The step "size" is controlled by arg -(larger values mean more steps) in a non-specified way. -If you want to control the step size -you must experimentally tune the value of arg. -Returns true if the step finished a collection cycle. -
  • - -
  • "setpause": -sets arg as the new value for the pause of -the collector (see §2.5). -Returns the previous value for pause. -
  • - -
  • "setstepmul": -sets arg as the new value for the step multiplier of -the collector (see §2.5). -Returns the previous value for step. -
  • - -
  • "isrunning": -returns a boolean that tells whether the collector is running -(i.e., not stopped). -
  • - -
  • "generational": -changes the collector to generational mode. -This is an experimental feature (see §2.5). -
  • - -
  • "incremental": -changes the collector to incremental mode. -This is the default mode. -
  • - -
- - - -

-


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: - -

    - -
  • The first line is the directory separator string. -Default is '\' for Windows and '/' for all other systems.
  • - -
  • The second line is the character that separates templates in a path. -Default is ';'.
  • - -
  • The third line is the string that marks the -substitution points in a template. -Default is '?'.
  • - -
  • The fourth line is a string that, in a path in Windows, -is replaced by the executable's directory. -Default is '!'.
  • - -
  • The fifth line is a mark to ignore all text before it -when building the luaopen_ function name. -Default is '-'.
  • - -
- - - -

-


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: - -

    - -
  • x: -(where x is not one of the magic characters -^$()%.[]*+-?) -represents the character x itself. -
  • - -
  • .: (a dot) represents all characters.
  • - -
  • %a: represents all letters.
  • - -
  • %c: represents all control characters.
  • - -
  • %d: represents all digits.
  • - -
  • %g: represents all printable characters except space.
  • - -
  • %l: represents all lowercase letters.
  • - -
  • %p: represents all punctuation characters.
  • - -
  • %s: represents all space characters.
  • - -
  • %u: represents all uppercase letters.
  • - -
  • %w: represents all alphanumeric characters.
  • - -
  • %x: represents all hexadecimal digits.
  • - -
  • %x: (where x is any non-alphanumeric character) -represents the character x. -This is the standard way to escape the magic characters. -Any punctuation character (even the non magic) -can be preceded by a '%' -when used to represent itself in a pattern. -
  • - -
  • [set]: -represents the class which is the union of all -characters in set. -A range of characters can be specified by -separating the end characters of the range, -in ascending order, with a '-', -All classes %x described above can also be used as -components in set. -All other characters in set represent themselves. -For example, [%w_] (or [_%w]) -represents all alphanumeric characters plus the underscore, -[0-7] represents the octal digits, -and [0-7%l%-] represents the octal digits plus -the lowercase letters plus the '-' character. - - -

    -The interaction between ranges and classes is not defined. -Therefore, patterns like [%a-z] or [a-%%] -have no meaning. -

  • - -
  • [^set]: -represents the complement of set, -where set is interpreted as above. -
  • - -

-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 - -

    - -
  • -a single character class, -which matches any single character in the class; -
  • - -
  • -a single character class followed by '*', -which matches 0 or more repetitions of characters in the class. -These repetition items will always match the longest possible sequence; -
  • - -
  • -a single character class followed by '+', -which matches 1 or more repetitions of characters in the class. -These repetition items will always match the longest possible sequence; -
  • - -
  • -a single character class followed by '-', -which also matches 0 or more repetitions of characters in the class. -Unlike '*', -these repetition items will always match the shortest possible sequence; -
  • - -
  • -a single character class followed by '?', -which matches 0 or 1 occurrence of a character in the class; -
  • - -
  • -%n, for n between 1 and 9; -such item matches a substring equal to the n-th captured string -(see below); -
  • - -
  • -%bxy, where x and y are two distinct characters; -such item matches strings that start with x, end with y, -and where the x and y are balanced. -This means that, if one reads the string from left to right, -counting +1 for an x and -1 for a y, -the ending y is the first y where the count reaches 0. -For instance, the item %b() matches expressions with -balanced parentheses. -
  • - -
  • -%f[set], a frontier pattern; -such item matches an empty string at any position such that -the next character belongs to set -and the previous character does not belong to set. -The set set is interpreted as previously described. -The beginning and the end of the subject are handled as if -they were the character '\0'. -
  • - -
- - - - -

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: - -

    -
  • "r": read mode (the default);
  • -
  • "w": write mode;
  • -
  • "a": append mode;
  • -
  • "r+": update mode, all previous data is preserved;
  • -
  • "w+": update mode, all previous data is erased;
  • -
  • "a+": append update mode, previous data is preserved, - writing is only allowed at the end of file.
  • -

-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 - -

    - -
  • "*n": -reads a number; -this is the only format that returns a number instead of a string. -
  • - -
  • "*a": -reads the whole file, starting at the current position. -On end of file, it returns the empty string. -
  • - -
  • "*l": -reads the next line skipping the end of line, -returning nil on end of file. -This is the default format. -
  • - -
  • "*L": -reads the next line keeping the end of line (if present), -returning nil on end of file. -
  • - -
  • number: -reads a string with up to this number of bytes, -returning nil on end of file. -If number is zero, -it reads nothing and returns an empty string, -or nil on end of file. -
  • - -
- - - -

-


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: - -

    -
  • "set": base is position 0 (beginning of the file);
  • -
  • "cur": base is current position;
  • -
  • "end": base is end of file;
  • -

-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: - -

    - -
  • "no": -no buffering; the result of any output operation appears immediately. -
  • - -
  • "full": -full buffering; output operation is performed only -when the buffer is full or when -you explicitly flush the file (see io.flush). -
  • - -
  • "line": -line buffering; output is buffered until a newline is output -or there is any input from some special files -(such as a terminal device). -
  • - -

-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: - -

    - -
  • "exit": -the command terminated normally; -the following number is the exit status of the command. -
  • - -
  • "signal": -the command was terminated by a signal; -the following number is the signal that terminated the command. -
  • - -
- -

-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: - -

    -
  • 'c': the hook is called every time Lua calls a function;
  • -
  • 'r': the hook is called every time Lua returns from a function;
  • -
  • 'l': the hook is called every time Lua enters a new line of code.
  • -

-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: - -

    -
  • -e stat: executes string stat;
  • -
  • -l mod: "requires" mod;
  • -
  • -i: enters interactive mode after running script;
  • -
  • -v: prints version information;
  • -
  • -E: ignores environment variables;
  • -
  • --: stops handling options;
  • -
  • -: executes stdin as a file and stops handling options.
  • -

-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

-
    - -
  • -The concept of environment changed. -Only Lua functions have environments. -To set the environment of a Lua function, -use the variable _ENV or the function load. - - -

    -C functions no longer have environments. -Use an upvalue with a shared table if you need to keep -shared state among several C functions. -(You may use luaL_setfuncs to open a C library -with all functions sharing a common upvalue.) - - -

    -To manipulate the "environment" of a userdata -(which is now called user value), -use the new functions -lua_getuservalue and lua_setuservalue. -

  • - -
  • -Lua identifiers cannot use locale-dependent letters. -
  • - -
  • -Doing a step or a full collection in the garbage collector -does not restart the collector if it has been stopped. -
  • - -
  • -Weak tables with weak keys now perform like ephemeron tables. -
  • - -
  • -The event tail return in debug hooks was removed. -Instead, tail calls generate a special new event, -tail call, so that the debugger can know that -there will not be a corresponding return event. -
  • - -
  • -Equality between function values has changed. -Now, a function definition may not create a new value; -it may reuse some previous value if there is no -observable difference to the new function. -
  • - -
- - - - -

8.2 – Changes in the Libraries

-
    - -
  • -Function module is deprecated. -It is easy to set up a module with regular Lua code. -Modules are not expected to set global variables. -
  • - -
  • -Functions setfenv and getfenv were removed, -because of the changes in environments. -
  • - -
  • -Function math.log10 is deprecated. -Use math.log with 10 as its second argument, instead. -
  • - -
  • -Function loadstring is deprecated. -Use load instead; it now accepts string arguments -and are exactly equivalent to loadstring. -
  • - -
  • -Function table.maxn is deprecated. -Write it in Lua if you really need it. -
  • - -
  • -Function os.execute now returns true when command -terminates successfully and nil plus error information -otherwise. -
  • - -
  • -Function unpack was moved into the table library -and therefore must be called as table.unpack. -
  • - -
  • -Character class %z in patterns is deprecated, -as now patterns may contain '\0' as a regular character. -
  • - -
  • -The table package.loaders was renamed package.searchers. -
  • - -
  • -Lua does not have bytecode verification anymore. -So, all functions that load code -(load and loadfile) -are potentially insecure when loading untrusted binary data. -(Actually, those functions were already insecure because -of flaws in the verification algorithm.) -When in doubt, -use the mode argument of those functions -to restrict them to loading textual chunks. -
  • - -
  • -The standard paths in the official distribution may -change between versions. -
  • - -
- - - - -

8.3 – Changes in the API

-
    - -
  • -Pseudoindex LUA_GLOBALSINDEX was removed. -You must get the global environment from the registry -(see §4.5). -
  • - -
  • -Pseudoindex LUA_ENVIRONINDEX -and functions lua_getfenv/lua_setfenv -were removed, -as C functions no longer have environments. -
  • - -
  • -Function luaL_register is deprecated. -Use luaL_setfuncs so that your module does not create globals. -(Modules are not expected to set global variables anymore.) -
  • - -
  • -The osize argument to the allocation function -may not be zero when creating a new block, -that is, when ptr is NULL -(see lua_Alloc). -Use only the test ptr == NULL to check whether -the block is new. -
  • - -
  • -Finalizers (__gc metamethods) for userdata are called in the -reverse order that they were marked for finalization, -not that they were created (see §2.5.1). -(Most userdata are marked immediately after they are created.) -Moreover, -if the metatable does not have a __gc field when set, -the finalizer will not be called, -even if it is set later. -
  • - -
  • -luaL_typerror was removed. -Write your own version if you need it. -
  • - -
  • -Function lua_cpcall is deprecated. -You can simply push the function with lua_pushcfunction -and call it with lua_pcall. -
  • - -
  • -Functions lua_equal and lua_lessthan are deprecated. -Use the new lua_compare with appropriate options instead. -
  • - -
  • -Function lua_objlen was renamed lua_rawlen. -
  • - -
  • -Function lua_load has an extra parameter, mode. -Pass NULL to simulate the old behavior. -
  • - -
  • -Function lua_resume has an extra parameter, from. -Pass NULL or the thread doing the call. -
  • - -
- - - - -

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 07df5f6ee7a7a8b2108025dcd815f73f145a83af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3774 zcmV;v4ngsWP)$kl5 zqcT7g&?zu8?ezWYz4zUB-|zR9d+&Qy2xAN{qY(ew0A7^*gV^7jytKqPFV3{hZfovn zs%x!l>(m&Gdb8C+5XeR7>h0kj=o=X3A39;2KLYfEMt>p1YMW~dt`rpAC{lN~P>5pq zH1L4nAdCT17}*hN=LnEsvMl=5Ij^QArAa&_V~zoht-Ei~)E~(Ivhe0#jik{t$isEK znCH$TxCB8EKmcF>3@pRaHpbR%Gqm*dsZA4H{j(NjZFp^iNFW+RBx6R*X19J*`0XG5 z^Y>cR=^Hi9#ovYGlbFSr#Q*^PgCGC^gb*SC5TcBfzQLe-r2m!Quik&_g9XzTj0qSR zD`FkG_RYWDa^+#UUxL&t+!K+&(ion@Fd`5l5p7{Qsva9vegC|4^NzJUMvn)^gqWsF zvu^j=%FfCVg^cgbXDRl1DE$lsfe;BjjmFmRHER~E-MeWoNsyyNHCpG%Y}igd_(Md;&9La8_B075NDRX9gTD zIHY`}9E~aGi9Kk1@P~rmPna=*=gz~UTdTpsQmjX)J23%v9NliQS)8`xJh6Qz_nE~e z&tP|!dcJdo;JMNa3>afSx$lko8>fp-I}OiCVz(dOF1u6e8$IrsSP?=5mp~lkaFqm? zAUMxRq%ecIu3WE)Uf=%p8g z+RSY?G=VO%wAfdICj?Uzb+5jr{8m|)i#{M}JjaDIoXf#1=DYLwX;1EW&sijPvm6EkBGuOx6r~lKv`g`yH?)|&PRUr$5Ibw2HBM7C74XvE@gaPjN+@;j$J)AgYhnT-U5m+wj|Wz8K630AfO8PUoGD^^Mcq zY9C<~%wUm^u%ox5P21)KNN0$(v^OI$A~?iwsS_fRu1+`EH|CRdpA4zsk8Z#|?x@^vVEAL+2JxH%&^{JUU%B=?EU7`Ar*Q|JvqPofcBt765(*f5JI$>=3{<%K)4ei zogo$)5XP}_X$y^pIYyWTt}EAnhTq}u4sAdBvC(WC{I#x4^>$vCvQ0UDs^18sAQG9o zEaP0qjrSSv1W0FyO%9&y$@em~n@8}}EXBG6x%ew49J_q%l@As_XnNpi|MTTPr~ca_ zW%uon6dBKL*pvzYFvf<~p6K8hK9BDNNN0$7xp^hWC3n^7FoQ?P(=m(6!Pj&S2f1fqH=`(w)KcPl5aEi2}~4hF*f*g}vaS-=c7v>N8c z{yNM*%+azq=@prWtgpi~^3?^AsJqS(>=pb=6PrGH#=O{Hcho$_F#MtsK$$3e2fZvg zy}!-V%`+uFMOW87LIgu3vKuMgqwY0}*Sd;aokQp(F#-{}Ss(Iy1iekY1ZQX?1WEL? z7=zq`lH-#Hw=bHRio3yPun%`c5rI1Hb|wTSWTs|12Mg#QkkwTmy zAYul0H*_b(BnkP#!R_&p@d54uz0JKthGv3C^fdKS%~alookE`QX@%#MQN2=SFWrOha7Ij7ImStNaWsy~? zsylUeT02_-z-G4s0L!v=+Wx|cxr$tmY&$a1by8z#6HBp!*9{@mU9XQ0h@L%V_R}4g z&s#2{MCOj4`5ux-SUautC5@{U895o-biKMWWoQ09{|jx8wz}@_(ep%Yk4{90C#s6-sa}fU5{}m>#>VtE_b#5bn8O+3k{&6GoEkB;yGie;A_5Uy zqPN*tU()pE+_&~``5XX({el-xT_}%`%fsc>_0@m5{+FhXru>rpyLESe31R>cK^FFrCm+#WL$-D{Z3*9>Lg{wi}xEYn_`@Hy`-d z1N}kIY%@Eu&Bpe|Rr6N;%Yk>6&RI$lgpIO26BYT%C!dU-o4bqqQpGY?p6lPru6Hzc z@WuSDI^BYaDH*>R)~)$V1J0Edn4r(9vo>E<2XjOJr2*G124;t^U+p{iUnZN5oapCpCk(F}}<#3ZZli!Nk z^UWT;Q9qm-i`i$kJS}5P%puBJ<&krTO;*#$Y7d$o96EbQ{aF1XFpTj}wf}eI|IOba z%w}_CWu?JjkV>U-ad9L$@Mu$CU;pUQBZgt5QmI@n=W@9K(A(SF-rnxzy|_!5ekKqCQTad`sa|&&Q6jfy}iAEst?|mH*emIjg9SB zRVWlHl?r3bvh2qnf6V6(+>4TulB%kzFveeh{k1?K*t&J=m>dk9P8SjqQdn4sF;*&- z(b3VFnVH$y*$Rb%rs zefJ#z#KpyZ_0?C$jvY%)O?7a?7#}%u1OT>d*)keF*REZ=c=4j6tkr5MilS*cB_$;< zFArmEv)Oby-7}4>TD9uE_ulKT4s6Bp@^Y0*rBEo&o;?cy8#Zi^%jH+DTv4f1SFc_L zfc5LwXJ=;vKt@K!?%liR&!6Almmq$2R@G|tg$oyGnpP+jQBhF<(9qCOR8%AuiBtJCSc zyu1LQw6wIQre^Zw$^E0N)#}R1%J}$rkw`Qc#z0A{)dIkjDN`I(PfyS2=x9f~R4N64 zPe1*1=gytQ#l=RWao4V0bLY-=?Bpl*dQDA@LZMJ9l{Gar$;rvzfB$`Tb#+==T0=ua zSy@?1N{UXWyL9Q&#*G`Zv$GE#JXljxBauj2T3VD!rO9N<%F3#*uP-Sn(P%W=w{Jgx z{(NC!VNOmC0OaN6ZQHg@tJQw^;fGtdZUulVSFX&NGv~~iGoO9-nNq0~2n78w23E{L zmth7T3|W>10ISuSm6cUgRCMXmr5!tV0D!x@`?6)rcI?<8lgZ#IIehqVOiYYpi@x#3 z8xau^+1c4ER;th&( zVHk--A`l3|!os9dsYatANm8TH96x@%qM{-&FmUtc&2qVX-MV%A_U(J~%{TY#*<&ym zX3Ur|c$No?u%e>k#EBDaZEY7XUVLH`0zh|n zw_~XRz;RH!y1MS)zn_X$Km70mNs@ZKo~G$z$BuD09F}FpVzEY}F&d2ug#rLPJUpgPpKh}a^y$-i zJl@%}XHT6vRaaNHckf=MQYn>6Fk&*D<+ja0B z5C{a#&CQN-V`HPyXe3EeAP~gH#>U3RayT5ZSd1}tbaaSNDAZ^)j%n&QHMoE=7KubA zlWEeVNpiV7Dk=&gzM|0Dz(>0HA5Q-_F}_znz(xxqbU~E|+`a#EH|V zPjA|^DJLg~rs?+f_6rv-T)upnAP7fChoq;cFJHcV=gyt)zWXjs(+gZ<%kMDTlOd1+TFW%&z(D`)oKF*0@Bmd zLqkIy?RvewprGK+ojWv5%Ve?@D^>&r1p$CcrMhuv}x1&joiO~|IC>)G) - - -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: -

    -
  • Where and how to install Lua — edit Makefile. -
  • How to build Lua — edit src/Makefile. -
  • Lua features — edit src/luaconf.h. -
- -

- 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

-
    -
  • yieldable pcall and metamethods -
  • new lexical scheme for globals -
  • ephemeron tables -
  • new library for bitwise operations -
  • light C functions -
  • emergency garbage collector -
  • goto statement -
  • finalizers for tables -
- -Here are the other changes introduced in Lua 5.2: -

Language

-
    -
  • no more fenv for threads or functions -
  • tables honor the __len metamethod -
  • hex and \z escapes in strings -
  • support for hexadecimal floats -
  • order metamethods work for different types -
  • no more verification of opcode consistency -
  • hook event "tail return" replaced by "tail call" -
  • empty statement -
  • break statement may appear in the middle of a block -
- -

Libraries

-
    -
  • arguments for function called through xpcall -
  • optional 'mode' argument to load and loadfile (to control binary x text) -
  • optional 'env' argument to load and loadfile (environment for loaded chunk) -
  • loadlib may load libraries with global names (RTLD_GLOBAL) -
  • new function package.searchpath -
  • modules receive their paths when loaded -
  • optional base in math.log -
  • optional separator in string.rep -
  • file:write returns file -
  • closing a pipe returns exit status -
  • os.exit may close state -
  • new metamethods __pairs and __ipairs -
  • new option 'isrunning' for collectgarbage and lua_gc -
  • frontier patterns -
  • \0 in patterns -
  • new option *L for io.read -
  • options for io.lines -
  • debug.getlocal can access function varargs -
- -

C API

-
    -
  • main thread predefined in the registry -
  • new functions -lua_absindex, -lua_arith, -lua_compare, -lua_copy, -lua_len, -lua_rawgetp, -lua_rawsetp, -lua_upvalueid, -lua_upvaluejoin, -lua_version. -
  • new functions -luaL_checkversion, -luaL_setmetatable, -luaL_testudata, -luaL_tolstring. -
  • lua_pushstring and pushlstring return string -
  • nparams and isvararg available in debug API -
  • new lua_Unsigned -
- -

Implementation

-
    -
  • max constants per function raised to 226 -
  • generational mode for garbage collection (experimental) -
  • NaN trick (experimental) -
  • internal (immutable) version of ctypes -
  • simpler implementation for string buffers -
  • parser uses much less C-stack space (no more auto arrays) -
- -

Lua standalone interpreter

-
    -
  • new -E option to avoid environment variables -
  • handling of non-string error messages -
- -

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