lean2/src/util/lua.h
Leonardo de Moura 956f203a55 refactor(bindings/lua): move Lua bindings to the file associated with them
The directory bindings/lua was getting too big and had too many dependencies.
Moreover, it was getting too painful to edit/maintain two different places.
Now, the bindings for module X are in the directory that defines X.
For example, the bindings for util/name.cpp are located at util/name.cpp.

The only exception is the kernel. We do not want to inflate the kernel
with Lua bindings. The bindings for the kernel classes are located
at bindings/kernel_bindings.

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
2013-11-26 19:15:56 -08:00

131 lines
4.8 KiB
C++

/*
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
*/
#pragma once
#include <lua.hpp>
namespace lean {
// =======================================
// Lua 5.1 and 5.2 compatibility
//
// The following helper functions make sure
// we can compile using Lua 5.1 or 5.2
void setfuncs(lua_State * L, luaL_Reg const * l, int nup);
bool testudata(lua_State * L, int idx, char const * mt);
int load(lua_State * L, lua_Reader reader, void * data, char const * source);
size_t objlen(lua_State * L, int idx);
void dofile(lua_State * L, char const * fname);
void dostring(lua_State * L, char const * str);
void pcall(lua_State * L, int nargs, int nresults, int errorfun);
int lessthan(lua_State * L, int idx1, int idx2);
int equal(lua_State * L, int idx1, int idx2);
int get_nonnil_top(lua_State * L);
// =======================================
// =======================================
// Goodies/Macros for automating Lua binding
// generation.
/**
\brief Helper class for registering a new
set of Lua bindings.
*/
class lua_module {
public:
typedef void (*init_fn)(lua_State * L);
lua_module(init_fn f);
static void init(lua_State * L);
};
/**
\brief Wrapper for invoking function f, and catching Lean exceptions.
*/
extern int (*g_safe_function_wrapper)(lua_State * L, lua_CFunction f);
template<lua_CFunction F> int safe_function(lua_State * L) {
return g_safe_function_wrapper(L, F);
}
template<lua_CFunction F> void set_global_function(lua_State * L, char const * name) {
lua_pushcfunction(L, safe_function<F>);
lua_setglobal(L, name);
}
/**
\brief Helper object for setting g_safe_function_wrapper.
*/
struct set_safe_function_wrapper { set_safe_function_wrapper(int (*f)(lua_State *, lua_CFunction)); };
/**
\brief Helper object for setting a different check_result function.
*/
struct set_check_result { set_check_result(void (*f)(lua_State *, int)); };
#define SET_GLOBAL_FUN(F, N) set_global_function<F>(L, N)
// Auxiliary macro for creating a Lua table that stores enumeration values
#define SET_ENUM(N, V) lua_pushstring(L, N); lua_pushinteger(L, static_cast<int>(V)); lua_settable(L, -3)
#define DECL_PUSH_CORE(NAME, T, TREF) \
int push_ ## NAME(lua_State * L, TREF val) { \
void * mem = lua_newuserdata(L, sizeof(T)); \
new (mem) T(val); \
luaL_getmetatable(L, NAME ## _mt); \
lua_setmetatable(L, -2); \
return 1; \
}
#define DECL_PUSH(T) \
DECL_PUSH_CORE(T, T, T const &) \
DECL_PUSH_CORE(T, T, T &&)
#define DECL_GC(T) static int T ## _gc(lua_State * L) { static_cast<T*>(lua_touserdata(L, 1))->~T(); return 0; }
#define DECL_PRED(T) \
bool is_ ## T(lua_State * L, int idx) { return testudata(L, idx, T ## _mt); } \
static int T ## _pred(lua_State * L) { \
lua_pushboolean(L, is_ ## T(L, 1)); \
return 1; \
}
/**
\brief Create basic declarations for adding a new kind of userdata in Lua
T is a Lean object type.
For example, if T == expr, it produces an implementation for the
following declarations
constexpr char const * expr_mt = "expr";
expr & to_expr(lua_State * L, int i);
bool is_expr(lua_State * L, int i);
static int expr_pred(lua_State * L);
static int expr_gc(lua_State * L);
int push_expr(lua_State * L, expr const & e);
int push_expr(lua_State * L, expr && e);
*/
#define DECL_UDATA(T) \
constexpr char const * T ## _mt = #T; \
T & to_ ## T(lua_State * L, int i) { return *static_cast<T*>(luaL_checkudata(L, i, T ## _mt)); } \
DECL_PRED(T) \
DECL_GC(T) \
DECL_PUSH(T)
/**
\brief Similar to DECL_UDATA, but it only declares the functions.
For example, if T == expr, it produces the following declarations:
class expr;
expr & to_expr(lua_State * L, int i);
bool is_expr(lua_State * L, int i);
int push_expr(lua_State * L, expr const & e);
int push_expr(lua_State * L, expr && e);
*/
#define UDATA_DEFS_CORE(T) \
T & to_ ## T(lua_State * L, int i); \
bool is_ ## T(lua_State * L, int i); \
int push_ ## T(lua_State * L, T const & e); \
int push_ ## T(lua_State * L, T && e);
#define UDATA_DEFS(T) \
class T; \
UDATA_DEFS_CORE(T)
// =======================================
}