Add support for creating meta-variables in the parser.

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2013-08-25 11:18:19 -07:00
parent 25e47a8a2f
commit b42e04297d
2 changed files with 32 additions and 13 deletions

View file

@ -121,6 +121,7 @@ class parser::imp {
bool m_found_errors;
local_decls m_local_decls;
unsigned m_num_local_decls;
context m_context;
builtins m_builtins;
expr_pos_info m_expr_pos_info;
pos_info m_last_cmd_pos;
@ -146,8 +147,17 @@ class parser::imp {
imp & m_fn;
local_decls::mk_scope m_scope;
unsigned m_old_num_local_decls;
mk_scope(imp & fn):m_fn(fn), m_scope(fn.m_local_decls), m_old_num_local_decls(fn.m_num_local_decls) {}
~mk_scope() { m_fn.m_num_local_decls = m_old_num_local_decls; }
context m_old_context;
mk_scope(imp & fn):
m_fn(fn),
m_scope(fn.m_local_decls),
m_old_num_local_decls(fn.m_num_local_decls),
m_old_context(fn.m_context) {
}
~mk_scope() {
m_fn.m_num_local_decls = m_old_num_local_decls;
m_fn.m_context = m_old_context;
}
};
/** \brief Return the current position information */
@ -585,7 +595,7 @@ class parser::imp {
auto p = pos();
next();
mk_scope scope(*this);
register_binding(g_unused);
register_binding(g_unused, expr());
// The -1 is a trick to get right associativity in Pratt's parsers
expr right = parse_expr(g_arrow_precedence-1);
return save(mk_arrow(left, right), p);
@ -612,8 +622,12 @@ class parser::imp {
}
/** \brief Register the name \c n as a local declaration. */
void register_binding(name const & n) {
void register_binding(name const & n, expr const & type, expr const & val = expr()) {
unsigned lvl = m_num_local_decls;
if (val)
m_context = extend(m_context, n, expr(), val);
else
m_context = extend(m_context, n, type);
m_local_decls.insert(n, lvl);
m_num_local_decls++;
lean_assert(m_local_decls.find(n)->second == lvl);
@ -630,7 +644,7 @@ class parser::imp {
unsigned sz = result.size();
result.resize(sz + names.size());
expr type = parse_expr();
for (std::pair<pos_info, name> const & n : names) register_binding(n.second);
for (std::pair<pos_info, name> const & n : names) register_binding(n.second, type);
unsigned i = names.size();
while (i > 0) {
--i;
@ -739,7 +753,7 @@ class parser::imp {
name id = check_identifier_next("invalid let expression, identifier expected");
check_assign_next("invalid let expression, ':=' expected");
expr val = parse_expr();
register_binding(id);
register_binding(id, expr(), val);
bindings.push_back(std::make_tuple(p, id, val));
if (curr_is_in()) {
next();
@ -786,8 +800,7 @@ class parser::imp {
/** \brief Create a fresh metavariable. */
expr mk_metavar() {
// TODO
return expr();
return m_elaborator.mk_metavar(m_context);
}
/** \brief Parse \c _ a hole that must be filled by the elaborator. */
@ -856,7 +869,7 @@ class parser::imp {
case scanner::token::Eq : return g_eq_precedence;
case scanner::token::Arrow : return g_arrow_precedence;
case scanner::token::LeftParen: case scanner::token::IntVal: case scanner::token::DecimalVal:
case scanner::token::StringVal: case scanner::token::Type:
case scanner::token::StringVal: case scanner::token::Type: case scanner::token::Placeholder:
return 1;
default:
return 0;
@ -874,8 +887,13 @@ class parser::imp {
/*@}*/
expr elaborate(expr const & e) {
// TODO
return e;
if (has_metavar(e)) {
// TODO fix
m_elaborator.display(std::cerr);
throw parser_error("expression contains metavariables... not implemented yet.", m_last_cmd_pos);
} else {
return e;
}
}
/**

View file

@ -25,15 +25,16 @@ class elaborator {
public:
elaborator(environment const & env);
metavar_env & menv() { return m_metaenv; }
expr operator()(expr const & e);
void clear() { m_metaenv.clear(); }
expr mk_metavar(context const & ctx) { return m_metaenv.mk_metavar(ctx); }
void set_interrupt(bool flag) { m_metaenv.set_interrupt(flag); }
void interrupt() { set_interrupt(true); }
void reset_interrupt() { set_interrupt(false); }
void display(std::ostream & out) const { m_metaenv.display(out); }
};
/** \brief Return true iff \c e is a special constant used to mark application of overloads. */