106 lines
2.6 KiB
C++
106 lines
2.6 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
|
||
|
*/
|
||
|
#ifdef LEAN_USE_LUA
|
||
|
#include <sstream>
|
||
|
#include <lua.hpp>
|
||
|
#include "util/debug.h"
|
||
|
#include "util/sexpr/sexpr.h"
|
||
|
#include "bindings/lua/util.h"
|
||
|
#include "bindings/lua/name.h"
|
||
|
#include "bindings/lua/numerics.h"
|
||
|
|
||
|
namespace lean {
|
||
|
constexpr char const * sexpr_mt = "sexpr.mt";
|
||
|
|
||
|
static int push_sexpr(lua_State * L, sexpr const & e) {
|
||
|
void * mem = lua_newuserdata(L, sizeof(sexpr));
|
||
|
new (mem) sexpr(e);
|
||
|
luaL_getmetatable(L, sexpr_mt);
|
||
|
lua_setmetatable(L, -2);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
bool is_sexpr(lua_State * L, int idx) {
|
||
|
return testudata(L, idx, sexpr_mt);
|
||
|
}
|
||
|
|
||
|
static sexpr to_sexpr(lua_State * L, int idx) {
|
||
|
if (lua_isnil(L, idx)) {
|
||
|
return sexpr();
|
||
|
} else if (lua_isboolean(L, idx)) {
|
||
|
return sexpr(lua_toboolean(L, idx));
|
||
|
} else if (lua_isnumber(L, idx)) {
|
||
|
// Remark: we convert to integer by default
|
||
|
return sexpr(static_cast<int>(lua_tointeger(L, idx)));
|
||
|
} else if (is_name(L, idx)) {
|
||
|
return sexpr(to_name(L, idx));
|
||
|
} else if (is_sexpr(L, idx)) {
|
||
|
return *static_cast<sexpr*>(lua_touserdata(L, idx));
|
||
|
} else if (is_mpz(L, idx)) {
|
||
|
return sexpr(to_mpz(L, idx));
|
||
|
} else if (is_mpq(L, idx)) {
|
||
|
return sexpr(to_mpq(L, idx));
|
||
|
} else {
|
||
|
return sexpr(lua_tostring(L, idx));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int sexpr_gc(lua_State * L) {
|
||
|
to_sexpr(L, 1).~sexpr();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int sexpr_tostring(lua_State * L) {
|
||
|
std::ostringstream out;
|
||
|
out << to_sexpr(L, 1);
|
||
|
lua_pushfstring(L, out.str().c_str());
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int mk_sexpr(lua_State * L) {
|
||
|
sexpr r;
|
||
|
int nargs = lua_gettop(L);
|
||
|
if (nargs == 0) {
|
||
|
r = sexpr();
|
||
|
} else {
|
||
|
int i = nargs;
|
||
|
r = to_sexpr(L, i);
|
||
|
i--;
|
||
|
for (; i >= 1; i--) {
|
||
|
r = sexpr(to_sexpr(L, i), r);
|
||
|
}
|
||
|
}
|
||
|
return push_sexpr(L, r);
|
||
|
}
|
||
|
|
||
|
static int sexpr_eq(lua_State * L) {
|
||
|
lua_pushboolean(L, to_sexpr(L, 1) == to_sexpr(L, 2));
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static int sexpr_lt(lua_State * L) {
|
||
|
lua_pushboolean(L, to_sexpr(L, 1) < to_sexpr(L, 2));
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
static const struct luaL_Reg sexpr_m[] = {
|
||
|
{"__gc", sexpr_gc}, // never throws
|
||
|
{"__tostring", safe_function<sexpr_tostring>},
|
||
|
{"__eq", safe_function<sexpr_eq>},
|
||
|
{"__lt", safe_function<sexpr_lt>},
|
||
|
{0, 0}
|
||
|
};
|
||
|
|
||
|
void open_sexpr(lua_State * L) {
|
||
|
luaL_newmetatable(L, sexpr_mt);
|
||
|
setfuncs(L, sexpr_m, 0);
|
||
|
lua_pushcfunction(L, safe_function<mk_sexpr>);
|
||
|
lua_setglobal(L, "sexpr");
|
||
|
}
|
||
|
}
|
||
|
#endif
|