feat(library,frontends/lean): add basic doc string support

This commit is contained in:
Leonardo de Moura 2016-11-25 10:42:51 -08:00
parent a009541b6e
commit 97dd2f34d5
18 changed files with 328 additions and 14 deletions

View file

@ -345,6 +345,9 @@ meta constant generalize_core : transparency → expr → name → tactic unit
meta constant instantiate_mvars : expr → tactic expr
/- Add the given declaration to the environment -/
meta constant add_decl : declaration → tactic unit
/- (doc_string env d) return the doc string for d (if available) -/
meta constant doc_string : name → tactic string
meta constant add_doc_string : name → string → tactic unit
/- (set_basic_attribute_core attr_name c_name persistent prio) set attribute attr_name for constant c_name with the given priority.
If the priority is none, then use default -/
meta constant set_basic_attribute_core : name → name → bool → option nat → tactic unit

View file

@ -28,6 +28,7 @@ Author: Leonardo de Moura
#include "library/type_context.h"
#include "library/reducible.h"
#include "library/typed_expr.h"
#include "library/documentation.h"
#include "library/vm/vm.h"
#include "library/vm/vm_string.h"
#include "library/compiler/vm_compiler.h"
@ -107,6 +108,9 @@ environment namespace_cmd(parser & p) {
unsigned old_export_decls_sz = length(get_active_export_decls(p.env()));
environment env = push_scope(p.env(), p.ios(), scope_kind::Namespace, n);
env = activate_export_decls(env, get_namespace(env));
if (auto doc = p.get_doc_string()) {
env = add_doc_string(env, get_namespace(env), *doc);
}
return replay_export_decls_core(env, p.ios(), old_export_decls_sz);
}

View file

@ -22,6 +22,7 @@ Author: Leonardo de Moura
#include "library/locals.h"
#include "library/explicit.h"
#include "library/unfold_macros.h"
#include "library/documentation.h"
#include "frontends/lean/parser.h"
#include "frontends/lean/decl_util.h"
#include "frontends/lean/util.h"
@ -125,6 +126,8 @@ static environment declare_var(parser & p, environment env,
bool is_trusted = !modifiers.m_is_meta;
env = module::add(env, check(env, mk_constant_assumption(full_n, ls, new_type, is_trusted)));
}
if (auto doc = p.get_doc_string())
env = add_doc_string(env, full_n, *doc);
if (!ns.is_anonymous()) {
if (modifiers.m_is_protected)
env = add_expr_alias(env, get_protected_shortest_name(full_n), full_n);

View file

@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
*/
#include <string>
#include "util/timeit.h"
#include "kernel/type_checker.h"
#include "kernel/declaration.h"
@ -19,6 +20,7 @@ Author: Leonardo de Moura
#include "library/unfold_macros.h"
#include "library/noncomputable.h"
#include "library/module.h"
#include "library/documentation.h"
#include "library/scope_pos_info_provider.h"
#include "library/replace_visitor.h"
#include "library/equations_compiler/equations.h"
@ -318,7 +320,8 @@ static expr fix_rec_fn_name(expr const & e, name const & c_name, name const & c_
static pair<environment, name>
declare_definition(parser & p, environment const & env, def_cmd_kind kind, buffer<name> const & lp_names,
name const & c_name, expr const & type, expr const & _val,
decl_modifiers const & modifiers, decl_attributes attrs, pos_info const & pos) {
decl_modifiers const & modifiers, decl_attributes attrs, optional<std::string> const & doc_string,
pos_info const & pos) {
auto env_n = mk_real_name(env, c_name, modifiers.m_is_private, pos);
environment new_env = env_n.first;
name c_real_name = env_n.second;
@ -349,6 +352,9 @@ declare_definition(parser & p, environment const & env, def_cmd_kind kind, buffe
new_env = attrs.apply(new_env, p.ios(), c_real_name);
new_env = compile_decl(p, new_env, kind, modifiers.m_is_noncomputable, c_name, c_real_name, pos);
if (doc_string) {
new_env = add_doc_string(new_env, c_real_name, *doc_string);
}
return mk_pair(new_env, c_real_name);
}
@ -554,6 +560,7 @@ environment single_definition_cmd_core(parser & p, def_cmd_kind kind, decl_modif
buffer<expr> params;
expr fn, val;
auto header_pos = p.pos();
optional<std::string> doc_string = p.get_doc_string();
module::scope_pos_info scope_pos(header_pos);
declaration_info_scope scope(p, kind, modifiers);
bool is_example = (kind == def_cmd_kind::Example);
@ -582,7 +589,7 @@ environment single_definition_cmd_core(parser & p, def_cmd_kind kind, decl_modif
}
finalize_definition(elab, new_params, type, val, lp_names);
name c_name = mlocal_name(fn);
auto env_n = declare_definition(p, elab.env(), kind, lp_names, c_name, type, val, modifiers, attrs, header_pos);
auto env_n = declare_definition(p, elab.env(), kind, lp_names, c_name, type, val, modifiers, attrs, doc_string, header_pos);
if (kind == Example) return p.env();
environment new_env = env_n.first;
name c_real_name = env_n.second;

View file

@ -5,7 +5,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Daniel Selsam, Leonardo de Moura
*/
#include <algorithm>
#include <library/attribute_manager.h>
#include <string>
#include "util/sstream.h"
#include "util/name_map.h"
#include "util/fresh_name.h"
@ -17,6 +17,7 @@ Authors: Daniel Selsam, Leonardo de Moura
#include "kernel/free_vars.h"
#include "library/scoped_ext.h"
#include "library/locals.h"
#include "library/attribute_manager.h"
#include "library/deep_copy.h"
#include "library/placeholder.h"
#include "library/aliases.h"
@ -27,6 +28,7 @@ Authors: Daniel Selsam, Leonardo de Moura
#include "library/trace.h"
#include "library/app_builder.h"
#include "library/type_context.h"
#include "library/documentation.h"
#include "library/inductive_compiler/add_decl.h"
#include "frontends/lean/decl_cmds.h"
#include "frontends/lean/decl_util.h"
@ -72,6 +74,7 @@ class inductive_cmd_fn {
level m_u; // temporary auxiliary global universe used for inferring the result
// universe of an inductive datatype declaration.
bool m_infer_result_universe{false};
optional<std::string> m_doc_string;
[[ noreturn ]] void throw_error(char const * error_msg) const { throw parser_error(error_msg, m_pos); }
[[ noreturn ]] void throw_error(sstream const & strm) const { throw parser_error(strm, m_pos); }
@ -480,13 +483,20 @@ public:
m_env = m_env.add_universe(tmp_global_univ_name());
m_u = mk_global_univ(tmp_global_univ_name());
check_attrs(m_attrs);
m_doc_string = p.get_doc_string();
}
void post_process(buffer<expr> const & new_params, buffer<expr> const & new_inds, buffer<buffer<expr> > const & new_intro_rules) {
add_aliases(new_params, new_inds, new_intro_rules);
add_namespaces(new_inds);
for (expr const & ind : new_inds)
for (expr const & ind : new_inds) {
m_env = m_attrs.apply(m_env, m_p.ios(), mlocal_name(ind));
/* TODO(Leo): add support for doc-strings in mutual inductive definitions.
We are currently using the same doc string for all elements.
*/
if (m_doc_string)
m_env = add_doc_string(m_env, mlocal_name(ind), *m_doc_string);
}
if (!m_mut_attrs.empty()) {
lean_assert(new_inds.size() == m_mut_attrs.size());
for (unsigned i = 0; i < new_inds.size(); ++i)

View file

@ -1944,7 +1944,8 @@ unsigned parser::curr_lbp() const {
else
return get_token_info().expr_precedence();
case scanner::token_kind::CommandKeyword: case scanner::token_kind::Eof:
case scanner::token_kind::QuotedSymbol:
case scanner::token_kind::QuotedSymbol: case scanner::token_kind::DocBlock:
case scanner::token_kind::ModDocBlock:
return 0;
case scanner::token_kind::Identifier: case scanner::token_kind::Numeral:
case scanner::token_kind::Decimal: case scanner::token_kind::String:
@ -2028,11 +2029,22 @@ public:
virtual optional<expr> is_stuck(expr const & e) override { return ctx().is_stuck(e); }
};
static name_set * g_documentable_cmds = nullptr;
static bool support_docummentation(name const & n) {
return g_documentable_cmds->contains(n);
}
void parser::parse_command() {
lean_assert(curr() == scanner::token_kind::CommandKeyword);
m_last_cmd_pos = pos();
name cmd_name = get_token_info().value();
m_cmd_token = get_token_info().token();
if (m_doc_string && !support_docummentation(cmd_name)) {
next();
reset_doc_string();
throw parser_error(sstream() << "command '" << cmd_name << "' does not support doc string", m_last_cmd_pos);
}
if (auto it = cmds().find(cmd_name)) {
lazy_type_context tc(m_env, get_options());
scope_global_ios scope1(m_ios);
@ -2049,10 +2061,35 @@ void parser::parse_command() {
m_env = it->get_fn()(*this);
}
} else {
reset_doc_string();
auto p = pos();
next();
throw parser_error(sstream() << "unknown command '" << cmd_name << "'", p);
}
reset_doc_string();
}
void parser::parse_doc_block() {
m_doc_string = m_scanner.get_str_val();
next();
}
void parser::parse_mod_doc_block() {
next();
// TODO(Leo): save doc string
}
void parser::check_no_doc_string() {
if (m_doc_string) {
auto p = pos();
next();
reset_doc_string();
throw parser_error("invalid occurrence of doc string immediately before current position", p);
}
}
void parser::reset_doc_string() {
m_doc_string = optional<std::string>();
}
static optional<std::string> try_file(std::string const & base, optional<unsigned> const & k, name const & f, char const * ext) {
@ -2174,15 +2211,27 @@ bool parser::parse_commands() {
check_interrupted();
switch (curr()) {
case scanner::token_kind::CommandKeyword:
if (curr_is_token(get_end_tk()))
if (curr_is_token(get_end_tk())) {
check_no_doc_string();
save_snapshot();
}
parse_command();
save_snapshot();
break;
case scanner::token_kind::DocBlock:
check_no_doc_string();
parse_doc_block();
break;
case scanner::token_kind::ModDocBlock:
check_no_doc_string();
parse_mod_doc_block();
break;
case scanner::token_kind::Eof:
check_no_doc_string();
done = true;
break;
case scanner::token_kind::Keyword:
check_no_doc_string();
if (curr_is_token(get_period_tk())) {
next();
break;
@ -2306,6 +2355,20 @@ void initialize_parser() {
"(lean parser) import modules in parallel");
g_tmp_prefix = new name(name::mk_internal_unique_name());
g_anonymous_inst_name_prefix = new name("_inst");
g_documentable_cmds = new name_set();
g_documentable_cmds->insert("namespace");
g_documentable_cmds->insert("definition");
g_documentable_cmds->insert("theorem");
g_documentable_cmds->insert("constant");
g_documentable_cmds->insert("axiom");
g_documentable_cmds->insert("meta");
g_documentable_cmds->insert("mutual");
g_documentable_cmds->insert("@[");
g_documentable_cmds->insert("protected");
g_documentable_cmds->insert("class");
g_documentable_cmds->insert("inductive");
g_documentable_cmds->insert("structure");
}
void finalize_parser() {
@ -2313,5 +2376,6 @@ void finalize_parser() {
delete g_tmp_prefix;
delete g_parser_show_errors;
delete g_parser_parallel_import;
delete g_documentable_cmds;
}
}

View file

@ -147,6 +147,9 @@ class parser : public abstract_parser {
// noncomputable definitions not tagged as noncomputable.
bool m_ignore_noncomputable;
// Docgen
optional<std::string> m_doc_string;
void throw_parser_exception(char const * msg, pos_info p);
void throw_nested_exception(throwable const & ex, pos_info p);
@ -167,6 +170,10 @@ class parser : public abstract_parser {
void parse_imports();
void check_modules_up_to_date();
void parse_doc_block();
void parse_mod_doc_block();
void check_no_doc_string();
void reset_doc_string();
void parse_command();
bool parse_commands();
unsigned curr_lbp_core() const;
@ -266,6 +273,8 @@ public:
pos_info cmd_pos() const { return m_last_cmd_pos; }
name const & get_cmd_token() const { return m_cmd_token; }
optional<std::string> get_doc_string() const { return m_doc_string; }
expr mk_app(expr fn, expr arg, pos_info const & p);
expr mk_app(expr fn, buffer<expr> const & args, pos_info const & p);
expr mk_app(std::initializer_list<expr> const & args, pos_info const & p);

View file

@ -351,6 +351,32 @@ void scanner::read_single_line_comment() {
}
}
void scanner::read_doc_block_core() {
m_buffer.clear();
while (true) {
check_not_eof("unexpected end of documentation block");
char c = curr();
next();
if (c == '-') {
if (curr() == '/') {
next();
return;
}
}
m_buffer += c;
}
}
auto scanner::read_doc_block() -> token_kind {
read_doc_block_core();
return token_kind::DocBlock;
}
auto scanner::read_mod_doc_block() -> token_kind {
read_doc_block_core();
return token_kind::ModDocBlock;
}
void scanner::read_comment_block() {
unsigned nesting = 1;
while (true) {
@ -537,17 +563,23 @@ auto scanner::read_key_cmd_id() -> token_kind {
static name * g_begin_comment_tk = nullptr;
static name * g_begin_comment_block_tk = nullptr;
static name * g_begin_doc_block_tk = nullptr;
static name * g_begin_mod_doc_block_tk = nullptr;
static name * g_pound_tk = nullptr;
void initialize_scanner() {
g_begin_comment_tk = new name("--");
g_begin_comment_block_tk = new name("/-");
g_begin_doc_block_tk = new name("/--");
g_begin_mod_doc_block_tk = new name("/-!");
g_pound_tk = new name("#");
}
void finalize_scanner() {
delete g_begin_comment_tk;
delete g_begin_comment_block_tk;
delete g_begin_doc_block_tk;
delete g_begin_mod_doc_block_tk;
delete g_pound_tk;
}
@ -577,12 +609,16 @@ auto scanner::scan(environment const & env) -> token_kind {
} else {
token_kind k = read_key_cmd_id();
if (k == token_kind::Keyword) {
// We treat '(--', '(*', '--' as "keyword".
// We treat '/-', '/--', '/-!', '--' as "keyword".
name const & n = m_token_info.value();
if (n == *g_begin_comment_tk)
read_single_line_comment();
else if (n == *g_begin_comment_block_tk)
read_comment_block();
else if (n == *g_begin_doc_block_tk)
return read_doc_block();
else if (n == *g_begin_mod_doc_block_tk)
return read_mod_doc_block();
else if (n == *g_pound_tk && curr() == '"')
return read_char();
else

View file

@ -24,7 +24,9 @@ namespace lean {
*/
class scanner {
public:
enum class token_kind {Keyword, CommandKeyword, Identifier, Numeral, Decimal, String, Char, QuotedSymbol, Eof};
enum class token_kind {Keyword, CommandKeyword, Identifier, Numeral, Decimal,
String, Char, QuotedSymbol,
DocBlock, ModDocBlock, Eof};
protected:
token_table const * m_tokens;
std::istream & m_stream;
@ -76,6 +78,9 @@ protected:
token_kind read_number();
token_kind read_key_cmd_id();
token_kind read_quoted_symbol();
void read_doc_block_core();
token_kind read_doc_block();
token_kind read_mod_doc_block();
public:
scanner(std::istream & strm, char const * strm_name = nullptr);

View file

@ -38,6 +38,7 @@ Author: Leonardo de Moura
#include "library/kernel_serializer.h"
#include "library/type_context.h"
#include "library/app_builder.h"
#include "library/documentation.h"
#include "library/compiler/vm_compiler.h"
#include "library/constructions/rec_on.h"
#include "library/constructions/induction_on.h"
@ -84,6 +85,7 @@ struct structure_cmd_fn {
name m_namespace;
name m_name;
name m_given_name;
optional<std::string> m_doc_string;
pos_info m_name_pos;
buffer<name> m_level_names;
decl_attributes m_attrs;
@ -117,6 +119,7 @@ struct structure_cmd_fn {
m_infer_result_universe = false;
m_inductive_predicate = false;
m_prio = get_default_priority(p.get_options());
m_doc_string = p.get_doc_string();
}
void check_attrs(decl_attributes const & attrs, pos_info const & pos) const {
@ -838,6 +841,11 @@ struct structure_cmd_fn {
add_alias(no_confusion_name);
}
void add_doc_string() {
if (m_doc_string)
m_env = ::lean::add_doc_string(m_env, m_name, *m_doc_string);
}
environment operator()() {
process_header();
module::scope_pos_info scope(m_name_pos);
@ -871,6 +879,7 @@ struct structure_cmd_fn {
declare_projections();
declare_auxiliary();
declare_coercions();
add_doc_string();
if (!m_inductive_predicate) {
declare_no_confustion();
}

View file

@ -89,7 +89,7 @@ void init_token_table(token_table & t) {
{"", 0}, {"", g_max_prec}, {"", 0}, {"^", 0}, {"", 0}, {"", 0},
{"//", 0}, {"|", 0}, {"!", g_max_prec}, {"?", 0}, {"with", 0}, {"without", 0}, {"...", 0}, {",", 0},
{".", 0}, {":", 0}, {"::", 0}, {"calc", 0}, {"as", 0}, {":=", 0}, {"--", 0}, {"#", g_max_prec},
{"(*", 0}, {"/-", 0}, {"begin", g_max_prec}, {"using", 0},
{"(*", 0}, {"/-", 0}, {"/--", 0}, {"/-!", 0}, {"begin", g_max_prec}, {"using", 0},
{"@@", g_max_prec}, {"@", g_max_prec},
{"sorry", g_max_prec}, {"+", g_plus_prec}, {"->", g_arrow_prec}, {"<-", 0},
{"?(", g_max_prec}, {"", g_max_prec}, {"", 0}, {"match", 0},
@ -104,7 +104,7 @@ void init_token_table(token_table & t) {
"variables", "parameter", "parameters", "constant", "constants",
"evaluate", "check", "eval", "vm_eval", "using_well_founded", "[whnf]",
"print", "end", "namespace", "section", "prelude", "help",
"import", "inductive", "record", "structure", "class", "universe", "universes", "local",
"import", "inductive", "structure", "class", "universe", "universes", "local",
"precedence", "reserve", "infixl", "infixr", "infix", "postfix", "prefix", "notation",
"exit", "set_option", "open", "export", "override", "@[",
"attribute", "persistent", "instance", "include", "omit", "init_quotient",

View file

@ -16,4 +16,4 @@ add_library(library OBJECT deep_copy.cpp expr_lt.cpp io_state.cpp
mpq_macro.cpp arith_instance_manager.cpp replace_visitor_with_tc.cpp
aux_definition.cpp inverse.cpp library_system.cpp pattern_attribute.cpp choice.cpp
locals.cpp normalize.cpp discr_tree.cpp
messages.cpp message_builder.cpp comp_val.cpp)
messages.cpp message_builder.cpp comp_val.cpp documentation.cpp)

View file

@ -0,0 +1,74 @@
/*
Copyright (c) 2016 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
*/
#include <string>
#include "util/sstream.h"
#include "library/module.h"
namespace lean {
struct documentation_ext : public environment_extension {
name_map<std::string> m_doc_strings; // map: declaration/namespace -> doc string
};
struct documentation_ext_reg {
unsigned m_ext_id;
documentation_ext_reg() { m_ext_id = environment::register_extension(std::make_shared<documentation_ext>()); }
};
static documentation_ext_reg * g_ext = nullptr;
static documentation_ext const & get_extension(environment const & env) {
return static_cast<documentation_ext const &>(env.get_extension(g_ext->m_ext_id));
}
static environment update(environment const & env, documentation_ext const & ext) {
return env.update(g_ext->m_ext_id, std::make_shared<documentation_ext>(ext));
}
static name * g_documentation = nullptr;
static std::string * g_doc_key = nullptr;
environment add_doc_string(environment const & env, name const & n, std::string const & doc) {
auto ext = get_extension(env);
if (ext.m_doc_strings.contains(n)) {
throw exception(sstream() << "environment already contains a doc string for '" << n << "'");
}
ext.m_doc_strings.insert(n, doc);
auto new_env = update(env, ext);
return module::add(new_env, *g_doc_key, [=](environment const &, serializer & s) { s << n << doc; });
}
optional<std::string> get_doc_string(environment const & env, name const & n) {
auto ext = get_extension(env);
if (auto r = ext.m_doc_strings.find(n))
return optional<std::string>(*r);
else
return optional<std::string>();
}
static void documentation_reader(deserializer & d, shared_environment & senv,
std::function<void(asynch_update_fn const &)> &,
std::function<void(delayed_update_fn const &)> &) {
name n; std::string doc;
d >> n >> doc;
senv.update([=](environment const & env) -> environment {
auto ext = get_extension(env);
ext.m_doc_strings.insert(n, doc);
return update(env, ext);
});
}
void initialize_documentation() {
g_ext = new documentation_ext_reg();
g_documentation = new name("documentation");
g_doc_key = new std::string("doc");
register_module_object_reader(*g_doc_key, documentation_reader);
}
void finalize_documentation() {
delete g_doc_key;
delete g_documentation;
delete g_ext;
}
}

View file

@ -0,0 +1,15 @@
/*
Copyright (c) 2016 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
*/
#pragma once
#include <string>
#include "kernel/environment.h"
namespace lean {
environment add_doc_string(environment const & env, name const & n, std::string const & doc);
optional<std::string> get_doc_string(environment const & env, name const & n);
void initialize_documentation();
void finalize_documentation();
}

View file

@ -48,6 +48,7 @@ Author: Leonardo de Moura
#include "library/inverse.h"
#include "library/pattern_attribute.h"
#include "library/comp_val.h"
#include "library/documentation.h"
namespace lean {
void initialize_library_core_module() {
@ -106,9 +107,11 @@ void initialize_library_module() {
initialize_inverse();
initialize_pattern_attribute();
initialize_comp_val();
initialize_documentation();
}
void finalize_library_module() {
finalize_documentation();
finalize_comp_val();
finalize_pattern_attribute();
finalize_inverse();

View file

@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
*/
#include <string>
#include "util/fresh_name.h"
#include "util/sexpr/option_declarations.h"
#include "kernel/type_checker.h"
@ -15,10 +16,12 @@ Author: Leonardo de Moura
#include "library/util.h"
#include "library/cache_helper.h"
#include "library/module.h"
#include "library/documentation.h"
#include "library/scoped_ext.h"
#include "library/vm/vm_environment.h"
#include "library/vm/vm_exceptional.h"
#include "library/vm/vm_format.h"
#include "library/vm/vm_string.h"
#include "library/vm/vm_options.h"
#include "library/vm/vm_name.h"
#include "library/vm/vm_nat.h"
@ -619,6 +622,25 @@ vm_obj tactic_opened_namespaces(vm_obj const & s) {
return mk_tactic_success(to_obj(get_namespaces(env)), to_tactic_state(s));
}
vm_obj tactic_doc_string(vm_obj const & n, vm_obj const & _s) {
tactic_state const & s = to_tactic_state(_s);
if (optional<std::string> doc = get_doc_string(s.env(), to_name(n))) {
return mk_tactic_success(to_obj(*doc), s);
} else {
return mk_tactic_exception(sstream() << "no doc string for '" << n << "'", s);
}
}
vm_obj tactic_add_doc_string(vm_obj const & n, vm_obj const & doc, vm_obj const & _s) {
tactic_state const & s = to_tactic_state(_s);
try {
environment new_env = add_doc_string(s.env(), to_name(n), to_string(doc));
return mk_tactic_success(set_env(s, new_env));
} catch (throwable & ex) {
return mk_tactic_exception(ex, s);
}
}
void initialize_tactic_state() {
DECLARE_VM_BUILTIN(name({"tactic_state", "env"}), tactic_state_env);
DECLARE_VM_BUILTIN(name({"tactic_state", "format_expr"}), tactic_state_format_expr);
@ -651,6 +673,8 @@ void initialize_tactic_state() {
DECLARE_VM_BUILTIN(name({"tactic", "is_trace_enabled_for"}), tactic_is_trace_enabled_for);
DECLARE_VM_BUILTIN(name({"tactic", "instantiate_mvars"}), tactic_instantiate_mvars);
DECLARE_VM_BUILTIN(name({"tactic", "add_decl"}), tactic_add_decl);
DECLARE_VM_BUILTIN(name({"tactic", "doc_string"}), tactic_doc_string);
DECLARE_VM_BUILTIN(name({"tactic", "add_doc_string"}), tactic_add_doc_string);
DECLARE_VM_BUILTIN(name({"tactic", "opened_namespaces"}), tactic_opened_namespaces);
g_pp_instantiate_goal_mvars = new name{"pp", "instantiate_goal_mvars"};
register_bool_option(*g_pp_instantiate_goal_mvars, LEAN_DEFAULT_PP_INSTANTIATE_GOAL_MVARS,

View file

@ -1,9 +1,9 @@
/- /- -/ -/
/- - /--/-/
/-/-/--/-/-/
/--/
/------------/
/---/
/- -/
/- -----------/
/- --/
/- ---/
/-
-/

View file

@ -0,0 +1,48 @@
/--
Documentation for x
Testing...
-/
def x := 10 + 20
def y := "alo"
open tactic
run_command do
d ← doc_string `x,
trace d
run_command add_doc_string `y "testing simple doc"
run_command do
d ← doc_string `y,
trace d
/-- Documentation for foo -/
namespace foo
/-- Documentation for bla -/
namespace bla
/-- Documentation for single -/
inductive single
| unit
end bla
end foo
run_command do
doc_string `foo >>= trace,
doc_string `foo.bla >>= trace,
doc_string `foo.bla.single >>= trace
/-- Documentation for constant A -/
constant A : Type
run_command doc_string `A >>= trace
/-- Documentation for point -/
structure point :=
(x : nat) (y : nat)
run_command doc_string `point >>= trace