Skip to content

Commit

Permalink
Initial implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
vieiraa committed Feb 19, 2020
1 parent 72d6f2a commit 2de4001
Show file tree
Hide file tree
Showing 2 changed files with 206 additions and 0 deletions.
114 changes: 114 additions & 0 deletions components/script/luascript.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#include "luascript.h"

#include <vector>

namespace Script
{
LuaScript::LuaScript() : mState(luaL_newstate()) { luaL_openlibs(mState); }

LuaScript::~LuaScript()
{
if (mState)
lua_close(mState);
}

void LuaScript::printError(const std::string& variable, const std::string& reason)
{
#ifndef NDEBUG
std::cerr << "Can't get variable " << variable << ".\nReason: " << reason << "\n";
#endif
}

template <> std::string LuaScript::luaGetDefault() { return "null"; }

template <> bool LuaScript::luaGet(const std::string& variable) { return static_cast<bool>(lua_toboolean(mState, -1)); }

template <> std::string LuaScript::luaGet(const std::string& variable)
{
std::string ret = "null";

release_assert(lua_isstring(mState, -1));

if (lua_isstring(mState, -1))
ret = std::string(lua_tostring(mState, -1));
else
printError(variable, "Not a string");

return ret;
}

bool LuaScript::luaGetToStack(const std::string& variable)
{
mLevel = 0;
std::string var{};

for (char c : variable)
{
if (c == '.')
{
if (mLevel == 0)
{
lua_getglobal(mState, var.c_str());
}

else
{
lua_getfield(mState, -1, var.c_str());
}

if (lua_isnil(mState, -1))
{
printError(variable, var + " is not defined");
return false;
}

else
{
var = "";
++mLevel;
}
}

else
{
var += c;
}
}

if (mLevel == 0)
{
lua_getglobal(mState, var.c_str());
}

else
{
lua_getfield(mState, -1, var.c_str());
}

if (lua_isnil(mState, -1))
{
printError(variable, var + " is not defined");
return false;
}

return true;
}

void LuaScript::clean()
{
int n = lua_gettop(mState);
lua_pop(mState, n);
}

void LuaScript::runScript(const std::string& path)
{
lua_settop(mState, 0);

if (luaL_dofile(mState, path.c_str()))
{
std::cerr << "Lua error: " << lua_tostring(mState, -1) << "\n";
lua_pop(mState, 1);
exit(1);
}
}
}
92 changes: 92 additions & 0 deletions components/script/luascript.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#pragma once

#include <misc/assert.h>

#include <iostream>
#include <string>
#include <vector>

#include <lua.hpp>

namespace Script
{
class LuaScript
{
lua_State* mState;
int mLevel;

public:
LuaScript();
~LuaScript();

void printError(const std::string& variable, const std::string& reason);

template <typename T> void registerType(const std::string& metatable_name);

template <typename T> T get(const std::string& variable)
{
release_assert(mState);

T result;
if (luaGetToStack(variable))
{
result = luaGet<T>(variable);
}

else
{
result = luaGetDefault<T>();
}

lua_pop(mState, mLevel + 1);
return result;
}

template <typename T> std::vector<T> getVector(const std::string& variable)
{
std::vector<T> ret;
lua_getglobal(mState, variable.c_str());
if (lua_isnil(mState, -1))
{
return {};
}

lua_pushnil(mState);

while (lua_next(mState, -2))
{
T aux;
if constexpr (std::is_same<T, std::string>::value)
{
ret.push_back(lua_tostring(mState, -1));
}

else
{
ret.push_back(static_cast<T>(lua_tonumber(mState, -1)));
}

lua_pop(mState, 1);
}

clean();
return ret;
}

void runScript(const std::string& path);

private:
bool luaGetToStack(const std::string& variable);

void clean();

template <typename T> T luaGet(const std::string& variable = "")
{
release_assert(lua_isnumber(mState, -1) && "Not a number");

return static_cast<T>(lua_tonumber(mState, -1));
};

template <typename T> T luaGetDefault() { return {}; }
};
}

0 comments on commit 2de4001

Please sign in to comment.