feat(frontends/lean): allow user to associate priorities to class-instances, closes #180
This commit is contained in:
parent
9f6a8827e0
commit
397395bbc9
11 changed files with 153 additions and 37 deletions
6
library/priority.lean
Normal file
6
library/priority.lean
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import data.num
|
||||||
|
|
||||||
|
namespace priority
|
||||||
|
definition default : num := 1000
|
||||||
|
definition max : num := 4294967295
|
||||||
|
end priority
|
|
@ -72,6 +72,7 @@
|
||||||
;; modifiers
|
;; modifiers
|
||||||
(,(rx (or "\[persistent\]" "\[notation\]" "\[visible\]" "\[instance\]" "\[class\]"
|
(,(rx (or "\[persistent\]" "\[notation\]" "\[visible\]" "\[instance\]" "\[class\]"
|
||||||
"\[coercion\]" "\[reducible\]" "\[off\]" "\[none\]" "\[on\]")) . 'font-lock-doc-face)
|
"\[coercion\]" "\[reducible\]" "\[off\]" "\[none\]" "\[on\]")) . 'font-lock-doc-face)
|
||||||
|
(,(rx "\[priority" (zero-or-more (not (any "\]"))) "\]") . font-lock-doc-face)
|
||||||
;; tactics
|
;; tactics
|
||||||
(,(rx symbol-start
|
(,(rx symbol-start
|
||||||
(or "\\b.*_tac" "Cond" "or_else" "then" "try" "when" "assumption" "apply" "back" "beta" "done" "exact" "repeat")
|
(or "\\b.*_tac" "Cond" "or_else" "then" "try" "when" "assumption" "apply" "back" "beta" "done" "exact" "repeat")
|
||||||
|
|
|
@ -11,34 +11,66 @@ Author: Leonardo de Moura
|
||||||
#include "library/scoped_ext.h"
|
#include "library/scoped_ext.h"
|
||||||
#include "library/kernel_serializer.h"
|
#include "library/kernel_serializer.h"
|
||||||
#include "library/reducible.h"
|
#include "library/reducible.h"
|
||||||
|
#include "library/num.h"
|
||||||
#include "frontends/lean/parser.h"
|
#include "frontends/lean/parser.h"
|
||||||
#include "frontends/lean/util.h"
|
#include "frontends/lean/util.h"
|
||||||
#include "frontends/lean/tactic_hint.h"
|
#include "frontends/lean/tactic_hint.h"
|
||||||
|
#include "frontends/lean/tokens.h"
|
||||||
|
|
||||||
|
#ifndef LEAN_INSTANCE_DEFAULT_PRIORITY
|
||||||
|
#define LEAN_INSTANCE_DEFAULT_PRIORITY 1000
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
struct class_entry {
|
struct class_entry {
|
||||||
bool m_class_cmd;
|
bool m_class_cmd;
|
||||||
name m_class;
|
name m_class;
|
||||||
name m_instance; // only relevant if m_class_cmd == false
|
name m_instance; // only relevant if m_class_cmd == false
|
||||||
class_entry():m_class_cmd(false) {}
|
unsigned m_priority; // only relevant if m_class_cmd == false
|
||||||
explicit class_entry(name const & c):m_class_cmd(true), m_class(c) {}
|
class_entry():m_class_cmd(false), m_priority(0) {}
|
||||||
class_entry(name const & c, name const & i):m_class_cmd(false), m_class(c), m_instance(i) {}
|
explicit class_entry(name const & c):m_class_cmd(true), m_class(c), m_priority(0) {}
|
||||||
|
class_entry(name const & c, name const & i, unsigned p):
|
||||||
|
m_class_cmd(false), m_class(c), m_instance(i), m_priority(p) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct class_state {
|
struct class_state {
|
||||||
typedef name_map<list<name>> class_instances;
|
typedef name_map<list<name>> class_instances;
|
||||||
|
typedef name_map<unsigned> instance_priorities;
|
||||||
class_instances m_instances;
|
class_instances m_instances;
|
||||||
|
instance_priorities m_priorities;
|
||||||
|
|
||||||
|
unsigned get_priority(name const & i) const {
|
||||||
|
if (auto it = m_priorities.find(i))
|
||||||
|
return *it;
|
||||||
|
else
|
||||||
|
return LEAN_INSTANCE_DEFAULT_PRIORITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
list<name> insert(name const & inst, unsigned priority, list<name> const & insts) const {
|
||||||
|
if (!insts)
|
||||||
|
return to_list(inst);
|
||||||
|
else if (priority >= get_priority(head(insts)))
|
||||||
|
return list<name>(inst, insts);
|
||||||
|
else
|
||||||
|
return list<name>(head(insts), insert(inst, priority, tail(insts)));
|
||||||
|
}
|
||||||
|
|
||||||
void add_class(name const & c) {
|
void add_class(name const & c) {
|
||||||
auto it = m_instances.find(c);
|
auto it = m_instances.find(c);
|
||||||
if (!it)
|
if (!it)
|
||||||
m_instances.insert(c, list<name>());
|
m_instances.insert(c, list<name>());
|
||||||
}
|
}
|
||||||
void add_instance(name const & c, name const & i) {
|
|
||||||
|
void add_instance(name const & c, name const & i, unsigned p) {
|
||||||
auto it = m_instances.find(c);
|
auto it = m_instances.find(c);
|
||||||
if (!it)
|
if (!it) {
|
||||||
m_instances.insert(c, to_list(i));
|
m_instances.insert(c, to_list(i));
|
||||||
else
|
} else {
|
||||||
m_instances.insert(c, cons(i, filter(*it, [&](name const & i1) { return i1 != i; })));
|
auto lst = filter(*it, [&](name const & i1) { return i1 != i; });
|
||||||
|
m_instances.insert(c, insert(i, p, lst));
|
||||||
|
}
|
||||||
|
if (p != LEAN_INSTANCE_DEFAULT_PRIORITY)
|
||||||
|
m_priorities.insert(i, p);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -52,7 +84,7 @@ struct class_config {
|
||||||
if (e.m_class_cmd)
|
if (e.m_class_cmd)
|
||||||
s.add_class(e.m_class);
|
s.add_class(e.m_class);
|
||||||
else
|
else
|
||||||
s.add_instance(e.m_class, e.m_instance);
|
s.add_instance(e.m_class, e.m_instance, e.m_priority);
|
||||||
}
|
}
|
||||||
static name const & get_class_name() {
|
static name const & get_class_name() {
|
||||||
return *g_class_name;
|
return *g_class_name;
|
||||||
|
@ -64,7 +96,7 @@ struct class_config {
|
||||||
if (e.m_class_cmd)
|
if (e.m_class_cmd)
|
||||||
s << true << e.m_class;
|
s << true << e.m_class;
|
||||||
else
|
else
|
||||||
s << false << e.m_class << e.m_instance;
|
s << false << e.m_class << e.m_instance << e.m_priority;
|
||||||
}
|
}
|
||||||
static entry read_entry(deserializer & d) {
|
static entry read_entry(deserializer & d) {
|
||||||
entry e;
|
entry e;
|
||||||
|
@ -72,7 +104,7 @@ struct class_config {
|
||||||
if (e.m_class_cmd)
|
if (e.m_class_cmd)
|
||||||
d >> e.m_class;
|
d >> e.m_class;
|
||||||
else
|
else
|
||||||
d >> e.m_class >> e.m_instance;
|
d >> e.m_class >> e.m_instance >> e.m_priority;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -100,7 +132,7 @@ environment add_class(environment const & env, name const & n, bool persistent)
|
||||||
}
|
}
|
||||||
|
|
||||||
static name * g_tmp_prefix = nullptr;
|
static name * g_tmp_prefix = nullptr;
|
||||||
environment add_instance(environment const & env, name const & n, bool persistent) {
|
environment add_instance(environment const & env, name const & n, unsigned priority, bool persistent) {
|
||||||
declaration d = env.get(n);
|
declaration d = env.get(n);
|
||||||
expr type = d.get_type();
|
expr type = d.get_type();
|
||||||
name_generator ngen(*g_tmp_prefix);
|
name_generator ngen(*g_tmp_prefix);
|
||||||
|
@ -112,7 +144,11 @@ environment add_instance(environment const & env, name const & n, bool persisten
|
||||||
type = instantiate(binding_body(type), mk_local(ngen.next(), binding_domain(type)));
|
type = instantiate(binding_body(type), mk_local(ngen.next(), binding_domain(type)));
|
||||||
}
|
}
|
||||||
name c = get_class_name(env, get_app_fn(type));
|
name c = get_class_name(env, get_app_fn(type));
|
||||||
return class_ext::add_entry(env, get_dummy_ios(), class_entry(c, n), persistent);
|
return class_ext::add_entry(env, get_dummy_ios(), class_entry(c, n, priority), persistent);
|
||||||
|
}
|
||||||
|
|
||||||
|
environment add_instance(environment const & env, name const & n, bool persistent) {
|
||||||
|
return add_instance(env, n, LEAN_INSTANCE_DEFAULT_PRIORITY, persistent);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_class(environment const & env, name const & c) {
|
bool is_class(environment const & env, name const & c) {
|
||||||
|
@ -125,14 +161,37 @@ list<name> get_class_instances(environment const & env, name const & c) {
|
||||||
return ptr_to_list(s.m_instances.find(c));
|
return ptr_to_list(s.m_instances.find(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
optional<unsigned> parse_instance_priority(parser & p) {
|
||||||
|
if (p.curr_is_token(get_priority_tk())) {
|
||||||
|
p.next();
|
||||||
|
auto pos = p.pos();
|
||||||
|
expr val = p.parse_expr();
|
||||||
|
val = type_checker(p.env()).whnf(val).first;
|
||||||
|
if (optional<mpz> mpz_val = to_num(val)) {
|
||||||
|
if (!mpz_val->is_unsigned_int())
|
||||||
|
throw parser_error("invalid 'priority', argument does not fit in a machine integer", pos);
|
||||||
|
p.check_token_next(get_rbracket_tk(), "invalid 'priority', ']' expected");
|
||||||
|
return optional<unsigned>(mpz_val->get_unsigned_int());
|
||||||
|
} else {
|
||||||
|
throw parser_error("invalid 'priority', argument does not evaluate to a numeral", pos);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return optional<unsigned>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
environment add_instance_cmd(parser & p) {
|
environment add_instance_cmd(parser & p) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
bool persistent = false;
|
bool persistent = false;
|
||||||
parse_persistent(p, persistent);
|
parse_persistent(p, persistent);
|
||||||
|
optional<unsigned> priority = parse_instance_priority(p);
|
||||||
environment env = p.env();
|
environment env = p.env();
|
||||||
while (p.curr_is_identifier()) {
|
while (p.curr_is_identifier()) {
|
||||||
found = true;
|
found = true;
|
||||||
name c = p.check_constant_next("invalid 'class instance' declaration, constant expected");
|
name c = p.check_constant_next("invalid 'class instance' declaration, constant expected");
|
||||||
|
if (priority)
|
||||||
|
env = add_instance(env, c, *priority, persistent);
|
||||||
|
else
|
||||||
env = add_instance(env, c, persistent);
|
env = add_instance(env, c, persistent);
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
|
|
|
@ -13,13 +13,17 @@ Author: Leonardo de Moura
|
||||||
namespace lean {
|
namespace lean {
|
||||||
/** \brief Add a new 'class' to the environment (if it is not already declared) */
|
/** \brief Add a new 'class' to the environment (if it is not already declared) */
|
||||||
environment add_class(environment const & env, name const & n, bool persistent = true);
|
environment add_class(environment const & env, name const & n, bool persistent = true);
|
||||||
/** \brief Add a new 'class instance' to the environment. */
|
/** \brief Add a new 'class instance' to the environment with default priority. */
|
||||||
environment add_instance(environment const & env, name const & n, bool persistent = true);
|
environment add_instance(environment const & env, name const & n, bool persistent = true);
|
||||||
|
/** \brief Add a new 'class instance' to the environment. */
|
||||||
|
environment add_instance(environment const & env, name const & n, unsigned priority, bool persistent);
|
||||||
/** \brief Return true iff \c c was declared with \c add_class . */
|
/** \brief Return true iff \c c was declared with \c add_class . */
|
||||||
bool is_class(environment const & env, name const & c);
|
bool is_class(environment const & env, name const & c);
|
||||||
/** \brief Return the instances of the given class. */
|
/** \brief Return the instances of the given class. */
|
||||||
list<name> get_class_instances(environment const & env, name const & c);
|
list<name> get_class_instances(environment const & env, name const & c);
|
||||||
name get_class_name(environment const & env, expr const & e);
|
name get_class_name(environment const & env, expr const & e);
|
||||||
|
/** \brief Parse priority for an class instance */
|
||||||
|
optional<unsigned> parse_instance_priority(parser & p);
|
||||||
void register_class_cmds(cmd_table & r);
|
void register_class_cmds(cmd_table & r);
|
||||||
|
|
||||||
/** \brief Return true iff \c type is a class or Pi that produces a class. */
|
/** \brief Return true iff \c type is a class or Pi that produces a class. */
|
||||||
|
|
|
@ -152,7 +152,8 @@ struct decl_modifiers {
|
||||||
bool m_is_instance;
|
bool m_is_instance;
|
||||||
bool m_is_coercion;
|
bool m_is_coercion;
|
||||||
bool m_is_reducible;
|
bool m_is_reducible;
|
||||||
decl_modifiers() {
|
optional<unsigned> m_priority;
|
||||||
|
decl_modifiers():m_priority() {
|
||||||
m_is_instance = false;
|
m_is_instance = false;
|
||||||
m_is_coercion = false;
|
m_is_coercion = false;
|
||||||
m_is_reducible = false;
|
m_is_reducible = false;
|
||||||
|
@ -160,6 +161,7 @@ struct decl_modifiers {
|
||||||
|
|
||||||
void parse(parser & p) {
|
void parse(parser & p) {
|
||||||
while (true) {
|
while (true) {
|
||||||
|
auto pos = p.pos();
|
||||||
if (p.curr_is_token(get_instance_tk())) {
|
if (p.curr_is_token(get_instance_tk())) {
|
||||||
m_is_instance = true;
|
m_is_instance = true;
|
||||||
p.next();
|
p.next();
|
||||||
|
@ -169,6 +171,10 @@ struct decl_modifiers {
|
||||||
} else if (p.curr_is_token(get_reducible_tk())) {
|
} else if (p.curr_is_token(get_reducible_tk())) {
|
||||||
m_is_reducible = true;
|
m_is_reducible = true;
|
||||||
p.next();
|
p.next();
|
||||||
|
} else if (auto it = parse_instance_priority(p)) {
|
||||||
|
m_priority = *it;
|
||||||
|
if (!m_is_instance)
|
||||||
|
throw parser_error("invalid '[priority]' occurrence, declaration must be marked as an '[instance]'", pos);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -332,8 +338,14 @@ environment definition_cmd_core(parser & p, bool is_theorem, bool is_opaque, boo
|
||||||
|
|
||||||
if (real_n != n)
|
if (real_n != n)
|
||||||
env = add_expr_alias_rec(env, n, real_n);
|
env = add_expr_alias_rec(env, n, real_n);
|
||||||
if (modifiers.m_is_instance)
|
if (modifiers.m_is_instance) {
|
||||||
env = add_instance(env, real_n);
|
bool persistent = true;
|
||||||
|
if (modifiers.m_priority) {
|
||||||
|
env = add_instance(env, real_n, *modifiers.m_priority, persistent);
|
||||||
|
} else {
|
||||||
|
env = add_instance(env, real_n, persistent);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (modifiers.m_is_coercion)
|
if (modifiers.m_is_coercion)
|
||||||
env = add_coercion(env, real_n, p.ios());
|
env = add_coercion(env, real_n, p.ios());
|
||||||
if (is_protected)
|
if (is_protected)
|
||||||
|
|
|
@ -357,7 +357,8 @@ parse_table parse_table::add(unsigned num, transition const * ts, expr const & a
|
||||||
return add_core(num, ts, new_a, overload);
|
return add_core(num, ts, new_a, overload);
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_table::for_each(buffer<transition> & ts, std::function<void(unsigned, transition const *, list<expr> const &)> const & fn) const {
|
void parse_table::for_each(buffer<transition> & ts,
|
||||||
|
std::function<void(unsigned, transition const *, list<expr> const &)> const & fn) const {
|
||||||
if (!is_nil(m_ptr->m_accept))
|
if (!is_nil(m_ptr->m_accept))
|
||||||
fn(ts.size(), ts.data(), m_ptr->m_accept);
|
fn(ts.size(), ts.data(), m_ptr->m_accept);
|
||||||
m_ptr->m_children.for_each([&](name const & k, pair<action, parse_table> const & p) {
|
m_ptr->m_children.for_each([&](name const & k, pair<action, parse_table> const & p) {
|
||||||
|
|
|
@ -71,15 +71,18 @@ void init_token_table(token_table & t) {
|
||||||
pair<char const *, unsigned> builtin[] =
|
pair<char const *, unsigned> builtin[] =
|
||||||
{{"fun", 0}, {"Pi", 0}, {"let", 0}, {"in", 0}, {"have", 0}, {"show", 0}, {"obtain", 0}, {"by", 0}, {"then", 0},
|
{{"fun", 0}, {"Pi", 0}, {"let", 0}, {"in", 0}, {"have", 0}, {"show", 0}, {"obtain", 0}, {"by", 0}, {"then", 0},
|
||||||
{"from", 0}, {"(", g_max_prec}, {")", 0}, {"{", g_max_prec}, {"}", 0}, {"_", g_max_prec},
|
{"from", 0}, {"(", g_max_prec}, {")", 0}, {"{", g_max_prec}, {"}", 0}, {"_", g_max_prec},
|
||||||
{"[", g_max_prec}, {"]", 0}, {"⦃", g_max_prec}, {"⦄", 0}, {".{", 0}, {"Type", g_max_prec}, {"Type'", g_max_prec}, {"using", 0},
|
{"[", g_max_prec}, {"]", 0}, {"⦃", g_max_prec}, {"⦄", 0}, {".{", 0}, {"Type", g_max_prec},
|
||||||
{"|", 0}, {"!", 0}, {"with", 0}, {"...", 0}, {",", 0}, {".", 0}, {":", 0}, {"::", 0}, {"calc", 0}, {":=", 0}, {"--", 0}, {"#", 0},
|
{"Type'", g_max_prec}, {"using", 0}, {"|", 0}, {"!", 0}, {"with", 0}, {"...", 0}, {",", 0},
|
||||||
{"(*", 0}, {"/-", 0}, {"begin", g_max_prec}, {"proof", g_max_prec}, {"qed", 0}, {"@", g_max_prec}, {"including", 0}, {"sorry", g_max_prec},
|
{".", 0}, {":", 0}, {"::", 0}, {"calc", 0}, {":=", 0}, {"--", 0}, {"#", 0},
|
||||||
{"+", g_plus_prec}, {g_cup, g_cup_prec}, {"->", g_arrow_prec}, {nullptr, 0}};
|
{"(*", 0}, {"/-", 0}, {"begin", g_max_prec}, {"proof", g_max_prec}, {"qed", 0}, {"@", g_max_prec},
|
||||||
|
{"including", 0}, {"sorry", g_max_prec}, {"+", g_plus_prec}, {g_cup, g_cup_prec}, {"->", g_arrow_prec},
|
||||||
|
{nullptr, 0}};
|
||||||
|
|
||||||
char const * commands[] = {"theorem", "axiom", "variable", "protected", "private", "opaque", "definition", "coercion",
|
char const * commands[] =
|
||||||
|
{"theorem", "axiom", "variable", "protected", "private", "opaque", "definition", "coercion",
|
||||||
"variables", "[persistent]", "[visible]", "[instance]",
|
"variables", "[persistent]", "[visible]", "[instance]",
|
||||||
"[off]", "[on]", "[none]", "[class]", "[coercion]", "[reducible]", "reducible", "irreducible",
|
"[off]", "[on]", "[none]", "[class]", "[coercion]", "[reducible]", "reducible", "irreducible",
|
||||||
"evaluate", "check", "eval", "print", "end", "namespace", "section", "import",
|
"evaluate", "check", "eval", "[priority", "print", "end", "namespace", "section", "import",
|
||||||
"inductive", "record", "renaming", "extends", "structure", "module", "universe",
|
"inductive", "record", "renaming", "extends", "structure", "module", "universe",
|
||||||
"precedence", "infixl", "infixr", "infix", "postfix", "prefix", "notation", "context",
|
"precedence", "infixl", "infixr", "infix", "postfix", "prefix", "notation", "context",
|
||||||
"exit", "set_option", "open", "export", "calc_subst", "calc_refl", "calc_trans", "tactic_hint",
|
"exit", "set_option", "open", "export", "calc_subst", "calc_refl", "calc_trans", "tactic_hint",
|
||||||
|
|
|
@ -63,6 +63,7 @@ static name * g_axiom = nullptr;
|
||||||
static name * g_variable = nullptr;
|
static name * g_variable = nullptr;
|
||||||
static name * g_opaque = nullptr;
|
static name * g_opaque = nullptr;
|
||||||
static name * g_instance = nullptr;
|
static name * g_instance = nullptr;
|
||||||
|
static name * g_priority = nullptr;
|
||||||
static name * g_coercion = nullptr;
|
static name * g_coercion = nullptr;
|
||||||
static name * g_reducible = nullptr;
|
static name * g_reducible = nullptr;
|
||||||
static name * g_with = nullptr;
|
static name * g_with = nullptr;
|
||||||
|
@ -140,6 +141,7 @@ void initialize_tokens() {
|
||||||
g_axiom = new name("axiom");
|
g_axiom = new name("axiom");
|
||||||
g_variable = new name("variable");
|
g_variable = new name("variable");
|
||||||
g_instance = new name("[instance]");
|
g_instance = new name("[instance]");
|
||||||
|
g_priority = new name("[priority");
|
||||||
g_coercion = new name("[coercion]");
|
g_coercion = new name("[coercion]");
|
||||||
g_reducible = new name("[reducible]");
|
g_reducible = new name("[reducible]");
|
||||||
g_with = new name("with");
|
g_with = new name("with");
|
||||||
|
@ -185,6 +187,7 @@ void finalize_tokens() {
|
||||||
delete g_axiom;
|
delete g_axiom;
|
||||||
delete g_variable;
|
delete g_variable;
|
||||||
delete g_instance;
|
delete g_instance;
|
||||||
|
delete g_priority;
|
||||||
delete g_coercion;
|
delete g_coercion;
|
||||||
delete g_reducible;
|
delete g_reducible;
|
||||||
delete g_in;
|
delete g_in;
|
||||||
|
@ -295,6 +298,7 @@ name const & get_axiom_tk() { return *g_axiom; }
|
||||||
name const & get_variable_tk() { return *g_variable; }
|
name const & get_variable_tk() { return *g_variable; }
|
||||||
name const & get_opaque_tk() { return *g_opaque; }
|
name const & get_opaque_tk() { return *g_opaque; }
|
||||||
name const & get_instance_tk() { return *g_instance; }
|
name const & get_instance_tk() { return *g_instance; }
|
||||||
|
name const & get_priority_tk() { return *g_priority; }
|
||||||
name const & get_coercion_tk() { return *g_coercion; }
|
name const & get_coercion_tk() { return *g_coercion; }
|
||||||
name const & get_reducible_tk() { return *g_reducible; }
|
name const & get_reducible_tk() { return *g_reducible; }
|
||||||
name const & get_class_tk() { return *g_class; }
|
name const & get_class_tk() { return *g_class; }
|
||||||
|
|
|
@ -65,6 +65,7 @@ name const & get_axiom_tk();
|
||||||
name const & get_variable_tk();
|
name const & get_variable_tk();
|
||||||
name const & get_opaque_tk();
|
name const & get_opaque_tk();
|
||||||
name const & get_instance_tk();
|
name const & get_instance_tk();
|
||||||
|
name const & get_priority_tk();
|
||||||
name const & get_coercion_tk();
|
name const & get_coercion_tk();
|
||||||
name const & get_reducible_tk();
|
name const & get_reducible_tk();
|
||||||
name const & get_class_tk();
|
name const & get_class_tk();
|
||||||
|
|
24
tests/lean/inst.lean
Normal file
24
tests/lean/inst.lean
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import logic data.prod priority
|
||||||
|
open priority
|
||||||
|
set_option pp.notation false
|
||||||
|
|
||||||
|
inductive C (A : Type) :=
|
||||||
|
mk : A → C A
|
||||||
|
|
||||||
|
definition val {A : Type} (c : C A) : A :=
|
||||||
|
C.rec (λa, a) c
|
||||||
|
|
||||||
|
variable magic (A : Type) : A
|
||||||
|
definition C_magic [instance] [priority max] (A : Type) : C A :=
|
||||||
|
C.mk (magic A)
|
||||||
|
|
||||||
|
definition C_prop [instance] : C Prop :=
|
||||||
|
C.mk true
|
||||||
|
|
||||||
|
definition C_prod [instance] {A B : Type} (Ha : C A) (Hb : C B) : C (prod A B) :=
|
||||||
|
C.mk (pair (val Ha) (val Hb))
|
||||||
|
|
||||||
|
-- C_magic will be used because it has max priority
|
||||||
|
definition test : C (prod Prop Prop) := _
|
||||||
|
|
||||||
|
eval test
|
1
tests/lean/inst.lean.expected.out
Normal file
1
tests/lean/inst.lean.expected.out
Normal file
|
@ -0,0 +1 @@
|
||||||
|
C.mk (magic (prod Prop Prop))
|
Loading…
Reference in a new issue