2013-11-10 17:11:44 +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
|
|
|
|
*/
|
|
|
|
#include <sstream>
|
|
|
|
#include <lua.hpp>
|
|
|
|
#include "kernel/environment.h"
|
2013-11-12 04:53:23 +00:00
|
|
|
#include "kernel/formatter.h"
|
2013-11-10 17:11:44 +00:00
|
|
|
#include "bindings/lua/util.h"
|
|
|
|
#include "bindings/lua/name.h"
|
2013-11-13 00:56:30 +00:00
|
|
|
#include "bindings/lua/options.h"
|
2013-11-10 17:11:44 +00:00
|
|
|
#include "bindings/lua/level.h"
|
|
|
|
#include "bindings/lua/expr.h"
|
2013-11-12 17:40:29 +00:00
|
|
|
#include "bindings/lua/object.h"
|
2013-11-10 17:11:44 +00:00
|
|
|
#include "bindings/lua/context.h"
|
2013-11-10 18:12:43 +00:00
|
|
|
#include "bindings/lua/environment.h"
|
2013-11-13 00:56:30 +00:00
|
|
|
#include "bindings/lua/formatter.h"
|
2013-11-10 17:11:44 +00:00
|
|
|
|
|
|
|
namespace lean {
|
|
|
|
constexpr char const * environment_mt = "environment.mt";
|
|
|
|
|
|
|
|
bool is_environment(lua_State * L, int idx) {
|
|
|
|
return testudata(L, idx, environment_mt);
|
|
|
|
}
|
|
|
|
|
2013-11-12 04:32:36 +00:00
|
|
|
environment & to_environment(lua_State * L, int idx) {
|
2013-11-10 17:11:44 +00:00
|
|
|
return *static_cast<environment*>(luaL_checkudata(L, idx, environment_mt));
|
|
|
|
}
|
|
|
|
|
2013-11-12 04:29:53 +00:00
|
|
|
ro_environment::ro_environment(lua_State * L, int idx):
|
|
|
|
read_only_environment(to_environment(L, idx)) {
|
|
|
|
}
|
|
|
|
|
|
|
|
rw_environment::rw_environment(lua_State * L, int idx):
|
|
|
|
read_write_environment(to_environment(L, idx)) {
|
|
|
|
}
|
|
|
|
|
2013-11-10 17:11:44 +00:00
|
|
|
static int environment_gc(lua_State * L) {
|
|
|
|
to_environment(L, 1).~environment();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-11-10 18:12:43 +00:00
|
|
|
int push_environment(lua_State * L, environment const & env) {
|
2013-11-10 17:11:44 +00:00
|
|
|
void * mem = lua_newuserdata(L, sizeof(environment));
|
2013-11-10 18:12:43 +00:00
|
|
|
new (mem) environment(env);
|
2013-11-10 17:11:44 +00:00
|
|
|
luaL_getmetatable(L, environment_mt);
|
|
|
|
lua_setmetatable(L, -2);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2013-11-10 18:12:43 +00:00
|
|
|
static int mk_environment(lua_State * L) {
|
|
|
|
return push_environment(L, environment());
|
|
|
|
}
|
|
|
|
|
2013-11-12 17:40:29 +00:00
|
|
|
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());
|
|
|
|
}
|
|
|
|
|
2013-11-10 17:11:44 +00:00
|
|
|
static int environment_add_uvar(lua_State * L) {
|
2013-11-12 04:29:53 +00:00
|
|
|
rw_environment env(L, 1);
|
2013-11-10 17:11:44 +00:00
|
|
|
int nargs = lua_gettop(L);
|
|
|
|
if (nargs == 2)
|
2013-11-12 04:29:53 +00:00
|
|
|
env->add_uvar(to_name_ext(L, 2));
|
2013-11-10 17:11:44 +00:00
|
|
|
else
|
2013-11-12 04:29:53 +00:00
|
|
|
env->add_uvar(to_name_ext(L, 2), to_level(L, 3));
|
2013-11-10 17:11:44 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int environment_is_ge(lua_State * L) {
|
2013-11-12 04:29:53 +00:00
|
|
|
ro_environment env(L, 1);
|
|
|
|
lua_pushboolean(L, env->is_ge(to_level(L, 2), to_level(L, 3)));
|
2013-11-10 17:11:44 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int environment_get_uvar(lua_State * L) {
|
2013-11-12 04:29:53 +00:00
|
|
|
ro_environment env(L, 1);
|
|
|
|
return push_level(L, env->get_uvar(to_name_ext(L, 2)));
|
2013-11-10 17:11:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int environment_add_definition(lua_State * L) {
|
2013-11-12 04:29:53 +00:00
|
|
|
rw_environment env(L, 1);
|
2013-11-10 17:11:44 +00:00
|
|
|
int nargs = lua_gettop(L);
|
|
|
|
if (nargs == 3) {
|
2013-11-12 04:29:53 +00:00
|
|
|
env->add_definition(to_name_ext(L, 2), to_nonnull_expr(L, 3));
|
2013-11-10 17:11:44 +00:00
|
|
|
} else if (nargs == 4) {
|
|
|
|
if (is_expr(L, 4))
|
2013-11-12 04:29:53 +00:00
|
|
|
env->add_definition(to_name_ext(L, 2), to_nonnull_expr(L, 3), to_nonnull_expr(L, 4));
|
2013-11-10 17:11:44 +00:00
|
|
|
else
|
2013-11-12 04:29:53 +00:00
|
|
|
env->add_definition(to_name_ext(L, 2), to_nonnull_expr(L, 3), lua_toboolean(L, 4));
|
2013-11-10 17:11:44 +00:00
|
|
|
} else {
|
2013-11-12 04:29:53 +00:00
|
|
|
env->add_definition(to_name_ext(L, 2), to_nonnull_expr(L, 3), to_nonnull_expr(L, 4), lua_toboolean(L, 5));
|
2013-11-10 17:11:44 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int environment_add_theorem(lua_State * L) {
|
2013-11-12 04:29:53 +00:00
|
|
|
rw_environment env(L, 1);
|
|
|
|
env->add_theorem(to_name_ext(L, 2), to_nonnull_expr(L, 3), to_nonnull_expr(L, 4));
|
2013-11-10 17:11:44 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int environment_add_var(lua_State * L) {
|
2013-11-12 04:29:53 +00:00
|
|
|
rw_environment env(L, 1);
|
|
|
|
env->add_var(to_name_ext(L, 2), to_nonnull_expr(L, 3));
|
2013-11-10 17:11:44 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int environment_add_axiom(lua_State * L) {
|
2013-11-12 04:29:53 +00:00
|
|
|
rw_environment env(L, 1);
|
|
|
|
env->add_axiom(to_name_ext(L, 2), to_nonnull_expr(L, 3));
|
2013-11-10 17:11:44 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-11-12 17:40:29 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-11-10 17:11:44 +00:00
|
|
|
static int environment_check_type(lua_State * L) {
|
2013-11-12 04:29:53 +00:00
|
|
|
ro_environment env(L, 1);
|
2013-11-10 17:11:44 +00:00
|
|
|
int nargs = lua_gettop(L);
|
|
|
|
if (nargs == 2)
|
2013-11-12 04:29:53 +00:00
|
|
|
return push_expr(L, env->infer_type(to_nonnull_expr(L, 2)));
|
2013-11-10 17:11:44 +00:00
|
|
|
else
|
2013-11-12 04:29:53 +00:00
|
|
|
return push_expr(L, env->infer_type(to_nonnull_expr(L, 2), to_context(L, 3)));
|
2013-11-10 17:11:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int environment_normalize(lua_State * L) {
|
2013-11-12 04:29:53 +00:00
|
|
|
ro_environment env(L, 1);
|
2013-11-10 17:11:44 +00:00
|
|
|
int nargs = lua_gettop(L);
|
|
|
|
if (nargs == 2)
|
2013-11-12 04:29:53 +00:00
|
|
|
return push_expr(L, env->normalize(to_nonnull_expr(L, 2)));
|
2013-11-10 17:11:44 +00:00
|
|
|
else
|
2013-11-12 04:29:53 +00:00
|
|
|
return push_expr(L, env->normalize(to_nonnull_expr(L, 2), to_context(L, 3)));
|
2013-11-10 17:11:44 +00:00
|
|
|
}
|
|
|
|
|
2013-11-13 22:26:01 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
\brief Iterator (closure base function) for kernel objects.
|
|
|
|
|
|
|
|
\see environment_objects
|
|
|
|
\see environment_local_objects.
|
|
|
|
*/
|
|
|
|
static int environment_next_object(lua_State * L) {
|
|
|
|
ro_environment env(L, lua_upvalueindex(1));
|
|
|
|
unsigned i = lua_tointeger(L, lua_upvalueindex(2));
|
|
|
|
unsigned num = lua_tointeger(L, lua_upvalueindex(3));
|
|
|
|
if (i >= num) {
|
|
|
|
lua_pushnil(L);
|
|
|
|
} else {
|
|
|
|
bool local = lua_toboolean(L, lua_upvalueindex(4));
|
|
|
|
lua_pushinteger(L, i + 1);
|
|
|
|
lua_replace(L, lua_upvalueindex(2)); // update closure
|
|
|
|
push_object(L, env->get_object(i, local));
|
2013-11-12 17:40:29 +00:00
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2013-11-13 22:26:01 +00:00
|
|
|
static int environment_objects_core(lua_State * L, bool local) {
|
2013-11-12 17:40:29 +00:00
|
|
|
ro_environment env(L, 1);
|
2013-11-13 22:26:01 +00:00
|
|
|
push_environment(L, env); // upvalue(1): environment
|
|
|
|
lua_pushinteger(L, 0); // upvalue(2): index
|
|
|
|
lua_pushinteger(L, env->get_num_objects(local)); // upvalue(3): size
|
|
|
|
lua_pushboolean(L, local); // upvalue(4): local flag
|
|
|
|
lua_pushcclosure(L, &environment_next_object, 4); // create closure with 4 upvalues
|
2013-11-12 17:40:29 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2013-11-13 22:26:01 +00:00
|
|
|
static int environment_objects(lua_State * L) {
|
|
|
|
return environment_objects_core(L, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int environment_local_objects(lua_State * L) {
|
|
|
|
return environment_objects_core(L, true);
|
|
|
|
}
|
|
|
|
|
2013-11-10 17:11:44 +00:00
|
|
|
static int environment_pred(lua_State * L) {
|
|
|
|
lua_pushboolean(L, is_environment(L, 1));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2013-11-12 04:53:23 +00:00
|
|
|
static int environment_tostring(lua_State * L) {
|
|
|
|
ro_environment env(L, 1);
|
|
|
|
std::ostringstream out;
|
2013-11-13 00:56:30 +00:00
|
|
|
formatter fmt = get_global_formatter(L);
|
|
|
|
options opts = get_global_options(L);
|
|
|
|
out << mk_pair(fmt(env, opts), opts);
|
2013-11-13 20:14:55 +00:00
|
|
|
lua_pushstring(L, out.str().c_str());
|
2013-11-12 04:53:23 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2013-11-10 17:11:44 +00:00
|
|
|
static const struct luaL_Reg environment_m[] = {
|
|
|
|
{"__gc", environment_gc}, // never throws
|
2013-11-12 04:53:23 +00:00
|
|
|
{"__tostring", safe_function<environment_tostring>},
|
2013-11-12 17:40:29 +00:00
|
|
|
{"has_parent", safe_function<environment_has_parent>},
|
|
|
|
{"has_children", safe_function<environment_has_children>},
|
|
|
|
{"parent", safe_function<environment_parent>},
|
2013-11-10 17:11:44 +00:00
|
|
|
{"add_uvar", safe_function<environment_add_uvar>},
|
|
|
|
{"is_ge", safe_function<environment_is_ge>},
|
|
|
|
{"get_uvar", safe_function<environment_get_uvar>},
|
|
|
|
{"add_definition", safe_function<environment_add_definition>},
|
|
|
|
{"add_theorem", safe_function<environment_add_theorem>},
|
|
|
|
{"add_var", safe_function<environment_add_var>},
|
|
|
|
{"add_axiom", safe_function<environment_add_axiom>},
|
2013-11-12 17:40:29 +00:00
|
|
|
{"find_object", safe_function<environment_find_object>},
|
|
|
|
{"has_object", safe_function<environment_has_object>},
|
2013-11-10 17:11:44 +00:00
|
|
|
{"check_type", safe_function<environment_check_type>},
|
|
|
|
{"normalize", safe_function<environment_normalize>},
|
2013-11-12 17:40:29 +00:00
|
|
|
{"objects", safe_function<environment_objects>},
|
|
|
|
{"local_objects", safe_function<environment_local_objects>},
|
2013-11-10 17:11:44 +00:00
|
|
|
{0, 0}
|
|
|
|
};
|
|
|
|
|
2013-11-10 18:12:43 +00:00
|
|
|
static char g_set_environment_key;
|
|
|
|
|
|
|
|
set_environment::set_environment(lua_State * L, environment & env) {
|
|
|
|
m_state = L;
|
2013-11-10 19:13:18 +00:00
|
|
|
lua_pushlightuserdata(m_state, static_cast<void *>(&g_set_environment_key));
|
2013-11-10 18:12:43 +00:00
|
|
|
push_environment(m_state, env);
|
|
|
|
lua_settable(m_state, LUA_REGISTRYINDEX);
|
|
|
|
}
|
|
|
|
|
|
|
|
set_environment::~set_environment() {
|
2013-11-10 19:13:18 +00:00
|
|
|
lua_pushlightuserdata(m_state, static_cast<void *>(&g_set_environment_key));
|
2013-11-10 18:12:43 +00:00
|
|
|
lua_pushnil(m_state);
|
|
|
|
lua_settable(m_state, LUA_REGISTRYINDEX);
|
|
|
|
}
|
|
|
|
|
|
|
|
int get_environment(lua_State * L) {
|
2013-11-10 19:13:18 +00:00
|
|
|
lua_pushlightuserdata(L, static_cast<void *>(&g_set_environment_key));
|
2013-11-10 18:12:43 +00:00
|
|
|
lua_gettable(L, LUA_REGISTRYINDEX);
|
|
|
|
if (!is_environment(L, -1))
|
2013-11-12 05:44:10 +00:00
|
|
|
throw exception("Lua registry does not contain a Lean environment");
|
2013-11-10 18:12:43 +00:00
|
|
|
return push_environment(L, to_environment(L, -1));
|
|
|
|
}
|
|
|
|
|
2013-11-10 17:11:44 +00:00
|
|
|
void open_environment(lua_State * L) {
|
|
|
|
luaL_newmetatable(L, environment_mt);
|
|
|
|
lua_pushvalue(L, -1);
|
|
|
|
lua_setfield(L, -2, "__index");
|
|
|
|
setfuncs(L, environment_m, 0);
|
|
|
|
|
2013-11-13 19:46:09 +00:00
|
|
|
SET_GLOBAL_FUN(mk_environment, "environment");
|
|
|
|
SET_GLOBAL_FUN(environment_pred, "is_environment");
|
|
|
|
SET_GLOBAL_FUN(get_environment, "get_environment");
|
2013-11-13 21:58:51 +00:00
|
|
|
SET_GLOBAL_FUN(get_environment, "get_env");
|
2013-11-10 17:11:44 +00:00
|
|
|
}
|
|
|
|
}
|