feat(lua): expose formatter in the Lua API

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2013-11-12 11:19:15 -08:00
parent 2af2a69fc6
commit c46edcf370
3 changed files with 115 additions and 1 deletions

View file

@ -1,5 +1,5 @@
add_library(lua util.cpp lua_exception.cpp name.cpp numerics.cpp
options.cpp sexpr.cpp format.cpp level.cpp local_context.cpp expr.cpp
context.cpp object.cpp environment.cpp leanlua_state.cpp)
context.cpp object.cpp environment.cpp formatter.cpp leanlua_state.cpp)
target_link_libraries(lua ${LEAN_LIBS})

View file

@ -0,0 +1,99 @@
/*
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
*/
#include <sstream>
#include <lua.hpp>
#include "kernel/formatter.h"
#include "bindings/lua/util.h"
#include "bindings/lua/options.h"
#include "bindings/lua/format.h"
#include "bindings/lua/expr.h"
#include "bindings/lua/context.h"
#include "bindings/lua/environment.h"
#include "bindings/lua/object.h"
namespace lean {
constexpr char const * formatter_mt = "formatter.mt";
bool is_formatter(lua_State * L, int idx) {
return testudata(L, idx, formatter_mt);
}
formatter & to_formatter(lua_State * L, int idx) {
return *static_cast<formatter*>(luaL_checkudata(L, idx, formatter_mt));
}
int push_formatter(lua_State * L, formatter const & o) {
void * mem = lua_newuserdata(L, sizeof(formatter));
new (mem) formatter(o);
luaL_getmetatable(L, formatter_mt);
lua_setmetatable(L, -2);
return 1;
}
static int formatter_gc(lua_State * L) {
to_formatter(L, 1).~formatter();
return 0;
}
[[ noreturn ]] void throw_invalid_formatter_call() {
throw exception("invalid formatter invocation, the acceptable arguments are: (expr, options?), (context, options?), (context, expr, bool? options?), (kernel object, options?), (environment, options?)");
}
static int formatter_call(lua_State * L) {
int nargs = lua_gettop(L);
formatter & fmt = to_formatter(L, 1);
options opts;
if (nargs <= 3) {
if (nargs == 3) {
if (is_options(L, 3))
opts = to_options(L, 3);
else if (is_context(L, 2) && is_expr(L, 3))
return push_format(L, fmt(to_context(L, 2), to_expr(L, 3)));
else
throw_invalid_formatter_call();
}
if (is_expr(L, 2)) {
return push_format(L, fmt(to_expr(L, 2), opts));
} else if (is_context(L, 2)) {
return push_format(L, fmt(to_context(L, 2), opts));
} else if (is_environment(L, 2)) {
ro_environment env(L, 2);
return push_format(L, fmt(env, opts));
} else if (is_object(L, 2)) {
return push_format(L, fmt(to_object(L, 2), opts));
} else {
throw_invalid_formatter_call();
}
} else if (nargs <= 5) {
if (nargs == 5)
opts = to_options(L, 5);
return push_format(L, fmt(to_context(L, 2), to_expr(L, 3), lua_toboolean(L, 4), opts));
} else {
throw_invalid_formatter_call();
}
}
static int formatter_pred(lua_State * L) {
lua_pushboolean(L, is_formatter(L, 1));
return 1;
}
static const struct luaL_Reg formatter_m[] = {
{"__gc", formatter_gc}, // never throws
{"__call", safe_function<formatter_call>},
{0, 0}
};
void open_formatter(lua_State * L) {
luaL_newmetatable(L, formatter_mt);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
setfuncs(L, formatter_m, 0);
set_global_function<formatter_pred>(L, "is_formatter");
}
}

View file

@ -0,0 +1,15 @@
/*
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 {
class formatter;
void open_formatter(lua_State * L);
bool is_formatter(lua_State * L, int idx);
formatter & to_formatter(lua_State * L, int idx);
int push_formatter(lua_State * L, formatter const & o);
}