diff --git a/src/frontends/lean/CMakeLists.txt b/src/frontends/lean/CMakeLists.txt index ce4982f05..d4787436d 100644 --- a/src/frontends/lean/CMakeLists.txt +++ b/src/frontends/lean/CMakeLists.txt @@ -1,6 +1,7 @@ add_library(lean_frontend register_module.cpp token_table.cpp scanner.cpp parse_table.cpp parser_config.cpp parser.cpp parser_pos_provider.cpp builtin_cmds.cpp builtin_tactic_cmds.cpp -builtin_exprs.cpp interactive.cpp notation_cmd.cpp calc.cpp) +builtin_exprs.cpp interactive.cpp notation_cmd.cpp calc.cpp +decl_cmds.cpp util.cpp) target_link_libraries(lean_frontend ${LEAN_LIBS}) diff --git a/src/frontends/lean/builtin_cmds.cpp b/src/frontends/lean/builtin_cmds.cpp index c389c1429..2319e532c 100644 --- a/src/frontends/lean/builtin_cmds.cpp +++ b/src/frontends/lean/builtin_cmds.cpp @@ -11,20 +11,15 @@ Author: Leonardo de Moura #include "library/io_state_stream.h" #include "library/scoped_ext.h" #include "library/aliases.h" -#include "library/private.h" #include "library/locals.h" +#include "frontends/lean/util.h" #include "frontends/lean/parser.h" #include "frontends/lean/calc.h" #include "frontends/lean/notation_cmd.h" +#include "frontends/lean/decl_cmds.h" namespace lean { static name g_raw("raw"); -static name g_llevel_curly(".{"); -static name g_rcurly("}"); -static name g_colon(":"); -static name g_assign(":="); -static name g_private("[private]"); -static name g_inline("[inline]"); static name g_true("true"); static name g_false("false"); static name g_options("options"); @@ -38,285 +33,6 @@ static name g_decls("decls"); static name g_hiding("hiding"); static name g_renaming("renaming"); -static void check_atomic(name const & n) { - if (!n.is_atomic()) - throw exception(sstream() << "invalid declaration name '" << n << "', identifier must be atomic"); -} - -environment universe_cmd(parser & p) { - 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 = module::add_universe(env, 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 & ps) { - if (p.curr_is_token(g_llevel_curly)) { - p.next(); - 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); - } - p.next(); - } -} - -static void update_parameters(buffer & 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); - }); -} - -static environment declare_var(parser & p, environment env, - name const & n, level_param_names const & ls, expr const & type, - bool is_axiom, binder_info const & bi, pos_info const & pos) { - if (in_section(p.env())) { - p.add_local_expr(n, p.save_pos(mk_local(n, type), pos), bi); - return env; - } else { - name const & ns = get_namespace(env); - name full_n = ns + n; - if (is_axiom) - env = module::add(env, check(env, mk_axiom(full_n, ls, type))); - else - env = module::add(env, check(env, mk_var_decl(full_n, ls, type))); - if (!ns.is_anonymous()) - env = add_alias(env, n, mk_constant(full_n)); - return env; - } -} - -static environment variable_cmd_core(parser & p, bool is_axiom, binder_info const & bi) { - auto pos = p.pos(); - name n = p.check_id_next("invalid declaration, identifier expected"); - check_atomic(n); - buffer ls_buffer; - 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()); - optional scope1; - if (!in_section(p.env())) - scope1.emplace(p); - parse_univ_params(p, ls_buffer); - parser::param_universe_scope scope2(p); - expr type; - if (!p.curr_is_token(g_colon)) { - buffer ps; - auto lenv = p.parse_binders(ps); - p.check_token_next(g_colon, "invalid declaration, ':' expected"); - type = p.parse_scoped_expr(ps, lenv); - type = p.pi_abstract(ps, type); - } else { - p.next(); - type = p.parse_expr(); - } - 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.elaborate(type, ls); - return declare_var(p, p.env(), n, ls, type, is_axiom, bi, pos); -} -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()); -} - -static environment variables_cmd_core(parser & p, bool is_axiom, binder_info const & bi) { - auto pos = p.pos(); - buffer ids; - while (!p.curr_is_token(g_colon)) { - name id = p.check_id_next("invalid parameters declaration, identifier expected"); - check_atomic(id); - ids.push_back(id); - } - p.next(); - optional scope1; - if (!in_section(p.env())) - scope1.emplace(p); - parser::param_universe_scope scope2(p); - expr type = p.parse_expr(); - level_param_names ls = to_level_param_names(collect_univ_params(type)); - type = p.elaborate(type, ls); - environment env = p.env(); - for (auto id : ids) - env = declare_var(p, env, id, ls, type, is_axiom, bi, pos); - return env; -} -environment variables_cmd(parser & p) { - return variables_cmd_core(p, false, binder_info()); -} -environment implicit_variables_cmd(parser & p) { - check_in_section(p); - return variables_cmd_core(p, false, mk_implicit_binder_info()); -} -environment cast_variables_cmd(parser & p) { - check_in_section(p); - return variables_cmd_core(p, false, mk_cast_binder_info()); -} - -// Collect local (section) constants occurring in type and value, sort them, and store in section_ps -static void collect_section_locals(expr const & type, expr const & value, parser const & p, buffer & section_ps) { - name_set ls = collect_locals(type, collect_locals(value)); - ls.for_each([&](name const & n) { - section_ps.push_back(*p.get_local(n)); - }); - std::sort(section_ps.begin(), section_ps.end(), [&](parameter const & p1, parameter const & p2) { - return p.get_local_index(mlocal_name(p1.m_local)) < p.get_local_index(mlocal_name(p2.m_local)); - }); -} - -static void parse_modifiers(parser & p, bool & is_private, bool & is_opaque) { - while (true) { - if (p.curr_is_token(g_private)) { - is_private = true; - p.next(); - } else if (p.curr_is_token(g_inline)) { - is_opaque = false; - p.next(); - } else { - break; - } - } -} - -// Wrap \c e with the "explicit macro", the idea is to inform the elaborator -// preprocessor, that we do not need create metavariables for implicit arguments -static expr mark_explicit(expr const & e) { - // TODO(Leo) - return e; -} - -environment definition_cmd_core(parser & p, bool is_theorem, bool is_opaque) { - bool is_private = false; - parse_modifiers(p, is_private, is_opaque); - if (is_theorem && !is_opaque) - throw exception("invalid theorem declaration, theorems cannot be transparent"); - name n = p.check_id_next("invalid declaration, identifier expected"); - check_atomic(n); - environment env = p.env(); - name real_n; // real name for this declaration - if (is_private) { - auto env_n = add_private_name(env, n, optional(hash(p.pos().first, p.pos().second))); - env = env_n.first; - real_n = env_n.second; - } else { - name const & ns = get_namespace(env); - real_n = ns + n; - } - buffer ls_buffer; - expr type, value; - level_param_names ls; - { - parser::local_scope scope1(p); - parse_univ_params(p, ls_buffer); - if (!p.curr_is_token(g_colon)) { - buffer ps; - optional lenv; - { - parser::param_universe_scope scope2(p); - lenv = p.parse_binders(ps); - p.check_token_next(g_colon, "invalid declaration, ':' expected"); - type = p.parse_scoped_expr(ps, *lenv); - } - p.check_token_next(g_assign, "invalid declaration, ':=' expected"); - value = p.parse_scoped_expr(ps, *lenv); - type = p.pi_abstract(ps, type); - value = p.lambda_abstract(ps, value); - } else { - p.next(); - { - parser::param_universe_scope scope2(p); - type = p.parse_expr(); - } - p.check_token_next(g_assign, "invalid declaration, ':=' expected"); - value = p.parse_expr(); - } - update_parameters(ls_buffer, collect_univ_params(value, collect_univ_params(type)), p); - ls = to_list(ls_buffer.begin(), ls_buffer.end()); - } - if (in_section(env)) { - buffer section_ps; - collect_section_locals(type, value, p, section_ps); - type = p.pi_abstract(section_ps, type); - value = p.lambda_abstract(section_ps, value); - buffer section_ls_buffer; - for (name const & l : ls) { - if (p.get_local_level_index(l)) - section_ls_buffer.push_back(mk_param_univ(l)); - else - break; - } - levels section_ls = to_list(section_ls_buffer.begin(), section_ls_buffer.end()); - buffer section_args; - for (auto const & p : section_ps) - section_args.push_back(p.m_local); - expr ref = mk_app(mark_explicit(mk_constant(real_n, section_ls)), section_args); - p.add_local_expr(n, ref); - } else { - if (real_n != n) - env = add_alias(env, n, mk_constant(real_n)); - } - if (is_theorem) { - // TODO(Leo): delay theorems - auto type_value = p.elaborate(type, value, ls); - type = type_value.first; - value = type_value.second; - env = module::add(env, check(env, mk_theorem(real_n, ls, type, value))); - } else { - auto type_value = p.elaborate(type, value, ls); - type = type_value.first; - value = type_value.second; - env = module::add(env, check(env, mk_definition(env, real_n, ls, type, value, is_opaque))); - } - return env; -} -environment definition_cmd(parser & p) { - return definition_cmd_core(p, false, true); -} -environment abbreviation_cmd(parser & p) { - return definition_cmd_core(p, false, false); -} -environment theorem_cmd(parser & p) { - return definition_cmd_core(p, true, true); -} - environment print_cmd(parser & p) { if (p.curr() == scanner::token_kind::String) { p.regular_stream() << p.get_str_val() << endl; @@ -495,23 +211,12 @@ cmd_table init_cmd_table() { add_cmd(r, cmd_info("set_option", "set configuration option", set_option_cmd)); add_cmd(r, cmd_info("exit", "exit", exit_cmd)); 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("variables", "declare new parameters", variables_cmd)); - add_cmd(r, cmd_info("{variables}", "declare new implict parameters", implicit_variables_cmd)); - add_cmd(r, cmd_info("[variables]", "declare new cast parameters", cast_variables_cmd)); - add_cmd(r, cmd_info("definition", "add new definition", definition_cmd)); - add_cmd(r, cmd_info("abbreviation", "add new abbreviation (aka transparent definition)", abbreviation_cmd)); - add_cmd(r, cmd_info("theorem", "add new theorem", theorem_cmd)); add_cmd(r, cmd_info("check", "type check given expression, and display its type", check_cmd)); add_cmd(r, cmd_info("#setline", "modify the current line number, it only affects error/report messages", set_line_cmd)); + register_decl_cmds(r); register_notation_cmds(r); register_calc_cmds(r); return r; diff --git a/src/frontends/lean/calc.cpp b/src/frontends/lean/calc.cpp index 8bb771ae8..ee56a1d4b 100644 --- a/src/frontends/lean/calc.cpp +++ b/src/frontends/lean/calc.cpp @@ -18,6 +18,7 @@ Author: Leonardo de Moura #include "library/choice.h" #include "library/placeholder.h" #include "frontends/lean/parser.h" +#include "frontends/lean/util.h" namespace lean { struct calc_ext : public environment_extension { @@ -211,7 +212,7 @@ static void decode_expr(expr const & e, buffer & preds, pos_info cons // Create (op _ _ ... _) static expr mk_op_fn(parser & p, name const & op, unsigned num_placeholders, pos_info const & pos) { - expr r = p.save_pos(mk_constant(op), pos); + expr r = p.save_pos(mark_explicit(mk_constant(op)), pos); while (num_placeholders > 0) { num_placeholders--; r = p.mk_app(r, p.save_pos(mk_expr_placeholder(), pos), pos); diff --git a/src/frontends/lean/decl_cmds.cpp b/src/frontends/lean/decl_cmds.cpp new file mode 100644 index 000000000..00ffe8811 --- /dev/null +++ b/src/frontends/lean/decl_cmds.cpp @@ -0,0 +1,301 @@ +/* +Copyright (c) 2014 Microsoft Corporation. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. + +Author: Leonardo de Moura +*/ +#include +#include "util/sstream.h" +#include "kernel/type_checker.h" +#include "library/scoped_ext.h" +#include "library/aliases.h" +#include "library/private.h" +#include "library/locals.h" +#include "frontends/lean/parser.h" +#include "frontends/lean/util.h" + +namespace lean { +static name g_llevel_curly(".{"); +static name g_rcurly("}"); +static name g_colon(":"); +static name g_assign(":="); +static name g_private("[private]"); +static name g_inline("[inline]"); + +environment universe_cmd(parser & p) { + 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 = module::add_universe(env, full_n); + if (!ns.is_anonymous()) + env = add_alias(env, n, mk_global_univ(full_n)); + } + return env; +} + +void parse_univ_params(parser & p, buffer & ps) { + if (p.curr_is_token(g_llevel_curly)) { + p.next(); + 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); + } + p.next(); + } +} + +void update_parameters(buffer & 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); + }); +} + +static environment declare_var(parser & p, environment env, + name const & n, level_param_names const & ls, expr const & type, + bool is_axiom, binder_info const & bi, pos_info const & pos) { + if (in_section(p.env())) { + p.add_local_expr(n, p.save_pos(mk_local(n, type), pos), bi); + return env; + } else { + name const & ns = get_namespace(env); + name full_n = ns + n; + if (is_axiom) + env = module::add(env, check(env, mk_axiom(full_n, ls, type))); + else + env = module::add(env, check(env, mk_var_decl(full_n, ls, type))); + if (!ns.is_anonymous()) + env = add_alias(env, n, mk_constant(full_n)); + return env; + } +} + +environment variable_cmd_core(parser & p, bool is_axiom, binder_info const & bi) { + auto pos = p.pos(); + name n = p.check_id_next("invalid declaration, identifier expected"); + check_atomic(n); + buffer ls_buffer; + 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()); + optional scope1; + if (!in_section(p.env())) + scope1.emplace(p); + parse_univ_params(p, ls_buffer); + parser::param_universe_scope scope2(p); + expr type; + if (!p.curr_is_token(g_colon)) { + buffer ps; + auto lenv = p.parse_binders(ps); + p.check_token_next(g_colon, "invalid declaration, ':' expected"); + type = p.parse_scoped_expr(ps, lenv); + type = p.pi_abstract(ps, type); + } else { + p.next(); + type = p.parse_expr(); + } + 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.elaborate(type, ls); + return declare_var(p, p.env(), n, ls, type, is_axiom, bi, pos); +} +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()); +} + +// Collect local (section) constants occurring in type and value, sort them, and store in section_ps +void collect_section_locals(expr const & type, expr const & value, parser const & p, buffer & section_ps) { + name_set ls = collect_locals(type, collect_locals(value)); + ls.for_each([&](name const & n) { + section_ps.push_back(*p.get_local(n)); + }); + std::sort(section_ps.begin(), section_ps.end(), [&](parameter const & p1, parameter const & p2) { + return p.get_local_index(mlocal_name(p1.m_local)) < p.get_local_index(mlocal_name(p2.m_local)); + }); +} + +static void parse_modifiers(parser & p, bool & is_private, bool & is_opaque) { + while (true) { + if (p.curr_is_token(g_private)) { + is_private = true; + p.next(); + } else if (p.curr_is_token(g_inline)) { + is_opaque = false; + p.next(); + } else { + break; + } + } +} + +environment definition_cmd_core(parser & p, bool is_theorem, bool is_opaque) { + bool is_private = false; + parse_modifiers(p, is_private, is_opaque); + if (is_theorem && !is_opaque) + throw exception("invalid theorem declaration, theorems cannot be transparent"); + name n = p.check_id_next("invalid declaration, identifier expected"); + check_atomic(n); + environment env = p.env(); + name real_n; // real name for this declaration + if (is_private) { + auto env_n = add_private_name(env, n, optional(hash(p.pos().first, p.pos().second))); + env = env_n.first; + real_n = env_n.second; + } else { + name const & ns = get_namespace(env); + real_n = ns + n; + } + buffer ls_buffer; + expr type, value; + level_param_names ls; + { + parser::local_scope scope1(p); + parse_univ_params(p, ls_buffer); + if (!p.curr_is_token(g_colon)) { + buffer ps; + optional lenv; + { + parser::param_universe_scope scope2(p); + lenv = p.parse_binders(ps); + p.check_token_next(g_colon, "invalid declaration, ':' expected"); + type = p.parse_scoped_expr(ps, *lenv); + } + p.check_token_next(g_assign, "invalid declaration, ':=' expected"); + value = p.parse_scoped_expr(ps, *lenv); + type = p.pi_abstract(ps, type); + value = p.lambda_abstract(ps, value); + } else { + p.next(); + { + parser::param_universe_scope scope2(p); + type = p.parse_expr(); + } + p.check_token_next(g_assign, "invalid declaration, ':=' expected"); + value = p.parse_expr(); + } + update_parameters(ls_buffer, collect_univ_params(value, collect_univ_params(type)), p); + ls = to_list(ls_buffer.begin(), ls_buffer.end()); + } + if (in_section(env)) { + buffer section_ps; + collect_section_locals(type, value, p, section_ps); + type = p.pi_abstract(section_ps, type); + value = p.lambda_abstract(section_ps, value); + buffer section_ls_buffer; + for (name const & l : ls) { + if (p.get_local_level_index(l)) + section_ls_buffer.push_back(mk_param_univ(l)); + else + break; + } + levels section_ls = to_list(section_ls_buffer.begin(), section_ls_buffer.end()); + buffer section_args; + for (auto const & p : section_ps) + section_args.push_back(p.m_local); + expr ref = mk_app(mark_explicit(mk_constant(real_n, section_ls)), section_args); + p.add_local_expr(n, ref); + } else { + if (real_n != n) + env = add_alias(env, n, mk_constant(real_n)); + } + if (is_theorem) { + // TODO(Leo): delay theorems + auto type_value = p.elaborate(type, value, ls); + type = type_value.first; + value = type_value.second; + env = module::add(env, check(env, mk_theorem(real_n, ls, type, value))); + } else { + auto type_value = p.elaborate(type, value, ls); + type = type_value.first; + value = type_value.second; + env = module::add(env, check(env, mk_definition(env, real_n, ls, type, value, is_opaque))); + } + return env; +} +environment definition_cmd(parser & p) { + return definition_cmd_core(p, false, true); +} +environment abbreviation_cmd(parser & p) { + return definition_cmd_core(p, false, false); +} +environment theorem_cmd(parser & p) { + return definition_cmd_core(p, true, true); +} + +static environment variables_cmd_core(parser & p, bool is_axiom, binder_info const & bi) { + auto pos = p.pos(); + buffer ids; + while (!p.curr_is_token(g_colon)) { + name id = p.check_id_next("invalid parameters declaration, identifier expected"); + check_atomic(id); + ids.push_back(id); + } + p.next(); + optional scope1; + if (!in_section(p.env())) + scope1.emplace(p); + parser::param_universe_scope scope2(p); + expr type = p.parse_expr(); + level_param_names ls = to_level_param_names(collect_univ_params(type)); + type = p.elaborate(type, ls); + environment env = p.env(); + for (auto id : ids) + env = declare_var(p, env, id, ls, type, is_axiom, bi, pos); + return env; +} +environment variables_cmd(parser & p) { + return variables_cmd_core(p, false, binder_info()); +} +environment implicit_variables_cmd(parser & p) { + check_in_section(p); + return variables_cmd_core(p, false, mk_implicit_binder_info()); +} +environment cast_variables_cmd(parser & p) { + check_in_section(p); + return variables_cmd_core(p, false, mk_cast_binder_info()); +} + +void register_decl_cmds(cmd_table & r) { + add_cmd(r, cmd_info("universe", "declare a global universe level", universe_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("definition", "add new definition", definition_cmd)); + add_cmd(r, cmd_info("abbreviation", "add new abbreviation (aka transparent definition)", abbreviation_cmd)); + add_cmd(r, cmd_info("theorem", "add new theorem", theorem_cmd)); + add_cmd(r, cmd_info("variables", "declare new parameters", variables_cmd)); + add_cmd(r, cmd_info("{variables}", "declare new implict parameters", implicit_variables_cmd)); + add_cmd(r, cmd_info("[variables]", "declare new cast parameters", cast_variables_cmd)); +} +} diff --git a/src/frontends/lean/decl_cmds.h b/src/frontends/lean/decl_cmds.h new file mode 100644 index 000000000..2ee286d34 --- /dev/null +++ b/src/frontends/lean/decl_cmds.h @@ -0,0 +1,17 @@ +/* +Copyright (c) 2014 Microsoft Corporation. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. + +Author: Leonardo de Moura +*/ +#pragma once +#include "util/buffer.h" +#include "kernel/expr.h" +#include "frontends/lean/cmd_table.h" +namespace lean { +class parser; +void parse_univ_params(parser & p, buffer & ps); +void update_parameters(buffer & ls_buffer, name_set const & found, parser const & p); +void collect_section_locals(expr const & type, expr const & value, parser const & p, buffer & section_ps); +void register_decl_cmds(cmd_table & r); +} diff --git a/src/frontends/lean/util.cpp b/src/frontends/lean/util.cpp new file mode 100644 index 000000000..0f2d77431 --- /dev/null +++ b/src/frontends/lean/util.cpp @@ -0,0 +1,28 @@ +/* +Copyright (c) 2014 Microsoft Corporation. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. + +Author: Leonardo de Moura +*/ +#include "util/sstream.h" +#include "library/scoped_ext.h" +#include "frontends/lean/parser.h" + +namespace lean { +void check_atomic(name const & n) { + if (!n.is_atomic()) + throw exception(sstream() << "invalid declaration name '" << n << "', identifier must be atomic"); +} + +void check_in_section(parser const & p) { + if (!in_section(p.env())) + throw exception(sstream() << "invalid command, it must be used in a section"); +} + +// Wrap \c e with the "explicit macro", the idea is to inform the elaborator +// preprocessor, that we do not need create metavariables for implicit arguments +expr mark_explicit(expr const & e) { + // TODO(Leo) + return e; +} +} diff --git a/src/frontends/lean/util.h b/src/frontends/lean/util.h new file mode 100644 index 000000000..58c5e1a51 --- /dev/null +++ b/src/frontends/lean/util.h @@ -0,0 +1,14 @@ +/* +Copyright (c) 2014 Microsoft Corporation. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. + +Author: Leonardo de Moura +*/ +#pragma once +#include "kernel/expr.h" +namespace lean { +class parser; +void check_atomic(name const & n); +void check_in_section(parser const & p); +expr mark_explicit(expr const & e); +}