feat(util/script_state): add 'import' command to Lua, it import files from the LEAN_PATH

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2013-12-22 21:27:12 -08:00
parent 84c984a435
commit b5d23619cb
5 changed files with 132 additions and 87 deletions

View file

@ -1,80 +1,6 @@
(** (**
-- This example demonstrates how to create Macros for automating proof -- import macros for, assume, mp, ...
-- construction using Lua. import("macros.lua")
-- This macro creates the syntax-sugar
-- name bindings ',' expr
-- For a function f with signature
-- f : ... (A : Type) ... (Pi x : A, ...)
--
-- farity is the arity of f
-- typepos is the position of (A : Type) argument
-- lambdapos is the position of the (Pi x : A, ...) argument
--
-- Example: suppose we invoke
--
-- binder_macro("for", Const("ForallIntro"), 3, 1, 3)
--
-- Then, the macro expression
--
-- for x y : Int, H x y
--
-- produces the expression
--
-- ForallIntro Int _ (fun x : Int, ForallIntro Int _ (fun y : Int, H x y))
--
-- The _ are placeholders (aka) holes that will be filled by the Lean
-- elaborator.
function binder_macro(name, f, farity, typepos, lambdapos)
macro(name, { macro_arg.Bindings, macro_arg.Comma, macro_arg.Expr },
function (bindings, body)
local r = body
for i = #bindings, 1, -1 do
local bname = bindings[i][1]
local btype = bindings[i][2]
local args = {}
args[#args + 1] = f
for j = 1, farity, 1 do
if j == typepos then
args[#args + 1] = btype
elseif j == lambdapos then
args[#args + 1] = fun(bname, btype, r)
else
args[#args + 1] = mk_placeholder()
end
end
r = mk_app(unpack(args))
end
return r
end)
end
function nary_macro(name, f, farity)
local bin_app = function(e1, e2)
local args = {}
args[#args + 1] = f
for i = 1, farity - 2, 1 do
args[#args + 1] = mk_placeholder()
end
args[#args + 1] = e1
args[#args + 1] = e2
return mk_app(unpack(args))
end
macro(name, { macro_arg.Expr, macro_arg.Expr, macro_arg.Exprs },
function (e1, e2, rest)
local r = bin_app(e1, e2)
for i = 1, #rest do
r = bin_app(r, rest[i])
end
return r
end)
end
binder_macro("for", Const("ForallIntro"), 3, 1, 3)
binder_macro("assume", Const("Discharge"), 3, 1, 3)
nary_macro("instantiate", Const("ForallElim"), 4)
nary_macro("mp", Const("MP"), 4)
**) **)
Definition Set (A : Type) : Type := A → Bool Definition Set (A : Type) : Type := A → Bool

87
src/extra/macros.lua Normal file
View file

@ -0,0 +1,87 @@
-- Extra macros for automating proof construction using Lua.
-- This macro creates the syntax-sugar
-- name bindings ',' expr
-- For a function f with signature
-- f : ... (A : Type) ... (Pi x : A, ...)
--
-- farity is the arity of f
-- typepos is the position of (A : Type) argument
-- lambdapos is the position of the (Pi x : A, ...) argument
--
-- Example: suppose we invoke
--
-- binder_macro("for", Const("ForallIntro"), 3, 1, 3)
--
-- Then, the macro expression
--
-- for x y : Int, H x y
--
-- produces the expression
--
-- ForallIntro Int _ (fun x : Int, ForallIntro Int _ (fun y : Int, H x y))
--
-- The _ are placeholders (aka) holes that will be filled by the Lean
-- elaborator.
function binder_macro(name, f, farity, typepos, lambdapos)
macro(name, { macro_arg.Bindings, macro_arg.Comma, macro_arg.Expr },
function (bindings, body)
local r = body
for i = #bindings, 1, -1 do
local bname = bindings[i][1]
local btype = bindings[i][2]
local args = {}
args[#args + 1] = f
for j = 1, farity, 1 do
if j == typepos then
args[#args + 1] = btype
elseif j == lambdapos then
args[#args + 1] = fun(bname, btype, r)
else
args[#args + 1] = mk_placeholder()
end
end
r = mk_app(unpack(args))
end
return r
end)
end
-- The following macro is used to create nary versions of operators such as MP and ForallElim.
-- Example: suppose we invoke
--
-- nary_macro("mp", Const("MP"), 4)
--
-- Then, the macro expression
--
-- mp Foo H1 H2 H3
--
-- produces the expression
--
-- (MP (MP (MP Foo H1) H2) H3)
function nary_macro(name, f, farity)
local bin_app = function(e1, e2)
local args = {}
args[#args + 1] = f
for i = 1, farity - 2, 1 do
args[#args + 1] = mk_placeholder()
end
args[#args + 1] = e1
args[#args + 1] = e2
return mk_app(unpack(args))
end
macro(name, { macro_arg.Expr, macro_arg.Expr, macro_arg.Exprs },
function (e1, e2, rest)
local r = bin_app(e1, e2)
for i = 1, #rest do
r = bin_app(r, rest[i])
end
return r
end)
end
binder_macro("for", Const("ForallIntro"), 3, 1, 3)
binder_macro("assume", Const("Discharge"), 3, 1, 3)
nary_macro("instantiate", Const("ForallElim"), 4)
nary_macro("mp", Const("MP"), 4)

View file

@ -23,16 +23,7 @@ static std::string get_exe_location() {
WCHAR path[MAX_PATH]; WCHAR path[MAX_PATH];
GetModuleFileNameW(hModule, path, MAX_PATH); GetModuleFileNameW(hModule, path, MAX_PATH);
std::wstring pathstr(path); std::wstring pathstr(path);
std::string r(pathstr.begin(), pathstr.end()); return std::string(pathstr.begin(), pathstr.end());
while (true) {
if (r.empty())
throw exception("failed to locate Lean executable location");
if (r.back() == g_sep) {
r.pop_back();
return r;
}
r.pop_back();
}
} }
#elif defined(__APPLE__) #elif defined(__APPLE__)
// OSX version // OSX version
@ -79,6 +70,18 @@ std::string normalize_path(std::string f) {
return f; return f;
} }
std::string get_path(std::string f) {
while (true) {
if (f.empty())
throw exception("failed to locate Lean executable location");
if (f.back() == g_sep) {
f.pop_back();
return f;
}
f.pop_back();
}
}
static std::string g_lean_path; static std::string g_lean_path;
static std::vector<std::string> g_lean_path_vector; static std::vector<std::string> g_lean_path_vector;
struct init_lean_path { struct init_lean_path {
@ -87,7 +90,7 @@ struct init_lean_path {
if (r == nullptr) { if (r == nullptr) {
g_lean_path = "."; g_lean_path = ".";
g_lean_path += g_path_sep; g_lean_path += g_path_sep;
g_lean_path += get_exe_location(); g_lean_path += get_path(get_exe_location());
} else { } else {
g_lean_path = r; g_lean_path = r;
} }

View file

@ -7,6 +7,7 @@ Author: Leonardo de Moura
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <vector> #include <vector>
#include <unordered_set>
#include "util/thread.h" #include "util/thread.h"
#include "util/lua.h" #include "util/lua.h"
#include "util/debug.h" #include "util/debug.h"
@ -18,6 +19,7 @@ Author: Leonardo de Moura
#include "util/script_exception.h" #include "util/script_exception.h"
#include "util/name.h" #include "util/name.h"
#include "util/splay_map.h" #include "util/splay_map.h"
#include "util/lean_path.h"
extern "C" void * lua_realloc(void *, void * q, size_t, size_t new_size) { return lean::realloc(q, new_size); } extern "C" void * lua_realloc(void *, void * q, size_t, size_t new_size) { return lean::realloc(q, new_size); }
@ -46,6 +48,7 @@ static char g_weak_ptr_key; // key for Lua registry (used at get_weak_ptr and sa
struct script_state::imp { struct script_state::imp {
lua_State * m_state; lua_State * m_state;
mutex m_mutex; mutex m_mutex;
std::unordered_set<std::string> m_imported_modules;
static std::weak_ptr<imp> * get_weak_ptr(lua_State * L) { static std::weak_ptr<imp> * get_weak_ptr(lua_State * L) {
lua_pushlightuserdata(L, static_cast<void *>(&g_weak_ptr_key)); lua_pushlightuserdata(L, static_cast<void *>(&g_weak_ptr_key));
@ -115,6 +118,14 @@ struct script_state::imp {
lock_guard<mutex> lock(m_mutex); lock_guard<mutex> lock(m_mutex);
::lean::dostring(m_state, str); ::lean::dostring(m_state, str);
} }
void import(char const * fname) {
std::string fname_str(find_file(fname));
if (m_imported_modules.find(fname_str) == m_imported_modules.end()) {
dofile(fname_str.c_str());
m_imported_modules.insert(fname_str);
}
}
}; };
script_state to_script_state(lua_State * L) { script_state to_script_state(lua_State * L) {
@ -143,6 +154,10 @@ void script_state::dostring(char const * str) {
m_ptr->dostring(str); m_ptr->dostring(str);
} }
void script_state::import(char const * str) {
m_ptr->import(str);
}
mutex & script_state::get_mutex() { mutex & script_state::get_mutex() {
return m_ptr->m_mutex; return m_ptr->m_mutex;
} }
@ -581,6 +596,13 @@ static int yield(lua_State * L) {
} }
} }
static int import(lua_State * L) {
std::string fname = luaL_checkstring(L, 1);
script_state s = to_script_state(L);
s.exec_unprotected([&]() { s.import(fname.c_str()); });
return 0;
}
static void open_interrupt(lua_State * L) { static void open_interrupt(lua_State * L) {
SET_GLOBAL_FUN(check_interrupted, "check_interrupted"); SET_GLOBAL_FUN(check_interrupted, "check_interrupted");
SET_GLOBAL_FUN(sleep, "sleep"); SET_GLOBAL_FUN(sleep, "sleep");
@ -597,5 +619,7 @@ void open_extra(lua_State * L) {
open_thread(L); open_thread(L);
#endif #endif
open_interrupt(L); open_interrupt(L);
SET_GLOBAL_FUN(import, "import");
} }
} }

View file

@ -44,6 +44,11 @@ public:
This method throws an exception if an error occurs. This method throws an exception if an error occurs.
*/ */
void dostring(char const * str); void dostring(char const * str);
/**
\brief Import file \c fname from the LEAN_PATH.
If the file was already included, then it nothing happens.
*/
void import(char const * fname);
/** /**
\brief Execute \c f in the using the internal Lua State. \brief Execute \c f in the using the internal Lua State.