feat(extra): add extension that demonstrates how to parse 'templates'

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2013-11-19 15:56:44 -08:00
parent 6989f1f9ba
commit 20c6789d1c
5 changed files with 81 additions and 8 deletions

View file

@ -56,7 +56,7 @@ static int parse_lean_expr(lua_State * L) {
3. (string, env, options, formatter?) : Everything is explicitly provided in this 3. (string, env, options, formatter?) : Everything is explicitly provided in this
version. We also support a variation where the formmater is omitted. version. We also support a variation where the formmater is omitted.
*/ */
int nargs = lua_gettop(L); int nargs = get_nonnil_top(L);
if (nargs == 1) { if (nargs == 1) {
ro_environment env(L); // get global environment ro_environment env(L); // get global environment
return parse_lean_expr_core(L, env); return parse_lean_expr_core(L, env);
@ -100,7 +100,7 @@ static int parse_lean_cmds(lua_State * L) {
The main difference is the function result. When calling with explicit options The main difference is the function result. When calling with explicit options
the function returns an updated set of options. Otherwise it does not return anything. the function returns an updated set of options. Otherwise it does not return anything.
*/ */
int nargs = lua_gettop(L); int nargs = get_nonnil_top(L);
if (nargs == 1) { if (nargs == 1) {
rw_environment env(L); // get global environment rw_environment env(L); // get global environment
parse_lean_cmds_core(L, env); parse_lean_cmds_core(L, env);

View file

@ -81,28 +81,41 @@ int equal(lua_State * L, int idx1, int idx2) {
#endif #endif
} }
int get_nonnil_top(lua_State * L) {
int top = lua_gettop(L);
while (top > 0 && lua_isnil(L, top))
top--;
return top;
}
static void exec(lua_State * L) { static void exec(lua_State * L) {
pcall(L, 0, LUA_MULTRET, 0); pcall(L, 0, LUA_MULTRET, 0);
} }
static void check_result(lua_State * L, int result) {
if (result) {
if (is_justification(L, -1))
throw elaborator_exception(to_justification(L, -1));
else
throw lua_exception(lua_tostring(L, -1));
}
}
void dofile(lua_State * L, char const * fname) { void dofile(lua_State * L, char const * fname) {
int result = luaL_loadfile(L, fname); int result = luaL_loadfile(L, fname);
if (result) check_result(L, result);
throw lua_exception(lua_tostring(L, -1));
exec(L); exec(L);
} }
void dostring(lua_State * L, char const * str) { void dostring(lua_State * L, char const * str) {
int result = luaL_loadstring(L, str); int result = luaL_loadstring(L, str);
if (result) check_result(L, result);
throw lua_exception(lua_tostring(L, -1));
exec(L); exec(L);
} }
void pcall(lua_State * L, int nargs, int nresults, int errorfun) { void pcall(lua_State * L, int nargs, int nresults, int errorfun) {
int result = lua_pcall(L, nargs, nresults, errorfun); int result = lua_pcall(L, nargs, nresults, errorfun);
if (result) check_result(L, result);
throw lua_exception(lua_tostring(L, -1));
} }
int safe_function_wrapper(lua_State * L, lua_CFunction f){ int safe_function_wrapper(lua_State * L, lua_CFunction f){

View file

@ -17,6 +17,7 @@ void dostring(lua_State * L, char const * str);
void pcall(lua_State * L, int nargs, int nresults, int errorfun); void pcall(lua_State * L, int nargs, int nresults, int errorfun);
int lessthan(lua_State * L, int idx1, int idx2); int lessthan(lua_State * L, int idx1, int idx2);
int equal(lua_State * L, int idx1, int idx2); int equal(lua_State * L, int idx1, int idx2);
int get_nonnil_top(lua_State * L);
/** /**
\brief Wrapper for invoking function f, and catching Lean exceptions. \brief Wrapper for invoking function f, and catching Lean exceptions.
*/ */

5
src/extra/README.md Normal file
View file

@ -0,0 +1,5 @@
Extra functionality
-------------------
This directory contains several Lua scripts that provide additional
functionality to Lean.

View file

@ -0,0 +1,54 @@
-- Parse a template expression string 'str'.
-- The string 'str' contains placeholders of the form 'a::i', where 'i' is a numeral.
-- The placeholders are replaced with values from the array 'args'.
-- See 'test' function for an example.
function parse_lean_tpl(str, args, env, opts, fmt)
assert(type(str) == "string")
assert(type(args) == "table")
assert(env == nil or is_environment(env))
if #args == 0 then
return parse_lean(str, env, opts, fmt)
else
-- Create the string "fun (a::1 : type-of-args[1]) ... (a::n : type-of-args[n]), $str",
-- where n is the size of args
local inferer = type_inferer(env)
local tbl = {"fun"}
for i = 1, #args do
table.insert(tbl, " (a::")
table.insert(tbl, i)
table.insert(tbl, " : ")
table.insert(tbl, tostring(inferer(args[i])))
table.insert(tbl, ")")
end
table.insert(tbl, ", ")
table.insert(tbl, str)
local new_str = table.concat(tbl)
local r = parse_lean(new_str, env, opts, fmt)
for i = 1, #args do
assert(r:is_lambda())
local n, d, body = r:fields()
r = body:instantiate(args[i])
end
return r
end
end
local test = function()
local env = environment()
-- Load environment with some definitions
parse_lean_cmds([[
Variables a b : Real
Variable f : Real -> Real
Variable g : Real -> Real -> Real
]], env)
local a, b, g = Consts("a, b, g")
local t1 = parse_lean_tpl("a::1 + (f a::2) - 10 + a::2", {a, g(b, a)}, env)
print(t1)
local t2 = parse_lean_tpl("f (a::1 + 1)", {g(b, b)}, env)
print(t2)
end
if not pcall(debug.getlocal, 4, 1) then
-- Main file
test()
end