2013-11-03 20:16:23 +00:00
|
|
|
/*
|
|
|
|
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
|
|
|
|
Author: Leonardo de Moura
|
|
|
|
*/
|
2013-11-08 19:59:47 +00:00
|
|
|
#pragma once
|
2013-11-03 20:16:23 +00:00
|
|
|
#include <lua.hpp>
|
2013-11-08 19:59:47 +00:00
|
|
|
|
2013-11-03 20:16:23 +00:00
|
|
|
namespace lean {
|
2013-11-27 03:15:49 +00:00
|
|
|
// =======================================
|
|
|
|
// Lua 5.1 and 5.2 compatibility
|
|
|
|
//
|
|
|
|
// The following helper functions make sure
|
|
|
|
// we can compile using Lua 5.1 or 5.2
|
2013-11-03 20:16:23 +00:00
|
|
|
void setfuncs(lua_State * L, luaL_Reg const * l, int nup);
|
2013-11-05 19:35:09 +00:00
|
|
|
bool testudata(lua_State * L, int idx, char const * mt);
|
2013-11-12 20:54:34 +00:00
|
|
|
int load(lua_State * L, lua_Reader reader, void * data, char const * source);
|
2013-11-08 16:26:04 +00:00
|
|
|
size_t objlen(lua_State * L, int idx);
|
2013-11-08 19:59:47 +00:00
|
|
|
void dofile(lua_State * L, char const * fname);
|
|
|
|
void dostring(lua_State * L, char const * str);
|
2013-11-14 00:30:59 +00:00
|
|
|
void pcall(lua_State * L, int nargs, int nresults, int errorfun);
|
2013-11-28 21:09:30 +00:00
|
|
|
/**
|
|
|
|
\brief Return true iff coroutine is done, false if it has yielded,
|
|
|
|
and throws an exception if error.
|
|
|
|
*/
|
|
|
|
bool resume(lua_State * L, int nargs);
|
2013-11-14 21:32:33 +00:00
|
|
|
int lessthan(lua_State * L, int idx1, int idx2);
|
|
|
|
int equal(lua_State * L, int idx1, int idx2);
|
2013-11-19 23:56:44 +00:00
|
|
|
int get_nonnil_top(lua_State * L);
|
2013-11-27 03:15:49 +00:00
|
|
|
// =======================================
|
|
|
|
|
|
|
|
// =======================================
|
|
|
|
// Goodies/Macros for automating Lua binding
|
|
|
|
// generation.
|
2013-11-03 22:42:54 +00:00
|
|
|
/**
|
|
|
|
\brief Wrapper for invoking function f, and catching Lean exceptions.
|
|
|
|
*/
|
2013-11-27 20:19:54 +00:00
|
|
|
int safe_function_wrapper(lua_State * L, lua_CFunction f);
|
2013-11-04 23:05:04 +00:00
|
|
|
template<lua_CFunction F> int safe_function(lua_State * L) {
|
2013-11-27 20:19:54 +00:00
|
|
|
return safe_function_wrapper(L, F);
|
2013-11-03 22:42:54 +00:00
|
|
|
}
|
2013-11-08 04:48:49 +00:00
|
|
|
template<lua_CFunction F> void set_global_function(lua_State * L, char const * name) {
|
|
|
|
lua_pushcfunction(L, safe_function<F>);
|
|
|
|
lua_setglobal(L, name);
|
|
|
|
}
|
2013-11-13 19:46:09 +00:00
|
|
|
#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)
|
2013-11-15 01:19:51 +00:00
|
|
|
|
2013-11-27 03:15:49 +00:00
|
|
|
#define DECL_PUSH_CORE(NAME, T, TREF) \
|
2013-11-15 01:19:51 +00:00
|
|
|
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)
|
2013-11-27 03:15:49 +00:00
|
|
|
// =======================================
|
2013-11-27 18:32:15 +00:00
|
|
|
|
|
|
|
// =======================================
|
|
|
|
// Goodies for installing code for migrating objects
|
|
|
|
// between different lua_State objects
|
|
|
|
typedef void (*lua_migrate_fn)(lua_State * src, int i, lua_State * tgt);
|
|
|
|
/**
|
|
|
|
\brief Set the field ___migrate in the metatable at position \c i with \c fn.
|
|
|
|
*/
|
|
|
|
void set_migrate_fn_field(lua_State * src, int i, lua_migrate_fn fn);
|
|
|
|
/**
|
|
|
|
\brief Return the value of the ___migrate field from metatable
|
|
|
|
for the userdata at position \c i.
|
|
|
|
*/
|
|
|
|
lua_migrate_fn get_migrate_fn(lua_State * src, int i);
|
2013-11-03 20:16:23 +00:00
|
|
|
}
|