diff --git a/src/bindings/lua/CMakeLists.txt b/src/bindings/lua/CMakeLists.txt index d50fe0eb6..1b8e99a46 100644 --- a/src/bindings/lua/CMakeLists.txt +++ b/src/bindings/lua/CMakeLists.txt @@ -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 environment.cpp leanlua_state.cpp) +context.cpp object.cpp environment.cpp leanlua_state.cpp) target_link_libraries(lua ${LEAN_LIBS}) diff --git a/src/bindings/lua/environment.cpp b/src/bindings/lua/environment.cpp index 598c39d4c..d151a5c71 100644 --- a/src/bindings/lua/environment.cpp +++ b/src/bindings/lua/environment.cpp @@ -12,6 +12,7 @@ Author: Leonardo de Moura #include "bindings/lua/name.h" #include "bindings/lua/level.h" #include "bindings/lua/expr.h" +#include "bindings/lua/object.h" #include "bindings/lua/context.h" #include "bindings/lua/environment.h" @@ -51,6 +52,25 @@ static int mk_environment(lua_State * L) { 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) { rw_environment env(L, 1); int nargs = lua_gettop(L); @@ -106,6 +126,17 @@ static int environment_add_axiom(lua_State * L) { 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) { ro_environment env(L, 1); 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))); } +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) { lua_pushboolean(L, is_environment(L, 1)); return 1; @@ -142,6 +197,9 @@ static int environment_tostring(lua_State * L) { static const struct luaL_Reg environment_m[] = { {"__gc", environment_gc}, // never throws {"__tostring", safe_function}, + {"has_parent", safe_function}, + {"has_children", safe_function}, + {"parent", safe_function}, {"add_uvar", safe_function}, {"is_ge", safe_function}, {"get_uvar", safe_function}, @@ -149,8 +207,12 @@ static const struct luaL_Reg environment_m[] = { {"add_theorem", safe_function}, {"add_var", safe_function}, {"add_axiom", safe_function}, + {"find_object", safe_function}, + {"has_object", safe_function}, {"check_type", safe_function}, {"normalize", safe_function}, + {"objects", safe_function}, + {"local_objects", safe_function}, {0, 0} }; diff --git a/src/bindings/lua/leanlua_state.cpp b/src/bindings/lua/leanlua_state.cpp index ccb874ba0..61803d476 100644 --- a/src/bindings/lua/leanlua_state.cpp +++ b/src/bindings/lua/leanlua_state.cpp @@ -23,6 +23,7 @@ Author: Leonardo de Moura #include "bindings/lua/local_context.h" #include "bindings/lua/expr.h" #include "bindings/lua/context.h" +#include "bindings/lua/object.h" #include "bindings/lua/environment.h" #include "bindings/lua/lean.lua" @@ -97,6 +98,7 @@ struct leanlua_state::imp { open_local_context(m_state); open_expr(m_state); open_context(m_state); + open_object(m_state); open_environment(m_state); open_state(m_state); open_thread(m_state); diff --git a/src/bindings/lua/object.cpp b/src/bindings/lua/object.cpp new file mode 100644 index 000000000..bdb51e99b --- /dev/null +++ b/src/bindings/lua/object.cpp @@ -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 +#include +#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(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}, + {"keyword", safe_function}, + {"has_name", safe_function}, + {"get_name", safe_function}, + {"has_type", safe_function}, + {"get_type", safe_function}, + {"has_cnstr_level", safe_function}, + {"get_cnstr_level", safe_function}, + {"is_definition", safe_function}, + {"is_opaque", safe_function}, + {"get_value", safe_function}, + {"get_weight", safe_function}, + {"is_axiom", safe_function}, + {"is_theorem", safe_function}, + {"is_var_decl", safe_function}, + {"is_builtin", safe_function}, + {"is_builtin_set", safe_function}, + {"in_builtin_set", safe_function}, + {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(L, "is_kernel_object"); +} +} diff --git a/src/bindings/lua/object.h b/src/bindings/lua/object.h new file mode 100644 index 000000000..a3d987cd9 --- /dev/null +++ b/src/bindings/lua/object.h @@ -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 +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); +} diff --git a/tests/lua/env2.lua b/tests/lua/env2.lua new file mode 100644 index 000000000..71ebdff33 --- /dev/null +++ b/tests/lua/env2.lua @@ -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())