feat(extra): add extension that demonstrates how to parse 'templates'
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
6989f1f9ba
commit
20c6789d1c
5 changed files with 81 additions and 8 deletions
|
@ -56,7 +56,7 @@ static int parse_lean_expr(lua_State * L) {
|
|||
3. (string, env, options, formatter?) : Everything is explicitly provided in this
|
||||
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) {
|
||||
ro_environment env(L); // get global environment
|
||||
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 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) {
|
||||
rw_environment env(L); // get global environment
|
||||
parse_lean_cmds_core(L, env);
|
||||
|
|
|
@ -81,28 +81,41 @@ int equal(lua_State * L, int idx1, int idx2) {
|
|||
#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) {
|
||||
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) {
|
||||
int result = luaL_loadfile(L, fname);
|
||||
if (result)
|
||||
throw lua_exception(lua_tostring(L, -1));
|
||||
check_result(L, result);
|
||||
exec(L);
|
||||
}
|
||||
|
||||
void dostring(lua_State * L, char const * str) {
|
||||
int result = luaL_loadstring(L, str);
|
||||
if (result)
|
||||
throw lua_exception(lua_tostring(L, -1));
|
||||
check_result(L, result);
|
||||
exec(L);
|
||||
}
|
||||
|
||||
void pcall(lua_State * L, int nargs, int nresults, int errorfun) {
|
||||
int result = lua_pcall(L, nargs, nresults, errorfun);
|
||||
if (result)
|
||||
throw lua_exception(lua_tostring(L, -1));
|
||||
check_result(L, result);
|
||||
}
|
||||
|
||||
int safe_function_wrapper(lua_State * L, lua_CFunction f){
|
||||
|
|
|
@ -17,6 +17,7 @@ void dostring(lua_State * L, char const * str);
|
|||
void pcall(lua_State * L, int nargs, int nresults, int errorfun);
|
||||
int lessthan(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.
|
||||
*/
|
||||
|
|
5
src/extra/README.md
Normal file
5
src/extra/README.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
Extra functionality
|
||||
-------------------
|
||||
|
||||
This directory contains several Lua scripts that provide additional
|
||||
functionality to Lean.
|
54
src/extra/parse_lean_tpl.lua
Normal file
54
src/extra/parse_lean_tpl.lua
Normal 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
|
Loading…
Reference in a new issue