feat(lua): allow lua scripts (embedded in Lean files) to access the environment

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2013-11-10 10:12:43 -08:00
parent 3078923ea4
commit 8c140ff86f
9 changed files with 190 additions and 4 deletions

View file

@ -12,6 +12,7 @@ Author: Leonardo de Moura
#include "bindings/lua/level.h"
#include "bindings/lua/expr.h"
#include "bindings/lua/context.h"
#include "bindings/lua/environment.h"
namespace lean {
constexpr char const * environment_mt = "environment.mt";
@ -29,14 +30,18 @@ static int environment_gc(lua_State * L) {
return 0;
}
static int mk_environment(lua_State * L) {
int push_environment(lua_State * L, environment const & env) {
void * mem = lua_newuserdata(L, sizeof(environment));
new (mem) environment();
new (mem) environment(env);
luaL_getmetatable(L, environment_mt);
lua_setmetatable(L, -2);
return 1;
}
static int mk_environment(lua_State * L) {
return push_environment(L, environment());
}
static int environment_add_uvar(lua_State * L) {
int nargs = lua_gettop(L);
if (nargs == 2)
@ -120,6 +125,29 @@ static const struct luaL_Reg environment_m[] = {
{0, 0}
};
static char g_set_environment_key;
set_environment::set_environment(lua_State * L, environment & env) {
m_state = L;
lua_pushlightuserdata(m_state, (void *)&g_set_environment_key);
push_environment(m_state, env);
lua_settable(m_state, LUA_REGISTRYINDEX);
}
set_environment::~set_environment() {
lua_pushlightuserdata(m_state, (void *)&g_set_environment_key);
lua_pushnil(m_state);
lua_settable(m_state, LUA_REGISTRYINDEX);
}
int get_environment(lua_State * L) {
lua_pushlightuserdata(L, (void *)&g_set_environment_key);
lua_gettable(L, LUA_REGISTRYINDEX);
if (!is_environment(L, -1))
luaL_error(L, "Lua registry does not contain a Lean environment");
return push_environment(L, to_environment(L, -1));
}
void open_environment(lua_State * L) {
luaL_newmetatable(L, environment_mt);
lua_pushvalue(L, -1);
@ -128,5 +156,7 @@ void open_environment(lua_State * L) {
set_global_function<mk_environment>(L, "environment");
set_global_function<environment_pred>(L, "is_environment");
set_global_function<get_environment>(L, "get_environment");
set_global_function<get_environment>(L, "env");
}
}

View file

@ -11,5 +11,15 @@ class environment;
void open_environment(lua_State * L);
bool is_environment(lua_State * L, int idx);
environment & to_environment(lua_State * L, int idx);
int push_environment(lua_State * L, environment const & o);
int push_environment(lua_State * L, environment const & env);
/**
\brief Auxiliary class for setting the Lua registry of a Lua state
with an environment object.
*/
class set_environment {
lua_State * m_state;
public:
set_environment(lua_State * L, environment & env);
~set_environment();
};
}

View file

@ -68,6 +68,11 @@ struct leanlua_state::imp {
std::lock_guard<std::mutex> lock(m_mutex);
::lean::dostring(m_state, str);
}
void dostring(char const * str, environment & env) {
set_environment set(m_state, env);
dostring(str);
}
};
leanlua_state::leanlua_state():
@ -84,4 +89,8 @@ void leanlua_state::dofile(char const * fname) {
void leanlua_state::dostring(char const * str) {
m_ptr->dostring(str);
}
void leanlua_state::dostring(char const * str, environment & env) {
m_ptr->dostring(str, env);
}
}

View file

@ -9,6 +9,7 @@ Author: Leonardo de Moura
#include "bindings/lua/lua_exception.h"
namespace lean {
class environment;
/**
\brief Wrapper for lua_State objects which contains all Lean bindings.
*/
@ -29,5 +30,6 @@ public:
This method throws an exception if an error occurs.
*/
void dostring(char const * str);
void dostring(char const * str, environment & env);
};
}

View file

@ -1593,7 +1593,7 @@ class parser::imp {
m_last_script_pos = mk_pair(m_scanner.get_script_block_line(), m_scanner.get_script_block_pos());
if (!m_leanlua_state)
throw exception("failed to execute Lua script, parser does not have a Lua interpreter");
m_leanlua_state->dostring(m_scanner.get_str_val().c_str());
m_leanlua_state->dostring(m_scanner.get_str_val().c_str(), m_frontend.get_environment());
next();
}

12
tests/lean/lua4.lean Normal file
View file

@ -0,0 +1,12 @@
Variable x : Int
{{
-- Add a variable to the environment using Lua
-- The type of the new variable is equal to the type
-- of x
typeofx = env():check_type(Const("x"))
print("type of x is " .. tostring(typeofx))
env():add_var("y", typeofx)
}}
Check x + y

View file

@ -0,0 +1,5 @@
Set: pp::colors
Set: pp::unicode
Assumed: x
type of x is Int
x + y :

13
tests/lean/lua5.lean Normal file
View file

@ -0,0 +1,13 @@
Variable x : Int
{{
local N = 100
-- Create N variables with the same type of x
typeofx = env():check_type(Const("x"))
for i = 1, N do
env():add_var("y_" .. i, typeofx)
end
}}
Show Environment 101
Check x + y_1 + y_2

View file

@ -0,0 +1,105 @@
Set: pp::colors
Set: pp::unicode
Assumed: x
Variable x :
Variable y_1 :
Variable y_2 :
Variable y_3 :
Variable y_4 :
Variable y_5 :
Variable y_6 :
Variable y_7 :
Variable y_8 :
Variable y_9 :
Variable y_10 :
Variable y_11 :
Variable y_12 :
Variable y_13 :
Variable y_14 :
Variable y_15 :
Variable y_16 :
Variable y_17 :
Variable y_18 :
Variable y_19 :
Variable y_20 :
Variable y_21 :
Variable y_22 :
Variable y_23 :
Variable y_24 :
Variable y_25 :
Variable y_26 :
Variable y_27 :
Variable y_28 :
Variable y_29 :
Variable y_30 :
Variable y_31 :
Variable y_32 :
Variable y_33 :
Variable y_34 :
Variable y_35 :
Variable y_36 :
Variable y_37 :
Variable y_38 :
Variable y_39 :
Variable y_40 :
Variable y_41 :
Variable y_42 :
Variable y_43 :
Variable y_44 :
Variable y_45 :
Variable y_46 :
Variable y_47 :
Variable y_48 :
Variable y_49 :
Variable y_50 :
Variable y_51 :
Variable y_52 :
Variable y_53 :
Variable y_54 :
Variable y_55 :
Variable y_56 :
Variable y_57 :
Variable y_58 :
Variable y_59 :
Variable y_60 :
Variable y_61 :
Variable y_62 :
Variable y_63 :
Variable y_64 :
Variable y_65 :
Variable y_66 :
Variable y_67 :
Variable y_68 :
Variable y_69 :
Variable y_70 :
Variable y_71 :
Variable y_72 :
Variable y_73 :
Variable y_74 :
Variable y_75 :
Variable y_76 :
Variable y_77 :
Variable y_78 :
Variable y_79 :
Variable y_80 :
Variable y_81 :
Variable y_82 :
Variable y_83 :
Variable y_84 :
Variable y_85 :
Variable y_86 :
Variable y_87 :
Variable y_88 :
Variable y_89 :
Variable y_90 :
Variable y_91 :
Variable y_92 :
Variable y_93 :
Variable y_94 :
Variable y_95 :
Variable y_96 :
Variable y_97 :
Variable y_98 :
Variable y_99 :
Variable y_100 :
x + y_1 + y_2 :