2014-06-11 00:02:06 +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-06-13 22:13:32 +00:00
|
|
|
#include <algorithm>
|
2014-06-13 18:24:26 +00:00
|
|
|
#include "util/sstream.h"
|
2014-06-13 22:13:32 +00:00
|
|
|
#include "kernel/type_checker.h"
|
2014-06-11 18:52:58 +00:00
|
|
|
#include "library/io_state_stream.h"
|
2014-06-13 18:24:26 +00:00
|
|
|
#include "library/scoped_ext.h"
|
|
|
|
#include "library/aliases.h"
|
2014-06-13 22:13:32 +00:00
|
|
|
#include "library/locals.h"
|
2014-06-11 18:44:16 +00:00
|
|
|
#include "frontends/lean/parser.h"
|
2014-06-11 00:02:06 +00:00
|
|
|
|
|
|
|
namespace lean {
|
2014-06-12 03:56:10 +00:00
|
|
|
static name g_raw("raw");
|
2014-06-13 22:13:32 +00:00
|
|
|
static name g_llevel_curly(".{");
|
|
|
|
static name g_rcurly("}");
|
|
|
|
static name g_colon(":");
|
|
|
|
|
2014-06-13 18:24:26 +00:00
|
|
|
static void check_atomic(name const & n) {
|
|
|
|
if (!n.is_atomic())
|
|
|
|
throw exception(sstream() << "invalid declaration name '" << n << "', identifier must be atomic");
|
|
|
|
}
|
2014-06-12 16:08:38 +00:00
|
|
|
|
|
|
|
environment universe_cmd(parser & p) {
|
2014-06-13 22:13:32 +00:00
|
|
|
name n = p.check_id_next("invalid universe declaration, identifier expected");
|
|
|
|
check_atomic(n);
|
|
|
|
environment env = p.env();
|
|
|
|
if (in_section(env)) {
|
|
|
|
p.add_local_level(n, mk_param_univ(n));
|
|
|
|
} else {
|
|
|
|
name const & ns = get_namespace(env);
|
|
|
|
name full_n = ns + n;
|
|
|
|
env = env.add_universe(full_n);
|
|
|
|
if (!ns.is_anonymous())
|
|
|
|
env = add_alias(env, n, mk_global_univ(full_n));
|
|
|
|
}
|
|
|
|
return env;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void check_in_section(parser const & p) {
|
|
|
|
if (!in_section(p.env()))
|
|
|
|
throw exception(sstream() << "invalid command, it must be used in a section");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void parse_univ_params(parser & p, buffer<name> & ps) {
|
|
|
|
if (p.curr_is_token(g_llevel_curly)) {
|
2014-06-12 16:08:38 +00:00
|
|
|
p.next();
|
2014-06-13 22:13:32 +00:00
|
|
|
while (!p.curr_is_token(g_rcurly)) {
|
|
|
|
name l = p.check_id_next("invalid universe parameter, identifier expected");
|
|
|
|
p.add_local_level(l, mk_param_univ(l));
|
|
|
|
ps.push_back(l);
|
2014-06-13 18:24:26 +00:00
|
|
|
}
|
2014-06-13 22:13:32 +00:00
|
|
|
p.next();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct local_scope_if_not_section {
|
|
|
|
parser & m_p;
|
|
|
|
local_scope_if_not_section(parser & p):m_p(p) {
|
|
|
|
if (!in_section(p.env()))
|
|
|
|
p.push_local_scope();
|
|
|
|
}
|
|
|
|
~local_scope_if_not_section() {
|
|
|
|
if (!in_section(m_p.env()))
|
|
|
|
m_p.pop_local_scope();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
static void update_parameters(buffer<name> & ls_buffer, name_set const & found, parser const & p) {
|
|
|
|
unsigned old_sz = ls_buffer.size();
|
|
|
|
found.for_each([&](name const & n) {
|
|
|
|
if (std::find(ls_buffer.begin(), ls_buffer.begin() + old_sz, n) == ls_buffer.begin() + old_sz)
|
|
|
|
ls_buffer.push_back(n);
|
|
|
|
});
|
|
|
|
std::sort(ls_buffer.begin(), ls_buffer.end(), [&](name const & n1, name const & n2) {
|
|
|
|
return *p.get_local_level_index(n1) < *p.get_local_level_index(n2);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
environment variable_cmd_core(parser & p, bool is_axiom, binder_info const & bi) {
|
|
|
|
name n = p.check_id_next("invalid declaration, identifier expected");
|
|
|
|
check_atomic(n);
|
|
|
|
buffer<name> ls_buffer;
|
|
|
|
buffer<parameter> ps;
|
|
|
|
if (p.curr_is_token(g_llevel_curly) && in_section(p.env()))
|
|
|
|
throw parser_error("invalid declaration, axioms/parameters occurring in sections cannot be universe polymorphic", p.pos());
|
|
|
|
local_scope_if_not_section scope(p);
|
|
|
|
parse_univ_params(p, ls_buffer);
|
|
|
|
p.set_type_use_placeholder(false);
|
|
|
|
if (!p.curr_is_token(g_colon))
|
|
|
|
p.parse_binders(ps);
|
|
|
|
p.check_token_next(g_colon, "invalid declaration, ':' expected");
|
|
|
|
expr type = p.parse_scoped_expr(ps);
|
|
|
|
level_param_names ls;
|
|
|
|
if (in_section(p.env())) {
|
|
|
|
ls = to_level_param_names(collect_univ_params(type));
|
|
|
|
} else {
|
|
|
|
update_parameters(ls_buffer, collect_univ_params(type), p);
|
|
|
|
ls = to_list(ls_buffer.begin(), ls_buffer.end());
|
|
|
|
}
|
|
|
|
type = p.pi_abstract(ps, type);
|
|
|
|
type = p.elaborate(type, ls);
|
|
|
|
if (in_section(p.env())) {
|
|
|
|
p.add_local_expr(n, mk_local(n, n, type), bi);
|
|
|
|
return p.env();
|
2014-06-12 16:08:38 +00:00
|
|
|
} else {
|
2014-06-13 22:13:32 +00:00
|
|
|
environment env = p.env();
|
|
|
|
name const & ns = get_namespace(env);
|
|
|
|
name full_n = ns + n;
|
|
|
|
if (is_axiom)
|
|
|
|
env = env.add(check(env, mk_axiom(full_n, ls, type)));
|
|
|
|
else
|
|
|
|
env = env.add(check(env, mk_var_decl(full_n, ls, type)));
|
|
|
|
if (!ns.is_anonymous())
|
|
|
|
env = add_alias(env, n, mk_constant(full_n));
|
|
|
|
return env;
|
2014-06-12 16:08:38 +00:00
|
|
|
}
|
|
|
|
}
|
2014-06-13 22:13:32 +00:00
|
|
|
environment variable_cmd(parser & p) {
|
|
|
|
return variable_cmd_core(p, false, binder_info());
|
|
|
|
}
|
|
|
|
environment axiom_cmd(parser & p) {
|
|
|
|
return variable_cmd_core(p, true, binder_info());
|
|
|
|
}
|
|
|
|
environment implicit_variable_cmd(parser & p) {
|
|
|
|
check_in_section(p);
|
|
|
|
return variable_cmd_core(p, false, mk_implicit_binder_info());
|
|
|
|
}
|
|
|
|
environment implicit_axiom_cmd(parser & p) {
|
|
|
|
check_in_section(p);
|
|
|
|
return variable_cmd_core(p, true, mk_implicit_binder_info());
|
|
|
|
}
|
|
|
|
environment cast_variable_cmd(parser & p) {
|
|
|
|
check_in_section(p);
|
|
|
|
return variable_cmd_core(p, false, mk_cast_binder_info());
|
|
|
|
}
|
2014-06-12 16:08:38 +00:00
|
|
|
|
2014-06-11 18:52:58 +00:00
|
|
|
environment print_cmd(parser & p) {
|
|
|
|
if (p.curr() == scanner::token_kind::String) {
|
2014-06-12 03:56:10 +00:00
|
|
|
p.regular_stream() << p.get_str_val() << "\n";
|
2014-06-11 18:52:58 +00:00
|
|
|
p.next();
|
2014-06-12 03:56:10 +00:00
|
|
|
} else if (p.curr_is_token(g_raw)) {
|
|
|
|
p.next();
|
|
|
|
expr e = p.parse_expr();
|
|
|
|
p.regular_stream() << e << "\n";
|
2014-06-11 18:52:58 +00:00
|
|
|
} else {
|
|
|
|
throw parser_error("invalid print command", p.pos());
|
|
|
|
}
|
|
|
|
return p.env();
|
|
|
|
}
|
|
|
|
|
2014-06-13 18:24:26 +00:00
|
|
|
environment section_cmd(parser & p) {
|
|
|
|
p.push_local_scope();
|
|
|
|
return push_scope(p.env(), p.ios());
|
|
|
|
}
|
|
|
|
|
|
|
|
environment namespace_cmd(parser & p) {
|
2014-06-13 22:13:32 +00:00
|
|
|
name n = p.check_id_next("invalid namespace declaration, identifier expected");
|
|
|
|
check_atomic(n);
|
|
|
|
return push_scope(p.env(), p.ios(), n);
|
2014-06-13 18:24:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
environment end_scoped_cmd(parser & p) {
|
|
|
|
if (in_section(p.env()))
|
|
|
|
p.pop_local_scope();
|
|
|
|
return pop_scope(p.env());
|
|
|
|
}
|
|
|
|
|
2014-06-13 22:13:32 +00:00
|
|
|
environment check_cmd(parser & p) {
|
|
|
|
expr e = p.parse_expr();
|
|
|
|
level_param_names ls = to_level_param_names(collect_univ_params(e));
|
|
|
|
e = p.elaborate(e, ls);
|
|
|
|
expr type = type_checker(p.env()).check(e, ls);
|
|
|
|
p.regular_stream() << e << " : " << type << endl;
|
|
|
|
return p.env();
|
|
|
|
}
|
|
|
|
|
2014-06-11 18:52:58 +00:00
|
|
|
cmd_table init_cmd_table() {
|
|
|
|
cmd_table r;
|
2014-06-13 22:13:32 +00:00
|
|
|
add_cmd(r, cmd_info("print", "print a string", print_cmd));
|
|
|
|
add_cmd(r, cmd_info("universe", "declare a global universe level", universe_cmd));
|
|
|
|
add_cmd(r, cmd_info("section", "open a new section", section_cmd));
|
|
|
|
add_cmd(r, cmd_info("namespace", "open a new namespace", namespace_cmd));
|
|
|
|
add_cmd(r, cmd_info("end", "close the current namespace/section", end_scoped_cmd));
|
|
|
|
add_cmd(r, cmd_info("variable", "declare a new parameter", variable_cmd));
|
|
|
|
add_cmd(r, cmd_info("{variable}", "declare a new implict parameter", implicit_variable_cmd));
|
|
|
|
add_cmd(r, cmd_info("[variable]", "declare a new cast parameter", cast_variable_cmd));
|
|
|
|
add_cmd(r, cmd_info("axiom", "declare a new axiom", axiom_cmd));
|
|
|
|
add_cmd(r, cmd_info("{axiom}", "declare a new implicit axiom", implicit_axiom_cmd));
|
|
|
|
add_cmd(r, cmd_info("check", "type check given expression, and display its type", check_cmd));
|
2014-06-11 18:52:58 +00:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2014-06-11 00:02:06 +00:00
|
|
|
cmd_table get_builtin_cmds() {
|
2014-06-11 18:52:58 +00:00
|
|
|
static optional<cmd_table> r;
|
|
|
|
if (!r)
|
|
|
|
r = init_cmd_table();
|
|
|
|
return *r;
|
2014-06-11 00:02:06 +00:00
|
|
|
}
|
|
|
|
}
|