lean2/src/frontends/lean/parser_macros.cpp

141 lines
4.6 KiB
C++
Raw Normal View History

/*
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 "frontends/lean/parser_imp.h"
#include "frontends/lean/notation.h"
namespace lean {
static char g_set_parser_key;
/** \brief Return a reference to the parser object */
parser_imp * get_parser(lua_State * L) {
lua_pushlightuserdata(L, static_cast<void *>(&g_set_parser_key));
lua_gettable(L, LUA_REGISTRYINDEX);
if (lua_islightuserdata(L, -1)) {
auto r = static_cast<parser_imp*>(lua_touserdata(L, -1));
lua_pop(L, 1);
return r;
}
lua_pop(L, 1);
return nullptr;
}
set_parser::set_parser(script_state * S, parser_imp * ptr) {
m_state = S;
if (m_state) {
m_state->apply([&](lua_State * L) {
m_prev = get_parser(L);
lua_pushlightuserdata(L, static_cast<void *>(&g_set_parser_key));
lua_pushlightuserdata(L, ptr);
lua_settable(L, LUA_REGISTRYINDEX);
});
}
}
set_parser::~set_parser() {
if (m_state) {
m_state->apply([&](lua_State * L) {
lua_pushlightuserdata(L, static_cast<void *>(&g_set_parser_key));
lua_pushlightuserdata(L, m_prev);
lua_settable(L, LUA_REGISTRYINDEX);
});
}
}
static char g_parser_expr_macros_key;
static char g_parser_tactic_macros_key;
static char g_parser_cmd_macros_key;
DECL_UDATA(macros)
macros & get_macros(lua_State * L, char * key) {
lua_pushlightuserdata(L, static_cast<void *>(key));
lua_gettable(L, LUA_REGISTRYINDEX);
if (lua_isnil(L, -1)) {
lua_pop(L, 1);
lua_pushlightuserdata(L, static_cast<void *>(key));
push_macros(L, macros());
lua_settable(L, LUA_REGISTRYINDEX);
lua_pushlightuserdata(L, static_cast<void *>(key));
lua_gettable(L, LUA_REGISTRYINDEX);
}
lean_assert(is_macros(L, -1));
macros & r = to_macros(L, -1);
lua_pop(L, 1);
return r;
}
macros & get_expr_macros(lua_State * L) { return get_macros(L, &g_parser_expr_macros_key); }
macros & get_tactic_macros(lua_State * L) { return get_macros(L, &g_parser_tactic_macros_key); }
macros & get_cmd_macros(lua_State * L) { return get_macros(L, &g_parser_cmd_macros_key); }
void mk_macro(lua_State * L, macros & mtable) {
int nargs = lua_gettop(L);
name macro_name = to_name_ext(L, 1);
unsigned prec = nargs == 4 ? lua_tointeger(L, 4) : g_app_precedence;
luaL_checktype(L, 3, LUA_TFUNCTION); // user-fun
buffer<macro_arg_kind> arg_kind_buffer;
int n = objlen(L, 2);
for (int i = 1; i <= n; i++) {
lua_rawgeti(L, 2, i);
arg_kind_buffer.push_back(static_cast<macro_arg_kind>(luaL_checkinteger(L, -1)));
lua_pop(L, 1);
}
list<macro_arg_kind> arg_kinds = to_list(arg_kind_buffer.begin(), arg_kind_buffer.end());
mtable.insert(mk_pair(macro_name, macro(arg_kinds, luaref(L, 3), prec)));
}
int mk_macro(lua_State * L) {
mk_macro(L, get_expr_macros(L));
return 0;
}
int mk_cmd_macro(lua_State * L) {
mk_macro(L, get_cmd_macros(L));
name macro_name = to_name_ext(L, 1);
parser_imp * ptr = get_parser(L);
if (!ptr)
throw exception("invalid cmd_macro, it is not in the context of a Lean parser");
// Make sure macro_name is a CommandId.
ptr->m_scanner.add_command_keyword(macro_name);
if (ptr->m_curr == scanner::token::Id && ptr->curr_name() == macro_name) {
ptr->m_curr = scanner::token::CommandId;
}
return 0;
}
int mk_tactic_macro(lua_State * L) {
mk_macro(L, get_tactic_macros(L));
return 0;
}
static const struct luaL_Reg macros_m[] = {
{"__gc", macros_gc}, // never throws
{0, 0}
};
void open_macros(lua_State * L) {
luaL_newmetatable(L, macros_mt);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
setfuncs(L, macros_m, 0);
SET_GLOBAL_FUN(macros_pred, "is_macros");
SET_GLOBAL_FUN(mk_macro, "macro");
SET_GLOBAL_FUN(mk_cmd_macro, "cmd_macro");
SET_GLOBAL_FUN(mk_tactic_macro, "tactic_macro");
lua_newtable(L);
SET_ENUM("Expr", macro_arg_kind::Expr);
SET_ENUM("Exprs", macro_arg_kind::Exprs);
SET_ENUM("Parameters", macro_arg_kind::Parameters);
SET_ENUM("Id", macro_arg_kind::Id);
SET_ENUM("String", macro_arg_kind::String);
SET_ENUM("Int", macro_arg_kind::Int);
SET_ENUM("Comma", macro_arg_kind::Comma);
SET_ENUM("Assign", macro_arg_kind::Assign);
SET_ENUM("Tactic", macro_arg_kind::Tactic);
SET_ENUM("Tactics", macro_arg_kind::Tactics);
lua_setglobal(L, "macro_arg");
}
}