feat(lua): expose kernel objects in the Lua API
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
d257156b88
commit
2af2a69fc6
6 changed files with 274 additions and 1 deletions
|
@ -1,5 +1,5 @@
|
||||||
add_library(lua util.cpp lua_exception.cpp name.cpp numerics.cpp
|
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
|
options.cpp sexpr.cpp format.cpp level.cpp local_context.cpp expr.cpp
|
||||||
context.cpp environment.cpp leanlua_state.cpp)
|
context.cpp object.cpp environment.cpp leanlua_state.cpp)
|
||||||
|
|
||||||
target_link_libraries(lua ${LEAN_LIBS})
|
target_link_libraries(lua ${LEAN_LIBS})
|
||||||
|
|
|
@ -12,6 +12,7 @@ Author: Leonardo de Moura
|
||||||
#include "bindings/lua/name.h"
|
#include "bindings/lua/name.h"
|
||||||
#include "bindings/lua/level.h"
|
#include "bindings/lua/level.h"
|
||||||
#include "bindings/lua/expr.h"
|
#include "bindings/lua/expr.h"
|
||||||
|
#include "bindings/lua/object.h"
|
||||||
#include "bindings/lua/context.h"
|
#include "bindings/lua/context.h"
|
||||||
#include "bindings/lua/environment.h"
|
#include "bindings/lua/environment.h"
|
||||||
|
|
||||||
|
@ -51,6 +52,25 @@ static int mk_environment(lua_State * L) {
|
||||||
return push_environment(L, environment());
|
return push_environment(L, environment());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int environment_has_parent(lua_State * L) {
|
||||||
|
ro_environment env(L, 1);
|
||||||
|
lua_pushboolean(L, env->has_parent());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int environment_has_children(lua_State * L) {
|
||||||
|
ro_environment env(L, 1);
|
||||||
|
lua_pushboolean(L, env->has_children());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int environment_parent(lua_State * L) {
|
||||||
|
ro_environment env(L, 1);
|
||||||
|
if (!env->has_parent())
|
||||||
|
throw exception("environment does not have a parent environment");
|
||||||
|
return push_environment(L, env->parent());
|
||||||
|
}
|
||||||
|
|
||||||
static int environment_add_uvar(lua_State * L) {
|
static int environment_add_uvar(lua_State * L) {
|
||||||
rw_environment env(L, 1);
|
rw_environment env(L, 1);
|
||||||
int nargs = lua_gettop(L);
|
int nargs = lua_gettop(L);
|
||||||
|
@ -106,6 +126,17 @@ static int environment_add_axiom(lua_State * L) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int environment_find_object(lua_State * L) {
|
||||||
|
ro_environment env(L, 1);
|
||||||
|
return push_object(L, env->find_object(to_name_ext(L, 2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int environment_has_object(lua_State * L) {
|
||||||
|
ro_environment env(L, 1);
|
||||||
|
lua_pushboolean(L, env->has_object(to_name_ext(L, 2)));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int environment_check_type(lua_State * L) {
|
static int environment_check_type(lua_State * L) {
|
||||||
ro_environment env(L, 1);
|
ro_environment env(L, 1);
|
||||||
int nargs = lua_gettop(L);
|
int nargs = lua_gettop(L);
|
||||||
|
@ -124,6 +155,30 @@ static int environment_normalize(lua_State * L) {
|
||||||
return push_expr(L, env->normalize(to_nonnull_expr(L, 2), to_context(L, 3)));
|
return push_expr(L, env->normalize(to_nonnull_expr(L, 2), to_context(L, 3)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int environment_objects(lua_State * L) {
|
||||||
|
ro_environment env(L, 1);
|
||||||
|
auto it = env->begin_objects();
|
||||||
|
auto end = env->end_objects();
|
||||||
|
lua_newtable(L);
|
||||||
|
for (int i = 1; it != end; ++it, ++i) {
|
||||||
|
push_object(L, *it);
|
||||||
|
lua_rawseti(L, -2, i);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int environment_local_objects(lua_State * L) {
|
||||||
|
ro_environment env(L, 1);
|
||||||
|
auto it = env->begin_local_objects();
|
||||||
|
auto end = env->end_local_objects();
|
||||||
|
lua_newtable(L);
|
||||||
|
for (int i = 1; it != end; ++it, ++i) {
|
||||||
|
push_object(L, *it);
|
||||||
|
lua_rawseti(L, -2, i);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int environment_pred(lua_State * L) {
|
static int environment_pred(lua_State * L) {
|
||||||
lua_pushboolean(L, is_environment(L, 1));
|
lua_pushboolean(L, is_environment(L, 1));
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -142,6 +197,9 @@ static int environment_tostring(lua_State * L) {
|
||||||
static const struct luaL_Reg environment_m[] = {
|
static const struct luaL_Reg environment_m[] = {
|
||||||
{"__gc", environment_gc}, // never throws
|
{"__gc", environment_gc}, // never throws
|
||||||
{"__tostring", safe_function<environment_tostring>},
|
{"__tostring", safe_function<environment_tostring>},
|
||||||
|
{"has_parent", safe_function<environment_has_parent>},
|
||||||
|
{"has_children", safe_function<environment_has_children>},
|
||||||
|
{"parent", safe_function<environment_parent>},
|
||||||
{"add_uvar", safe_function<environment_add_uvar>},
|
{"add_uvar", safe_function<environment_add_uvar>},
|
||||||
{"is_ge", safe_function<environment_is_ge>},
|
{"is_ge", safe_function<environment_is_ge>},
|
||||||
{"get_uvar", safe_function<environment_get_uvar>},
|
{"get_uvar", safe_function<environment_get_uvar>},
|
||||||
|
@ -149,8 +207,12 @@ static const struct luaL_Reg environment_m[] = {
|
||||||
{"add_theorem", safe_function<environment_add_theorem>},
|
{"add_theorem", safe_function<environment_add_theorem>},
|
||||||
{"add_var", safe_function<environment_add_var>},
|
{"add_var", safe_function<environment_add_var>},
|
||||||
{"add_axiom", safe_function<environment_add_axiom>},
|
{"add_axiom", safe_function<environment_add_axiom>},
|
||||||
|
{"find_object", safe_function<environment_find_object>},
|
||||||
|
{"has_object", safe_function<environment_has_object>},
|
||||||
{"check_type", safe_function<environment_check_type>},
|
{"check_type", safe_function<environment_check_type>},
|
||||||
{"normalize", safe_function<environment_normalize>},
|
{"normalize", safe_function<environment_normalize>},
|
||||||
|
{"objects", safe_function<environment_objects>},
|
||||||
|
{"local_objects", safe_function<environment_local_objects>},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ Author: Leonardo de Moura
|
||||||
#include "bindings/lua/local_context.h"
|
#include "bindings/lua/local_context.h"
|
||||||
#include "bindings/lua/expr.h"
|
#include "bindings/lua/expr.h"
|
||||||
#include "bindings/lua/context.h"
|
#include "bindings/lua/context.h"
|
||||||
|
#include "bindings/lua/object.h"
|
||||||
#include "bindings/lua/environment.h"
|
#include "bindings/lua/environment.h"
|
||||||
#include "bindings/lua/lean.lua"
|
#include "bindings/lua/lean.lua"
|
||||||
|
|
||||||
|
@ -97,6 +98,7 @@ struct leanlua_state::imp {
|
||||||
open_local_context(m_state);
|
open_local_context(m_state);
|
||||||
open_expr(m_state);
|
open_expr(m_state);
|
||||||
open_context(m_state);
|
open_context(m_state);
|
||||||
|
open_object(m_state);
|
||||||
open_environment(m_state);
|
open_environment(m_state);
|
||||||
open_state(m_state);
|
open_state(m_state);
|
||||||
open_thread(m_state);
|
open_thread(m_state);
|
||||||
|
|
178
src/bindings/lua/object.cpp
Normal file
178
src/bindings/lua/object.cpp
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
/*
|
||||||
|
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/object.h"
|
||||||
|
#include "bindings/lua/util.h"
|
||||||
|
#include "bindings/lua/name.h"
|
||||||
|
#include "bindings/lua/level.h"
|
||||||
|
#include "bindings/lua/expr.h"
|
||||||
|
|
||||||
|
namespace lean {
|
||||||
|
constexpr char const * object_mt = "object.mt";
|
||||||
|
|
||||||
|
bool is_object(lua_State * L, int idx) {
|
||||||
|
return testudata(L, idx, object_mt);
|
||||||
|
}
|
||||||
|
|
||||||
|
object & to_object(lua_State * L, int idx) {
|
||||||
|
return *static_cast<object*>(luaL_checkudata(L, idx, object_mt));
|
||||||
|
}
|
||||||
|
|
||||||
|
object & to_nonnull_object(lua_State * L, int idx) {
|
||||||
|
object & r = to_object(L, idx);
|
||||||
|
if (!r)
|
||||||
|
throw exception("non-null kernel object expected");
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int push_object(lua_State * L, object const & o) {
|
||||||
|
void * mem = lua_newuserdata(L, sizeof(object));
|
||||||
|
new (mem) object(o);
|
||||||
|
luaL_getmetatable(L, object_mt);
|
||||||
|
lua_setmetatable(L, -2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int object_gc(lua_State * L) {
|
||||||
|
to_object(L, 1).~object();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int object_is_null(lua_State * L) {
|
||||||
|
lua_pushboolean(L, !to_object(L, 1));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int object_keyword(lua_State * L) {
|
||||||
|
lua_pushfstring(L, to_nonnull_object(L, 1).keyword());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int object_has_name(lua_State * L) {
|
||||||
|
lua_pushboolean(L, to_nonnull_object(L, 1).has_name());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int object_get_name(lua_State * L) {
|
||||||
|
if (!to_nonnull_object(L, 1).has_name())
|
||||||
|
throw exception("kernel object does not have a name");
|
||||||
|
return push_name(L, to_nonnull_object(L, 1).get_name());
|
||||||
|
}
|
||||||
|
|
||||||
|
static int object_has_type(lua_State * L) {
|
||||||
|
lua_pushboolean(L, to_nonnull_object(L, 1).has_type());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int object_get_type(lua_State * L) {
|
||||||
|
if (!to_nonnull_object(L, 1).has_type())
|
||||||
|
throw exception("kernel object does not have a type");
|
||||||
|
return push_expr(L, to_nonnull_object(L, 1).get_type());
|
||||||
|
}
|
||||||
|
|
||||||
|
static int object_has_cnstr_level(lua_State * L) {
|
||||||
|
lua_pushboolean(L, to_nonnull_object(L, 1).has_cnstr_level());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int object_get_cnstr_level(lua_State * L) {
|
||||||
|
if (!to_nonnull_object(L, 1).has_cnstr_level())
|
||||||
|
throw exception("kernel object does not have a constraint level");
|
||||||
|
return push_level(L, to_nonnull_object(L, 1).get_cnstr_level());
|
||||||
|
}
|
||||||
|
|
||||||
|
static int object_is_definition(lua_State * L) {
|
||||||
|
lua_pushboolean(L, to_nonnull_object(L, 1).is_definition());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int object_is_opaque(lua_State * L) {
|
||||||
|
lua_pushboolean(L, to_nonnull_object(L, 1).is_opaque());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int object_get_value(lua_State * L) {
|
||||||
|
if (!to_nonnull_object(L, 1).is_definition())
|
||||||
|
throw exception("kernel object is not a definition/theorem");
|
||||||
|
return push_expr(L, to_nonnull_object(L, 1).get_value());
|
||||||
|
}
|
||||||
|
|
||||||
|
static int object_get_weight(lua_State * L) {
|
||||||
|
if (!to_nonnull_object(L, 1).is_definition())
|
||||||
|
throw exception("kernel object is not a definition");
|
||||||
|
lua_pushinteger(L, to_nonnull_object(L, 1).get_weight());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int object_is_axiom(lua_State * L) {
|
||||||
|
lua_pushboolean(L, to_nonnull_object(L, 1).is_axiom());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int object_is_theorem(lua_State * L) {
|
||||||
|
lua_pushboolean(L, to_nonnull_object(L, 1).is_theorem());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int object_is_var_decl(lua_State * L) {
|
||||||
|
lua_pushboolean(L, to_nonnull_object(L, 1).is_var_decl());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int object_is_builtin(lua_State * L) {
|
||||||
|
lua_pushboolean(L, to_nonnull_object(L, 1).is_builtin());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int object_is_builtin_set(lua_State * L) {
|
||||||
|
lua_pushboolean(L, to_nonnull_object(L, 1).is_builtin_set());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int object_in_builtin_set(lua_State * L) {
|
||||||
|
lua_pushboolean(L, to_nonnull_object(L, 1).in_builtin_set(to_expr(L, 2)));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int object_pred(lua_State * L) {
|
||||||
|
lua_pushboolean(L, is_object(L, 1));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct luaL_Reg object_m[] = {
|
||||||
|
{"__gc", object_gc}, // never throws
|
||||||
|
{"is_null", safe_function<object_is_null>},
|
||||||
|
{"keyword", safe_function<object_keyword>},
|
||||||
|
{"has_name", safe_function<object_has_name>},
|
||||||
|
{"get_name", safe_function<object_get_name>},
|
||||||
|
{"has_type", safe_function<object_has_type>},
|
||||||
|
{"get_type", safe_function<object_get_type>},
|
||||||
|
{"has_cnstr_level", safe_function<object_has_cnstr_level>},
|
||||||
|
{"get_cnstr_level", safe_function<object_get_cnstr_level>},
|
||||||
|
{"is_definition", safe_function<object_is_definition>},
|
||||||
|
{"is_opaque", safe_function<object_is_opaque>},
|
||||||
|
{"get_value", safe_function<object_get_value>},
|
||||||
|
{"get_weight", safe_function<object_get_weight>},
|
||||||
|
{"is_axiom", safe_function<object_is_axiom>},
|
||||||
|
{"is_theorem", safe_function<object_is_theorem>},
|
||||||
|
{"is_var_decl", safe_function<object_is_var_decl>},
|
||||||
|
{"is_builtin", safe_function<object_is_builtin>},
|
||||||
|
{"is_builtin_set", safe_function<object_is_builtin_set>},
|
||||||
|
{"in_builtin_set", safe_function<object_in_builtin_set>},
|
||||||
|
{0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
void open_object(lua_State * L) {
|
||||||
|
luaL_newmetatable(L, object_mt);
|
||||||
|
lua_pushvalue(L, -1);
|
||||||
|
lua_setfield(L, -2, "__index");
|
||||||
|
setfuncs(L, object_m, 0);
|
||||||
|
|
||||||
|
set_global_function<object_pred>(L, "is_kernel_object");
|
||||||
|
}
|
||||||
|
}
|
15
src/bindings/lua/object.h
Normal file
15
src/bindings/lua/object.h
Normal 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 object;
|
||||||
|
void open_object(lua_State * L);
|
||||||
|
bool is_object(lua_State * L, int idx);
|
||||||
|
object & to_object(lua_State * L, int idx);
|
||||||
|
int push_object(lua_State * L, object const & o);
|
||||||
|
}
|
16
tests/lua/env2.lua
Normal file
16
tests/lua/env2.lua
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
env = environment()
|
||||||
|
env:add_var("N", Type())
|
||||||
|
env:add_var("x", Const("N"))
|
||||||
|
for i, v in ipairs(env:objects()) do
|
||||||
|
print(v:get_name())
|
||||||
|
end
|
||||||
|
assert(not env:find_object("N"):is_null())
|
||||||
|
assert(env:find_object("Z"):is_null())
|
||||||
|
assert(env:find_object("N"):is_var_decl())
|
||||||
|
assert(env:find_object("N"):has_type())
|
||||||
|
assert(env:find_object("N"):has_name())
|
||||||
|
assert(env:find_object("N"):get_type() == Type())
|
||||||
|
assert(env:find_object("N"):get_name() == name("N"))
|
||||||
|
assert(env:find_object("x"):get_type() == Const("N"))
|
||||||
|
assert(not env:has_parent())
|
||||||
|
assert(not env:has_children())
|
Loading…
Reference in a new issue