2014-06-12 03:56:10 +00:00
|
|
|
/*
|
|
|
|
Copyright (c) 2014 Microsoft Corporation. All rights reserved.
|
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
|
|
|
|
Author: Leonardo de Moura
|
|
|
|
*/
|
2014-07-05 01:33:46 +00:00
|
|
|
#include "util/sstream.h"
|
2014-06-16 16:50:34 +00:00
|
|
|
#include "kernel/abstract.h"
|
2014-08-22 17:38:10 +00:00
|
|
|
#include "library/annotation.h"
|
2014-06-16 16:50:34 +00:00
|
|
|
#include "library/placeholder.h"
|
2014-06-25 19:50:47 +00:00
|
|
|
#include "library/explicit.h"
|
2014-10-23 17:24:03 +00:00
|
|
|
#include "library/aliases.h"
|
|
|
|
#include "library/scoped_ext.h"
|
2014-07-03 02:30:48 +00:00
|
|
|
#include "library/tactic/tactic.h"
|
2014-07-02 03:43:53 +00:00
|
|
|
#include "library/tactic/expr_to_tactic.h"
|
2014-10-22 21:23:14 +00:00
|
|
|
#include "library/tactic/exact_tactic.h"
|
2014-10-23 17:24:03 +00:00
|
|
|
#include "library/tactic/util.h"
|
2014-08-22 18:26:00 +00:00
|
|
|
#include "library/typed_expr.h"
|
2014-08-27 23:30:30 +00:00
|
|
|
#include "library/choice.h"
|
2014-08-29 01:20:58 +00:00
|
|
|
#include "library/let.h"
|
2015-01-24 00:50:32 +00:00
|
|
|
#include "library/constants.h"
|
2014-12-04 23:11:23 +00:00
|
|
|
#include "library/definitional/equations.h"
|
2015-02-25 21:58:39 +00:00
|
|
|
#include "library/tactic/assert_tactic.h"
|
2014-06-12 03:56:10 +00:00
|
|
|
#include "frontends/lean/builtin_exprs.h"
|
2015-01-10 18:11:13 +00:00
|
|
|
#include "frontends/lean/decl_cmds.h"
|
2014-06-13 22:13:32 +00:00
|
|
|
#include "frontends/lean/token_table.h"
|
2014-06-18 00:15:38 +00:00
|
|
|
#include "frontends/lean/calc.h"
|
2014-08-21 17:36:44 +00:00
|
|
|
#include "frontends/lean/begin_end_ext.h"
|
2014-06-12 16:08:38 +00:00
|
|
|
#include "frontends/lean/parser.h"
|
2014-07-14 04:41:44 +00:00
|
|
|
#include "frontends/lean/util.h"
|
2014-09-23 17:00:36 +00:00
|
|
|
#include "frontends/lean/tokens.h"
|
2014-10-23 20:30:04 +00:00
|
|
|
#include "frontends/lean/info_tactic.h"
|
2014-11-05 01:28:30 +00:00
|
|
|
#include "frontends/lean/info_annotation.h"
|
2015-01-17 01:08:48 +00:00
|
|
|
#include "frontends/lean/structure_cmd.h"
|
2015-02-03 01:02:14 +00:00
|
|
|
#include "frontends/lean/parse_rewrite_tactic.h"
|
2014-06-12 03:56:10 +00:00
|
|
|
|
|
|
|
namespace lean {
|
|
|
|
namespace notation {
|
2014-06-16 19:28:58 +00:00
|
|
|
static expr parse_Type(parser & p, unsigned, expr const *, pos_info const & pos) {
|
2014-09-23 17:00:36 +00:00
|
|
|
if (p.curr_is_token(get_llevel_curly_tk())) {
|
2014-06-12 16:08:38 +00:00
|
|
|
p.next();
|
|
|
|
level l = p.parse_level();
|
2014-09-23 17:00:36 +00:00
|
|
|
p.check_token_next(get_rcurly_tk(), "invalid Type expression, '}' expected");
|
2014-06-16 19:28:58 +00:00
|
|
|
return p.save_pos(mk_sort(l), pos);
|
2014-06-12 16:08:38 +00:00
|
|
|
} else {
|
2014-07-10 12:28:36 +00:00
|
|
|
return p.save_pos(mk_sort(mk_level_placeholder()), pos);
|
2014-06-12 16:08:38 +00:00
|
|
|
}
|
|
|
|
}
|
2014-06-12 03:56:10 +00:00
|
|
|
|
2014-06-16 19:28:58 +00:00
|
|
|
static expr parse_let(parser & p, pos_info const & pos);
|
|
|
|
static expr parse_let_body(parser & p, pos_info const & pos) {
|
2014-09-23 17:00:36 +00:00
|
|
|
if (p.curr_is_token(get_comma_tk())) {
|
2014-06-16 16:50:34 +00:00
|
|
|
p.next();
|
2014-06-16 19:28:58 +00:00
|
|
|
return parse_let(p, pos);
|
2014-09-23 17:00:36 +00:00
|
|
|
} else if (p.curr_is_token(get_in_tk())) {
|
2014-06-16 16:50:34 +00:00
|
|
|
p.next();
|
|
|
|
return p.parse_expr();
|
|
|
|
} else {
|
|
|
|
throw parser_error("invalid let declaration, 'in' or ',' expected", p.pos());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-08 14:47:42 +00:00
|
|
|
static void parse_let_modifiers(parser & p, bool & is_visible) {
|
2014-06-24 23:27:23 +00:00
|
|
|
while (true) {
|
2014-09-23 17:00:36 +00:00
|
|
|
if (p.curr_is_token(get_visible_tk())) {
|
2014-09-08 14:47:42 +00:00
|
|
|
is_visible = true;
|
2014-06-24 23:27:23 +00:00
|
|
|
p.next();
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-16 19:28:58 +00:00
|
|
|
static expr parse_let(parser & p, pos_info const & pos) {
|
2014-06-16 16:50:34 +00:00
|
|
|
parser::local_scope scope1(p);
|
|
|
|
if (p.parse_local_notation_decl()) {
|
2014-06-16 19:28:58 +00:00
|
|
|
return parse_let_body(p, pos);
|
2014-06-16 16:50:34 +00:00
|
|
|
} else {
|
2014-09-08 14:47:42 +00:00
|
|
|
auto id_pos = p.pos();
|
|
|
|
name id = p.check_atomic_id_next("invalid let declaration, identifier expected");
|
|
|
|
bool is_visible = false;
|
2014-08-28 23:27:52 +00:00
|
|
|
optional<expr> type;
|
|
|
|
expr value;
|
2014-09-08 14:47:42 +00:00
|
|
|
parse_let_modifiers(p, is_visible);
|
2014-09-23 17:00:36 +00:00
|
|
|
if (p.curr_is_token(get_assign_tk())) {
|
2014-06-16 16:50:34 +00:00
|
|
|
p.next();
|
|
|
|
value = p.parse_expr();
|
2014-09-23 17:00:36 +00:00
|
|
|
} else if (p.curr_is_token(get_colon_tk())) {
|
2014-06-16 16:50:34 +00:00
|
|
|
p.next();
|
|
|
|
type = p.parse_expr();
|
2014-09-23 17:00:36 +00:00
|
|
|
p.check_token_next(get_assign_tk(), "invalid declaration, ':=' expected");
|
2014-06-16 16:50:34 +00:00
|
|
|
value = p.parse_expr();
|
|
|
|
} else {
|
|
|
|
parser::local_scope scope2(p);
|
2014-06-30 16:14:55 +00:00
|
|
|
buffer<expr> ps;
|
2014-11-24 00:42:53 +00:00
|
|
|
unsigned rbp = 0;
|
|
|
|
auto lenv = p.parse_binders(ps, rbp);
|
2014-09-23 17:00:36 +00:00
|
|
|
if (p.curr_is_token(get_colon_tk())) {
|
2014-06-16 16:50:34 +00:00
|
|
|
p.next();
|
|
|
|
type = p.parse_scoped_expr(ps, lenv);
|
2014-08-28 23:27:52 +00:00
|
|
|
type = Pi(ps, *type, p);
|
2014-06-16 16:50:34 +00:00
|
|
|
}
|
2014-09-23 17:00:36 +00:00
|
|
|
p.check_token_next(get_assign_tk(), "invalid let declaration, ':=' expected");
|
2014-06-16 16:50:34 +00:00
|
|
|
value = p.parse_scoped_expr(ps, lenv);
|
2014-07-14 04:41:44 +00:00
|
|
|
value = Fun(ps, value, p);
|
2014-06-16 16:50:34 +00:00
|
|
|
}
|
2014-08-28 23:27:52 +00:00
|
|
|
expr v;
|
|
|
|
if (type)
|
|
|
|
v = p.save_pos(mk_typed_expr(*type, value), p.pos_of(value));
|
|
|
|
else
|
|
|
|
v = value;
|
2014-08-29 16:58:11 +00:00
|
|
|
v = p.save_pos(mk_let_value(v), id_pos);
|
2014-08-28 23:27:52 +00:00
|
|
|
p.add_local_expr(id, v);
|
2014-08-29 01:20:58 +00:00
|
|
|
expr b = parse_let_body(p, pos);
|
|
|
|
return p.save_pos(mk_let(id, v, b), pos);
|
2014-06-16 16:50:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-16 19:28:58 +00:00
|
|
|
static expr parse_let_expr(parser & p, unsigned, expr const *, pos_info const & pos) {
|
|
|
|
return parse_let(p, pos);
|
2014-06-16 16:50:34 +00:00
|
|
|
}
|
|
|
|
|
2014-06-16 19:28:58 +00:00
|
|
|
static expr parse_placeholder(parser & p, unsigned, expr const *, pos_info const & pos) {
|
2014-08-15 19:45:54 +00:00
|
|
|
return p.save_pos(mk_explicit_expr_placeholder(), pos);
|
2014-06-16 19:28:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static expr parse_by(parser & p, unsigned, expr const *, pos_info const & pos) {
|
2014-10-28 00:12:25 +00:00
|
|
|
parser::undef_id_to_local_scope scope(p);
|
|
|
|
p.next();
|
2015-03-06 02:07:06 +00:00
|
|
|
expr t = p.parse_tactic();
|
2014-07-03 15:33:29 +00:00
|
|
|
return p.mk_by(t, pos);
|
2014-06-16 17:41:08 +00:00
|
|
|
}
|
|
|
|
|
2015-02-24 19:59:27 +00:00
|
|
|
static expr parse_begin_end_core(parser & p, pos_info const & pos, name const & end_token, bool nested = false) {
|
2014-07-03 15:33:29 +00:00
|
|
|
if (!p.has_tactic_decls())
|
2014-08-21 17:36:44 +00:00
|
|
|
throw parser_error("invalid 'begin-end' expression, tactic module has not been imported", pos);
|
2014-10-26 22:47:29 +00:00
|
|
|
parser::undef_id_to_local_scope scope1(p);
|
2014-10-28 00:12:25 +00:00
|
|
|
p.next();
|
2015-03-06 02:07:06 +00:00
|
|
|
optional<expr> pre_tac = get_begin_end_pre_tactic(p.env());
|
2014-10-15 00:12:57 +00:00
|
|
|
buffer<expr> tacs;
|
|
|
|
bool first = true;
|
2015-02-25 21:58:39 +00:00
|
|
|
|
|
|
|
auto add_tac = [&](expr tac, pos_info const & pos) {
|
|
|
|
if (pre_tac)
|
|
|
|
tac = p.mk_app({get_and_then_tac_fn(), *pre_tac, tac}, pos);
|
|
|
|
tac = mk_begin_end_element_annotation(tac);
|
|
|
|
tacs.push_back(tac);
|
|
|
|
};
|
|
|
|
|
2015-03-13 22:22:57 +00:00
|
|
|
try {
|
|
|
|
while (!p.curr_is_token(end_token)) {
|
|
|
|
if (first) {
|
|
|
|
first = false;
|
2015-02-25 21:58:39 +00:00
|
|
|
} else {
|
2015-03-13 22:22:57 +00:00
|
|
|
auto pos = p.pos();
|
|
|
|
p.check_token_next(get_comma_tk(), "invalid 'begin-end' expression, ',' expected");
|
|
|
|
if (p.collecting_info()) {
|
|
|
|
expr info_tac = p.save_pos(mk_info_tactic_expr(), pos);
|
|
|
|
tacs.push_back(mk_begin_end_element_annotation(info_tac));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (p.curr_is_token(get_begin_tk())) {
|
|
|
|
auto pos = p.pos();
|
|
|
|
tacs.push_back(parse_begin_end_core(p, pos, get_end_tk(), true));
|
|
|
|
} else if (p.curr_is_token(get_lcurly_tk())) {
|
|
|
|
auto pos = p.pos();
|
|
|
|
tacs.push_back(parse_begin_end_core(p, pos, get_rcurly_tk(), true));
|
|
|
|
} else if (p.curr_is_token(end_token)) {
|
|
|
|
break;
|
|
|
|
} else if (p.curr_is_token(get_assert_tk())) {
|
|
|
|
auto pos = p.pos();
|
|
|
|
p.next();
|
|
|
|
name id = p.check_id_next("invalid 'assert' tactic, identifier expected");
|
|
|
|
p.check_token_next(get_colon_tk(), "invalid 'assert' tactic, ':' expected");
|
|
|
|
expr A = p.parse_expr();
|
|
|
|
expr assert_tac = p.save_pos(mk_assert_tactic_expr(id, A), pos);
|
|
|
|
tacs.push_back(mk_begin_end_element_annotation(assert_tac));
|
|
|
|
} else if (p.curr_is_token(get_have_tk())) {
|
|
|
|
auto pos = p.pos();
|
|
|
|
p.next();
|
|
|
|
auto id_pos = p.pos();
|
|
|
|
name id = p.check_id_next("invalid 'have' tactic, identifier expected");
|
|
|
|
p.check_token_next(get_colon_tk(), "invalid 'have' tactic, ':' expected");
|
|
|
|
expr A = p.parse_expr();
|
|
|
|
expr assert_tac = p.save_pos(mk_assert_tactic_expr(id, A), pos);
|
|
|
|
tacs.push_back(mk_begin_end_element_annotation(assert_tac));
|
|
|
|
if (p.curr_is_token(get_bar_tk())) {
|
|
|
|
expr local = p.save_pos(mk_local(id, A), id_pos);
|
|
|
|
expr t = parse_local_equations(p, local);
|
2015-03-07 03:04:09 +00:00
|
|
|
t = p.mk_app(get_exact_tac_fn(), t, pos);
|
|
|
|
t = p.save_pos(mk_begin_end_element_annotation(t), pos);
|
|
|
|
t = p.save_pos(mk_begin_end_annotation(t), pos);
|
|
|
|
add_tac(t, pos);
|
|
|
|
} else {
|
2015-03-13 22:22:57 +00:00
|
|
|
p.check_token_next(get_comma_tk(), "invalid 'have' tactic, ',' expected");
|
|
|
|
if (p.curr_is_token(get_from_tk())) {
|
|
|
|
// parse: 'from' expr
|
|
|
|
p.next();
|
|
|
|
auto pos = p.pos();
|
|
|
|
expr t = p.parse_expr();
|
|
|
|
t = p.mk_app(get_exact_tac_fn(), t, pos);
|
|
|
|
t = p.save_pos(mk_begin_end_element_annotation(t), pos);
|
|
|
|
t = p.save_pos(mk_begin_end_annotation(t), pos);
|
|
|
|
add_tac(t, pos);
|
|
|
|
} else if (p.curr_is_token(get_proof_tk())) {
|
|
|
|
auto pos = p.pos();
|
|
|
|
p.next();
|
|
|
|
expr t = p.parse_expr();
|
|
|
|
p.check_token_next(get_qed_tk(), "invalid proof-qed, 'qed' expected");
|
|
|
|
t = p.mk_app(get_exact_tac_fn(), t, pos);
|
|
|
|
t = p.save_pos(mk_begin_end_element_annotation(t), pos);
|
|
|
|
t = p.save_pos(mk_begin_end_annotation(t), pos);
|
|
|
|
add_tac(t, pos);
|
|
|
|
} else if (p.curr_is_token(get_begin_tk())) {
|
|
|
|
auto pos = p.pos();
|
|
|
|
tacs.push_back(parse_begin_end_core(p, pos, get_end_tk(), true));
|
|
|
|
} else if (p.curr_is_token(get_by_tk())) {
|
|
|
|
// parse: 'by' tactic
|
|
|
|
auto pos = p.pos();
|
|
|
|
p.next();
|
|
|
|
expr t = p.parse_tactic();
|
|
|
|
add_tac(t, pos);
|
|
|
|
} else {
|
|
|
|
throw parser_error("invalid 'have' tactic, 'by', 'begin', 'proof', or 'from' expected", p.pos());
|
|
|
|
}
|
2015-03-07 03:04:09 +00:00
|
|
|
}
|
2015-03-13 22:22:57 +00:00
|
|
|
} else if (p.curr_is_token(get_show_tk())) {
|
|
|
|
auto pos = p.pos();
|
|
|
|
expr t = p.parse_expr();
|
|
|
|
t = p.mk_app(get_exact_tac_fn(), t, pos);
|
|
|
|
add_tac(t, pos);
|
|
|
|
} else if (p.curr_is_token(get_match_tk()) || p.curr_is_token(get_assume_tk()) ||
|
|
|
|
p.curr_is_token(get_take_tk()) || p.curr_is_token(get_fun_tk())) {
|
|
|
|
auto pos = p.pos();
|
|
|
|
expr t = p.parse_expr();
|
|
|
|
t = p.mk_app(get_sexact_tac_fn(), t, pos);
|
|
|
|
add_tac(t, pos);
|
|
|
|
} else {
|
|
|
|
auto pos = p.pos();
|
|
|
|
expr t = p.parse_tactic();
|
|
|
|
add_tac(t, pos);
|
2015-02-25 21:58:39 +00:00
|
|
|
}
|
2015-02-24 19:59:27 +00:00
|
|
|
}
|
2015-03-13 22:22:57 +00:00
|
|
|
} catch (exception & ex) {
|
|
|
|
if (end_token == get_end_tk()) {
|
|
|
|
// When the end_token is 'end', the default parser
|
|
|
|
// sync_command does not work well because it will
|
|
|
|
// interpret 'end' as a synchronization point because 'end' is also a command.
|
|
|
|
while (!p.curr_is_token(get_end_tk())) {
|
|
|
|
if (p.curr() == scanner::token_kind::Eof)
|
|
|
|
ex.rethrow();
|
|
|
|
p.next();
|
|
|
|
}
|
|
|
|
p.next(); // consume 'end'
|
|
|
|
}
|
|
|
|
ex.rethrow();
|
2014-10-15 00:12:57 +00:00
|
|
|
}
|
|
|
|
auto end_pos = p.pos();
|
|
|
|
p.next();
|
|
|
|
if (tacs.empty()) {
|
|
|
|
expr tac = get_id_tac_fn();
|
|
|
|
if (pre_tac)
|
|
|
|
tac = p.mk_app({get_and_then_tac_fn(), *pre_tac, tac}, end_pos);
|
2014-10-29 05:15:38 +00:00
|
|
|
tac = mk_begin_end_element_annotation(tac);
|
2014-10-15 00:12:57 +00:00
|
|
|
tacs.push_back(tac);
|
2014-07-03 02:30:48 +00:00
|
|
|
}
|
2014-10-15 00:12:57 +00:00
|
|
|
expr r = tacs[0];
|
2014-10-29 06:26:24 +00:00
|
|
|
if (tacs.size() == 1) {
|
|
|
|
// Hack: for having a uniform squiggle placement for unsolved goals.
|
|
|
|
// That is, the result is always of the form and_then(...).
|
|
|
|
r = p.mk_app({get_and_then_tac_fn(), r, mk_begin_end_element_annotation(get_id_tac_fn())}, end_pos);
|
|
|
|
}
|
2014-10-15 00:12:57 +00:00
|
|
|
for (unsigned i = 1; i < tacs.size(); i++) {
|
|
|
|
r = p.mk_app({get_and_then_tac_fn(), r, tacs[i]}, end_pos);
|
|
|
|
}
|
2015-02-24 19:59:27 +00:00
|
|
|
r = p.save_pos(mk_begin_end_annotation(r), end_pos);
|
|
|
|
if (nested)
|
|
|
|
return r;
|
|
|
|
else
|
|
|
|
return p.mk_by(r, end_pos);
|
2014-10-15 00:12:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static expr parse_begin_end(parser & p, unsigned, expr const *, pos_info const & pos) {
|
2015-02-24 19:59:27 +00:00
|
|
|
return parse_begin_end_core(p, pos, get_end_tk());
|
2014-07-03 02:30:48 +00:00
|
|
|
}
|
|
|
|
|
2014-09-12 01:11:58 +00:00
|
|
|
static expr parse_proof_qed_core(parser & p, pos_info const & pos) {
|
2015-03-05 19:10:34 +00:00
|
|
|
expr r = p.parse_expr();
|
2014-09-23 17:00:36 +00:00
|
|
|
p.check_token_next(get_qed_tk(), "invalid proof-qed, 'qed' expected");
|
2015-03-05 19:10:34 +00:00
|
|
|
r = p.mk_by(p.mk_app(get_exact_tac_fn(), r, pos), pos);
|
2014-09-12 01:11:58 +00:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2014-06-16 22:04:29 +00:00
|
|
|
static expr parse_proof(parser & p, expr const & prop) {
|
2014-09-23 17:00:36 +00:00
|
|
|
if (p.curr_is_token(get_from_tk())) {
|
2014-06-20 18:18:53 +00:00
|
|
|
// parse: 'from' expr
|
2014-06-16 22:04:29 +00:00
|
|
|
p.next();
|
|
|
|
return p.parse_expr();
|
2014-09-23 17:00:36 +00:00
|
|
|
} else if (p.curr_is_token(get_proof_tk())) {
|
2014-09-12 01:11:58 +00:00
|
|
|
auto pos = p.pos();
|
|
|
|
p.next();
|
|
|
|
return parse_proof_qed_core(p, pos);
|
2014-10-15 00:12:57 +00:00
|
|
|
} else if (p.curr_is_token(get_begin_tk())) {
|
|
|
|
auto pos = p.pos();
|
2015-02-24 19:59:27 +00:00
|
|
|
return parse_begin_end_core(p, pos, get_end_tk());
|
2014-09-23 17:00:36 +00:00
|
|
|
} else if (p.curr_is_token(get_by_tk())) {
|
2014-06-20 18:18:53 +00:00
|
|
|
// parse: 'by' tactic
|
2014-06-16 22:04:29 +00:00
|
|
|
auto pos = p.pos();
|
|
|
|
p.next();
|
2015-03-06 02:07:06 +00:00
|
|
|
expr t = p.parse_tactic();
|
2014-07-03 15:33:29 +00:00
|
|
|
return p.mk_by(t, pos);
|
2014-09-23 17:00:36 +00:00
|
|
|
} else if (p.curr_is_token(get_using_tk())) {
|
2014-06-20 18:18:53 +00:00
|
|
|
// parse: 'using' locals* ',' proof
|
|
|
|
auto using_pos = p.pos();
|
|
|
|
p.next();
|
|
|
|
parser::local_scope scope(p);
|
|
|
|
buffer<expr> locals;
|
2015-02-09 01:27:22 +00:00
|
|
|
buffer<expr> new_locals;
|
2014-09-23 17:00:36 +00:00
|
|
|
while (!p.curr_is_token(get_comma_tk())) {
|
2014-06-20 18:18:53 +00:00
|
|
|
auto id_pos = p.pos();
|
2015-03-06 19:33:44 +00:00
|
|
|
expr l = p.parse_id();
|
2014-06-20 18:18:53 +00:00
|
|
|
if (!is_local(l))
|
|
|
|
throw parser_error("invalid 'using' declaration for 'have', local expected", id_pos);
|
2015-02-09 01:27:22 +00:00
|
|
|
expr new_l = l;
|
|
|
|
binder_info bi = local_info(l);
|
|
|
|
if (!bi.is_contextual())
|
|
|
|
new_l = update_local(l, bi.update_contextual(true));
|
|
|
|
p.add_local(new_l);
|
2014-06-20 18:18:53 +00:00
|
|
|
locals.push_back(l);
|
2015-02-09 01:27:22 +00:00
|
|
|
new_locals.push_back(new_l);
|
2014-06-20 18:18:53 +00:00
|
|
|
}
|
|
|
|
p.next(); // consume ','
|
|
|
|
expr pr = parse_proof(p, prop);
|
|
|
|
unsigned i = locals.size();
|
|
|
|
while (i > 0) {
|
|
|
|
--i;
|
2015-02-09 01:27:22 +00:00
|
|
|
expr l = locals[i];
|
|
|
|
expr new_l = new_locals[i];
|
|
|
|
pr = p.save_pos(Fun(new_l, pr), using_pos);
|
2014-10-16 20:37:55 +00:00
|
|
|
pr = p.save_pos(mk_app(pr, l), using_pos);
|
2014-06-20 18:18:53 +00:00
|
|
|
}
|
|
|
|
return pr;
|
2014-06-16 22:04:29 +00:00
|
|
|
} else {
|
2015-02-25 21:58:39 +00:00
|
|
|
throw parser_error("invalid expression, 'by', 'begin', 'proof', 'using' or 'from' expected", p.pos());
|
2014-06-16 22:04:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-25 22:30:42 +00:00
|
|
|
static expr parse_have_core(parser & p, pos_info const & pos, optional<expr> const & prev_local, bool is_visible) {
|
2014-06-21 00:17:39 +00:00
|
|
|
auto id_pos = p.pos();
|
|
|
|
name id;
|
2014-06-20 18:18:53 +00:00
|
|
|
expr prop;
|
2014-09-23 17:00:36 +00:00
|
|
|
if (p.curr_is_token(get_visible_tk())) {
|
2014-06-20 18:18:53 +00:00
|
|
|
p.next();
|
2014-09-08 14:47:42 +00:00
|
|
|
is_visible = true;
|
2014-06-21 00:17:39 +00:00
|
|
|
id = p.mk_fresh_name();
|
|
|
|
prop = p.parse_expr();
|
|
|
|
} else if (p.curr_is_identifier()) {
|
|
|
|
id = p.get_name_val();
|
|
|
|
p.next();
|
2014-09-23 17:00:36 +00:00
|
|
|
if (p.curr_is_token(get_visible_tk())) {
|
2014-06-21 00:17:39 +00:00
|
|
|
p.next();
|
2015-02-25 22:30:42 +00:00
|
|
|
p.check_token_next(get_colon_tk(), "invalid 'have/assert' declaration, ':' expected");
|
2014-09-08 14:47:42 +00:00
|
|
|
is_visible = true;
|
|
|
|
prop = p.parse_expr();
|
2014-09-23 17:00:36 +00:00
|
|
|
} else if (p.curr_is_token(get_colon_tk())) {
|
2014-06-21 00:17:39 +00:00
|
|
|
p.next();
|
|
|
|
prop = p.parse_expr();
|
|
|
|
} else {
|
|
|
|
expr left = p.id_to_expr(id, id_pos);
|
|
|
|
id = p.mk_fresh_name();
|
|
|
|
prop = p.parse_led(left);
|
|
|
|
}
|
2014-06-20 18:18:53 +00:00
|
|
|
} else {
|
2014-06-21 00:17:39 +00:00
|
|
|
id = p.mk_fresh_name();
|
|
|
|
prop = p.parse_expr();
|
2014-06-20 18:18:53 +00:00
|
|
|
}
|
2014-06-20 18:57:01 +00:00
|
|
|
expr proof;
|
2015-03-07 03:04:09 +00:00
|
|
|
if (p.curr_is_token(get_bar_tk()) && !prev_local) {
|
|
|
|
expr fn = p.save_pos(mk_local(id, prop), id_pos);
|
|
|
|
proof = parse_local_equations(p, fn);
|
2014-06-20 18:57:01 +00:00
|
|
|
} else {
|
2015-03-07 03:04:09 +00:00
|
|
|
p.check_token_next(get_comma_tk(), "invalid 'have/assert' declaration, ',' expected");
|
|
|
|
if (prev_local) {
|
|
|
|
parser::local_scope scope(p);
|
|
|
|
p.add_local(*prev_local);
|
|
|
|
auto proof_pos = p.pos();
|
|
|
|
proof = parse_proof(p, prop);
|
|
|
|
proof = p.save_pos(Fun(*prev_local, proof), proof_pos);
|
|
|
|
proof = p.save_pos(mk_app(proof, *prev_local), proof_pos);
|
|
|
|
} else {
|
|
|
|
proof = parse_proof(p, prop);
|
|
|
|
}
|
2014-06-20 18:57:01 +00:00
|
|
|
}
|
2015-02-25 22:30:42 +00:00
|
|
|
p.check_token_next(get_comma_tk(), "invalid 'have/assert' declaration, ',' expected");
|
2014-06-16 22:04:29 +00:00
|
|
|
parser::local_scope scope(p);
|
2014-09-08 14:47:42 +00:00
|
|
|
binder_info bi = mk_contextual_info(is_visible);
|
2014-06-30 16:14:55 +00:00
|
|
|
expr l = p.save_pos(mk_local(id, prop, bi), pos);
|
|
|
|
p.add_local(l);
|
2014-06-20 18:57:01 +00:00
|
|
|
expr body;
|
2014-09-23 17:00:36 +00:00
|
|
|
if (p.curr_is_token(get_then_tk())) {
|
2014-06-20 18:57:01 +00:00
|
|
|
auto then_pos = p.pos();
|
|
|
|
p.next();
|
2015-02-25 22:30:42 +00:00
|
|
|
if (p.curr_is_token(get_assert_tk())) {
|
|
|
|
p.next();
|
|
|
|
is_visible = true;
|
|
|
|
} else {
|
|
|
|
p.check_token_next(get_have_tk(), "invalid 'then' declaration, 'have' or 'assert' expected");
|
|
|
|
is_visible = false;
|
|
|
|
}
|
|
|
|
body = parse_have_core(p, then_pos, some_expr(l), is_visible);
|
2014-06-20 18:57:01 +00:00
|
|
|
} else {
|
|
|
|
body = p.parse_expr();
|
|
|
|
}
|
2014-06-16 22:04:29 +00:00
|
|
|
// remark: mk_contextual_info(false) informs the elaborator that prop should not occur inside metavariables.
|
2014-06-20 18:57:01 +00:00
|
|
|
body = abstract(body, l);
|
2014-07-27 04:35:26 +00:00
|
|
|
expr r = p.save_pos(mk_have_annotation(p.save_pos(mk_lambda(id, prop, body, bi), pos)), pos);
|
|
|
|
return p.mk_app(r, proof, pos);
|
2014-06-16 22:04:29 +00:00
|
|
|
}
|
|
|
|
|
2014-06-20 18:57:01 +00:00
|
|
|
static expr parse_have(parser & p, unsigned, expr const *, pos_info const & pos) {
|
2015-02-25 22:30:42 +00:00
|
|
|
return parse_have_core(p, pos, none_expr(), false);
|
|
|
|
}
|
|
|
|
|
|
|
|
static expr parse_assert(parser & p, unsigned, expr const *, pos_info const & pos) {
|
|
|
|
return parse_have_core(p, pos, none_expr(), true);
|
2014-06-20 18:57:01 +00:00
|
|
|
}
|
|
|
|
|
2014-09-23 17:00:36 +00:00
|
|
|
static name * H_show = nullptr;
|
2014-06-16 22:04:29 +00:00
|
|
|
static expr parse_show(parser & p, unsigned, expr const *, pos_info const & pos) {
|
|
|
|
expr prop = p.parse_expr();
|
2015-03-07 03:04:09 +00:00
|
|
|
if (p.curr_is_token(get_bar_tk())) {
|
|
|
|
expr fn = p.save_pos(mk_local(*H_show, prop), pos);
|
|
|
|
return parse_local_equations(p, fn);
|
|
|
|
} else {
|
|
|
|
p.check_token_next(get_comma_tk(), "invalid 'show' declaration, ',' expected");
|
|
|
|
expr proof = parse_proof(p, prop);
|
|
|
|
expr b = p.save_pos(mk_lambda(*H_show, prop, Var(0)), pos);
|
|
|
|
expr r = p.mk_app(b, proof, pos);
|
|
|
|
return p.save_pos(mk_show_annotation(r), pos);
|
|
|
|
}
|
2014-06-16 22:04:29 +00:00
|
|
|
}
|
|
|
|
|
2014-07-12 05:35:24 +00:00
|
|
|
static expr parse_obtain(parser & p, unsigned, expr const *, pos_info const & pos) {
|
2015-01-24 00:50:32 +00:00
|
|
|
if (!p.env().find(get_exists_elim_name()))
|
2014-12-16 03:05:03 +00:00
|
|
|
throw parser_error("invalid use of 'obtain' expression, environment does not contain 'exists.elim' theorem", pos);
|
2014-07-22 16:43:18 +00:00
|
|
|
// exists_elim {A : Type} {P : A → Prop} {B : Prop} (H1 : ∃ x : A, P x) (H2 : ∀ (a : A) (H : P a), B)
|
2014-07-11 03:08:51 +00:00
|
|
|
buffer<expr> ps;
|
|
|
|
auto b_pos = p.pos();
|
2014-11-24 00:42:53 +00:00
|
|
|
unsigned rbp = 0;
|
|
|
|
environment env = p.parse_binders(ps, rbp);
|
2014-07-11 03:08:51 +00:00
|
|
|
unsigned num_ps = ps.size();
|
|
|
|
if (num_ps < 2)
|
2014-07-12 05:35:24 +00:00
|
|
|
throw parser_error("invalid 'obtain' expression, at least 2 binders expected", b_pos);
|
2014-09-23 17:00:36 +00:00
|
|
|
p.check_token_next(get_comma_tk(), "invalid 'obtain' expression, ',' expected");
|
|
|
|
p.check_token_next(get_from_tk(), "invalid 'obtain' expression, 'from' expected");
|
2014-07-11 03:08:51 +00:00
|
|
|
expr H1 = p.parse_expr();
|
2014-09-23 17:00:36 +00:00
|
|
|
p.check_token_next(get_comma_tk(), "invalid 'obtain' expression, ',' expected");
|
2014-07-11 03:08:51 +00:00
|
|
|
expr b = p.parse_scoped_expr(ps, env);
|
|
|
|
expr H = ps[num_ps-1];
|
2014-07-11 03:50:53 +00:00
|
|
|
name H_name = local_pp_name(H);
|
2014-07-11 03:08:51 +00:00
|
|
|
unsigned i = num_ps-1;
|
|
|
|
while (i > 1) {
|
|
|
|
--i;
|
|
|
|
expr a = ps[i];
|
2014-07-11 03:50:53 +00:00
|
|
|
expr H_aux = mk_local(p.mk_fresh_name(), H_name.append_after(i), mk_expr_placeholder(), mk_contextual_info(false));
|
2014-07-11 03:08:51 +00:00
|
|
|
expr H2 = Fun({a, H}, b);
|
2015-01-24 00:50:32 +00:00
|
|
|
b = mk_app(mk_constant(get_exists_elim_name()), H_aux, H2);
|
2014-07-11 03:08:51 +00:00
|
|
|
H = H_aux;
|
|
|
|
}
|
|
|
|
expr a = ps[0];
|
|
|
|
expr H2 = Fun({a, H}, b);
|
2015-01-24 00:50:32 +00:00
|
|
|
expr r = mk_app(mk_constant(get_exists_elim_name()), H1, H2);
|
2014-07-11 03:08:51 +00:00
|
|
|
return p.rec_save_pos(r, pos);
|
|
|
|
}
|
|
|
|
|
2014-12-04 19:13:09 +00:00
|
|
|
static expr * g_not = nullptr;
|
|
|
|
static unsigned g_then_else_prec = 45;
|
|
|
|
|
|
|
|
static expr parse_ite(parser & p, expr const & c, pos_info const & pos) {
|
2015-01-24 00:50:32 +00:00
|
|
|
if (!p.env().find(get_ite_name()))
|
2014-12-04 19:13:09 +00:00
|
|
|
throw parser_error("invalid use of 'if-then-else' expression, environment does not contain 'ite' definition", pos);
|
|
|
|
p.check_token_next(get_then_tk(), "invalid 'if-then-else' expression, 'then' expected");
|
|
|
|
expr t = p.parse_expr(g_then_else_prec);
|
|
|
|
p.check_token_next(get_else_tk(), "invalid 'if-then-else' expression, 'else' expected");
|
|
|
|
expr e = p.parse_expr(g_then_else_prec);
|
2015-01-24 00:50:32 +00:00
|
|
|
return p.save_pos(mk_app(mk_constant(get_ite_name()), c, t, e), pos);
|
2014-12-04 19:13:09 +00:00
|
|
|
}
|
|
|
|
|
2015-01-16 20:42:42 +00:00
|
|
|
static expr parse_dite(parser & p, name const & H_name, expr const & c, pos_info const & pos) {
|
2014-12-04 19:13:09 +00:00
|
|
|
p.check_token_next(get_then_tk(), "invalid 'if-then-else' expression, 'then' expected");
|
|
|
|
expr t, e;
|
|
|
|
{
|
|
|
|
parser::local_scope scope(p);
|
|
|
|
expr H = mk_local(H_name, c);
|
|
|
|
p.add_local(H);
|
2015-01-16 20:42:42 +00:00
|
|
|
auto pos = p.pos();
|
|
|
|
t = p.save_pos(Fun(H, p.parse_expr(g_then_else_prec)), pos);
|
2014-12-04 19:13:09 +00:00
|
|
|
}
|
|
|
|
p.check_token_next(get_else_tk(), "invalid 'if-then-else' expression, 'else' expected");
|
|
|
|
{
|
|
|
|
parser::local_scope scope(p);
|
|
|
|
expr H = mk_local(H_name, mk_app(*g_not, c));
|
|
|
|
p.add_local(H);
|
2015-01-16 20:42:42 +00:00
|
|
|
auto pos = p.pos();
|
|
|
|
e = p.save_pos(Fun(H, p.parse_expr(g_then_else_prec)), pos);
|
2014-12-04 19:13:09 +00:00
|
|
|
}
|
2015-01-24 00:50:32 +00:00
|
|
|
return p.save_pos(mk_app(p.save_pos(mk_constant(get_dite_name()), pos), c, t, e), pos);
|
2014-12-04 19:13:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static expr parse_if_then_else(parser & p, unsigned, expr const *, pos_info const & pos) {
|
2015-01-16 20:42:42 +00:00
|
|
|
pair<optional<name>, expr> ie = p.parse_qualified_expr();
|
|
|
|
if (ie.first)
|
|
|
|
return parse_dite(p, *ie.first, ie.second, pos);
|
|
|
|
else
|
|
|
|
return parse_ite(p, ie.second, pos);
|
2014-12-04 19:13:09 +00:00
|
|
|
}
|
|
|
|
|
2014-06-18 00:15:38 +00:00
|
|
|
static expr parse_calc_expr(parser & p, unsigned, expr const *, pos_info const &) {
|
|
|
|
return parse_calc(p);
|
|
|
|
}
|
|
|
|
|
2015-02-03 01:02:14 +00:00
|
|
|
static expr parse_rewrite_tactic_expr(parser & p, unsigned, expr const *, pos_info const & pos) {
|
|
|
|
return p.save_pos(parse_rewrite_tactic(p), pos);
|
|
|
|
}
|
|
|
|
|
2015-02-06 22:13:32 +00:00
|
|
|
static expr parse_esimp_tactic_expr(parser & p, unsigned, expr const *, pos_info const & pos) {
|
|
|
|
return p.save_pos(parse_esimp_tactic(p), pos);
|
|
|
|
}
|
|
|
|
|
2014-06-23 23:10:36 +00:00
|
|
|
static expr parse_overwrite_notation(parser & p, unsigned, expr const *, pos_info const &) {
|
|
|
|
name n = p.check_id_next("invalid '#' local notation, identifier expected");
|
|
|
|
environment env = overwrite_notation(p.env(), n);
|
|
|
|
return p.parse_scoped_expr(0, nullptr, env);
|
|
|
|
}
|
|
|
|
|
2014-06-25 19:50:47 +00:00
|
|
|
static expr parse_explicit_expr(parser & p, unsigned, expr const *, pos_info const & pos) {
|
2015-01-20 02:40:33 +00:00
|
|
|
expr e = p.parse_expr(get_Max_prec());
|
2014-08-27 23:30:30 +00:00
|
|
|
if (is_choice(e)) {
|
|
|
|
buffer<expr> new_choices;
|
|
|
|
for (unsigned i = 0; i < get_num_choices(e); i++)
|
|
|
|
new_choices.push_back(p.save_pos(mk_explicit(get_choice(e, i)), pos));
|
|
|
|
return p.save_pos(mk_choice(new_choices.size(), new_choices.data()), pos);
|
|
|
|
} else {
|
|
|
|
return p.save_pos(mk_explicit(e), pos);
|
|
|
|
}
|
2014-06-25 19:50:47 +00:00
|
|
|
}
|
|
|
|
|
2014-10-02 00:13:41 +00:00
|
|
|
static expr parse_consume_args_expr(parser & p, unsigned, expr const *, pos_info const & pos) {
|
2015-01-20 02:40:33 +00:00
|
|
|
expr e = p.parse_expr(get_Max_prec());
|
2014-10-02 00:13:41 +00:00
|
|
|
if (is_choice(e)) {
|
|
|
|
buffer<expr> new_choices;
|
|
|
|
for (unsigned i = 0; i < get_num_choices(e); i++)
|
|
|
|
new_choices.push_back(p.save_pos(mk_consume_args(get_choice(e, i)), pos));
|
|
|
|
return p.save_pos(mk_choice(new_choices.size(), new_choices.data()), pos);
|
|
|
|
} else {
|
|
|
|
return p.save_pos(mk_consume_args(e), pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-01 01:35:57 +00:00
|
|
|
static expr parse_sorry(parser & p, unsigned, expr const *, pos_info const & pos) {
|
|
|
|
return p.mk_sorry(pos);
|
|
|
|
}
|
|
|
|
|
2014-09-04 16:56:27 +00:00
|
|
|
static expr parse_rparen(parser & p, unsigned, expr const * args, pos_info const & pos) {
|
2014-09-04 18:25:41 +00:00
|
|
|
if (p.collecting_info())
|
2014-10-16 03:03:35 +00:00
|
|
|
return p.save_pos(mk_extra_info(args[0], nulltag), pos);
|
2014-09-04 18:25:41 +00:00
|
|
|
else
|
|
|
|
return args[0];
|
2014-09-03 18:52:35 +00:00
|
|
|
}
|
|
|
|
|
2014-09-12 01:11:58 +00:00
|
|
|
static expr parse_proof_qed(parser & p, unsigned, expr const *, pos_info const & pos) {
|
|
|
|
return parse_proof_qed_core(p, pos);
|
|
|
|
}
|
|
|
|
|
2014-12-10 20:35:08 +00:00
|
|
|
static expr parse_inaccessible(parser & p, unsigned, expr const * args, pos_info const & pos) {
|
|
|
|
return p.save_pos(mk_inaccessible(args[0]), pos);
|
|
|
|
}
|
|
|
|
|
2014-06-12 03:56:10 +00:00
|
|
|
parse_table init_nud_table() {
|
|
|
|
action Expr(mk_expr_action());
|
|
|
|
action Skip(mk_skip_action());
|
|
|
|
action Binders(mk_binders_action());
|
|
|
|
expr x0 = mk_var(0);
|
|
|
|
parse_table r;
|
2014-06-16 17:41:08 +00:00
|
|
|
r = r.add({transition("_", mk_ext_action(parse_placeholder))}, x0);
|
2014-10-28 00:12:25 +00:00
|
|
|
r = r.add({transition("by", mk_ext_action_core(parse_by))}, x0);
|
2014-06-16 22:04:29 +00:00
|
|
|
r = r.add({transition("have", mk_ext_action(parse_have))}, x0);
|
2015-02-25 22:30:42 +00:00
|
|
|
r = r.add({transition("assert", mk_ext_action(parse_assert))}, x0);
|
2014-06-16 22:04:29 +00:00
|
|
|
r = r.add({transition("show", mk_ext_action(parse_show))}, x0);
|
2014-07-12 05:35:24 +00:00
|
|
|
r = r.add({transition("obtain", mk_ext_action(parse_obtain))}, x0);
|
2014-12-04 19:13:09 +00:00
|
|
|
r = r.add({transition("if", mk_ext_action(parse_if_then_else))}, x0);
|
2014-09-04 16:56:27 +00:00
|
|
|
r = r.add({transition("(", Expr), transition(")", mk_ext_action(parse_rparen))}, x0);
|
2014-12-10 20:35:08 +00:00
|
|
|
r = r.add({transition("?(", Expr), transition(")", mk_ext_action(parse_inaccessible))}, x0);
|
|
|
|
r = r.add({transition("⌞", Expr), transition("⌟", mk_ext_action(parse_inaccessible))}, x0);
|
2014-06-15 05:13:25 +00:00
|
|
|
r = r.add({transition("fun", Binders), transition(",", mk_scoped_expr_action(x0))}, x0);
|
|
|
|
r = r.add({transition("Pi", Binders), transition(",", mk_scoped_expr_action(x0, 0, false))}, x0);
|
|
|
|
r = r.add({transition("Type", mk_ext_action(parse_Type))}, x0);
|
2014-06-16 16:50:34 +00:00
|
|
|
r = r.add({transition("let", mk_ext_action(parse_let_expr))}, x0);
|
2014-06-18 00:15:38 +00:00
|
|
|
r = r.add({transition("calc", mk_ext_action(parse_calc_expr))}, x0);
|
2015-02-03 01:02:14 +00:00
|
|
|
r = r.add({transition("rewrite", mk_ext_action(parse_rewrite_tactic_expr))}, x0);
|
2015-02-06 22:13:32 +00:00
|
|
|
r = r.add({transition("esimp", mk_ext_action(parse_esimp_tactic_expr))}, x0);
|
2014-06-23 23:10:36 +00:00
|
|
|
r = r.add({transition("#", mk_ext_action(parse_overwrite_notation))}, x0);
|
2014-06-25 19:50:47 +00:00
|
|
|
r = r.add({transition("@", mk_ext_action(parse_explicit_expr))}, x0);
|
2014-10-02 00:13:41 +00:00
|
|
|
r = r.add({transition("!", mk_ext_action(parse_consume_args_expr))}, x0);
|
2014-10-28 00:12:25 +00:00
|
|
|
r = r.add({transition("begin", mk_ext_action_core(parse_begin_end))}, x0);
|
2014-09-12 01:11:58 +00:00
|
|
|
r = r.add({transition("proof", mk_ext_action(parse_proof_qed))}, x0);
|
2014-08-01 01:35:57 +00:00
|
|
|
r = r.add({transition("sorry", mk_ext_action(parse_sorry))}, x0);
|
2015-01-10 18:11:13 +00:00
|
|
|
r = r.add({transition("match", mk_ext_action(parse_match))}, x0);
|
2015-01-17 01:08:48 +00:00
|
|
|
init_structure_instance_parsing_rules(r);
|
2014-06-12 03:56:10 +00:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
parse_table init_led_table() {
|
2014-06-13 22:13:32 +00:00
|
|
|
parse_table r(false);
|
2014-12-04 23:11:23 +00:00
|
|
|
r = r.add({transition("->", mk_expr_action(get_arrow_prec()-1))}, mk_arrow(Var(1), Var(1)));
|
|
|
|
r = r.add({transition("<d", mk_expr_action(get_decreasing_prec()))}, mk_decreasing(Var(1), Var(0)));
|
2014-06-12 03:56:10 +00:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
}
|
2014-09-23 17:00:36 +00:00
|
|
|
bool is_show_aux_name(name const & n) { return n == *notation::H_show; }
|
|
|
|
|
|
|
|
static parse_table * g_nud_table = nullptr;
|
|
|
|
static parse_table * g_led_table = nullptr;
|
2014-06-12 03:56:10 +00:00
|
|
|
|
|
|
|
parse_table get_builtin_nud_table() {
|
2014-09-23 17:00:36 +00:00
|
|
|
return *g_nud_table;
|
2014-06-12 03:56:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
parse_table get_builtin_led_table() {
|
2014-09-23 17:00:36 +00:00
|
|
|
return *g_led_table;
|
|
|
|
}
|
|
|
|
|
|
|
|
void initialize_builtin_exprs() {
|
|
|
|
notation::H_show = new name("H_show");
|
2015-01-24 00:50:32 +00:00
|
|
|
notation::g_not = new expr(mk_constant(get_not_name()));
|
2014-09-23 17:00:36 +00:00
|
|
|
g_nud_table = new parse_table();
|
|
|
|
*g_nud_table = notation::init_nud_table();
|
|
|
|
g_led_table = new parse_table();
|
|
|
|
*g_led_table = notation::init_led_table();
|
|
|
|
}
|
|
|
|
|
|
|
|
void finalize_builtin_exprs() {
|
|
|
|
delete g_led_table;
|
|
|
|
delete g_nud_table;
|
|
|
|
delete notation::H_show;
|
2014-12-04 19:13:09 +00:00
|
|
|
delete notation::g_not;
|
2014-06-12 03:56:10 +00:00
|
|
|
}
|
|
|
|
}
|