feat(frontends/lean): modify syntax for local notation

The idea is to make it uniform with the syntax for defining local
attributes.
This commit is contained in:
Leonardo de Moura 2015-01-26 11:49:08 -08:00
parent b4d6f6e3ed
commit e2c41fca75
14 changed files with 75 additions and 69 deletions

View file

@ -15,9 +15,9 @@ namespace binary
variable {A : Type}
variables (op₁ : A → A → A) (inv : A → A) (one : A)
notation [local] a * b := op₁ a b
notation [local] a ⁻¹ := inv a
notation [local] 1 := one
local notation a * b := op₁ a b
local notation a ⁻¹ := inv a
local notation 1 := one
definition commutative := ∀a b, a*b = b*a
definition associative := ∀a b c, (a*b)*c = a*(b*c)
@ -35,7 +35,7 @@ namespace binary
variable (op₂ : A → A → A)
notation [local] a + b := op₂ a b
local notation a + b := op₂ a b
definition left_distributive := ∀a b c, a * (b + c) = a * b + a * c
definition right_distributive := ∀a b c, (a + b) * c = a * c + b * c

View file

@ -10,7 +10,7 @@ import init.logic
-- We need some of the following definitions asap when "initializing" Lean.
variables {A B : Type} (R : B → B → Type)
infix [local] `≺`:50 := R
local infix `≺`:50 := R
definition reflexive := ∀x, x ≺ x

View file

@ -11,7 +11,7 @@ import types.prod
open eq sigma sigma.ops equiv is_equiv
namespace sigma
infixr [local] ∘ := function.compose --remove
local infixr ∘ := function.compose --remove
variables {A A' : Type} {B : A → Type} {B' : A' → Type} {C : Πa, B a → Type}
{D : Πa b, C a b → Type}
{a a' a'' : A} {b b₁ b₂ : B a} {b' : B a'} {b'' : B a''} {u v w : Σa, B a}

View file

@ -16,9 +16,9 @@ namespace binary
variable {A : Type}
variables (op₁ : A → A → A) (inv : A → A) (one : A)
notation [local] a * b := op₁ a b
notation [local] a ⁻¹ := inv a
notation [local] 1 := one
local notation a * b := op₁ a b
local notation a ⁻¹ := inv a
local notation 1 := one
definition commutative := ∀a b, a * b = b * a
definition associative := ∀a b c, (a * b) * c = a * (b * c)
@ -36,7 +36,7 @@ namespace binary
variable (op₂ : A → A → A)
notation [local] a + b := op₂ a b
local notation a + b := op₂ a b
definition left_distributive := ∀a b c, a * (b + c) = a * b + a * c
definition right_distributive := ∀a b c, (a + b) * c = a * c + b * c

View file

@ -151,7 +151,7 @@ cases_on a
definition equiv (p q : × ) : Prop := pr1 p + pr2 q = pr2 p + pr1 q
notation [local] p `≡` q := equiv p q
local notation p `≡` q := equiv p q
theorem equiv.refl {p : × } : p ≡ p := !add.comm

View file

@ -334,7 +334,7 @@ private definition pair_nat.lt.wf : well_founded pair_nat.lt :=
intro_k (measure.wf pr₂) 20 -- we use intro_k to be able to execute gcd efficiently in the kernel
local attribute pair_nat.lt.wf [instance] -- instance will not be saved in .olean
infixl [local] `≺`:50 := pair_nat.lt
local infixl `≺`:50 := pair_nat.lt
private definition gcd.lt.dec (x y₁ : nat) : (succ y₁, x mod succ y₁) ≺ (x, succ y₁) :=
mod_lt (succ_pos y₁)

View file

@ -12,7 +12,7 @@ import init.logic
-- We need some of the following definitions asap when "initializing" Lean.
variables {A B : Type} (R : B → B → Prop)
infix [local] `≺`:50 := R
local infix `≺`:50 := R
definition reflexive := ∀x, x ≺ x

View file

@ -118,7 +118,7 @@
;; modifiers
(,(rx (or "\[persistent\]" "\[notation\]" "\[visible\]" "\[instance\]" "\[class\]" "\[parsing-only\]"
"\[coercion\]" "\[reducible\]" "\[irreducible\]" "\[wf\]" "\[whnf\]" "\[multiple-instances\]"
"\[decls\]" "\[strict\]" "\[local\]" "\[coercions\]" "\[classes\]" "\[notations\]" "\[tactic_hints\]" "\[reduce_hints\]"))
"\[decls\]" "\[strict\]" "\[coercions\]" "\[classes\]" "\[notations\]" "\[tactic_hints\]" "\[reduce_hints\]"))
. 'font-lock-doc-face)
(,(rx "\[priority" (zero-or-more (not (any "\]"))) "\]") . font-lock-doc-face)
;; tactics

View file

@ -610,15 +610,11 @@ static environment add_user_token(environment const & env, char const * val, uns
}
struct notation_modifiers {
bool m_persistent;
bool m_parse_only;
notation_modifiers():m_persistent(true), m_parse_only(false) {}
notation_modifiers():m_parse_only(false) {}
void parse(parser & p) {
while (true) {
if (p.curr_is_token(get_local_tk())) {
p.next();
m_persistent = false;
} else if (p.curr_is_token(get_parsing_only_tk())) {
if (p.curr_is_token(get_parsing_only_tk())) {
p.next();
m_parse_only = true;
} else {
@ -628,93 +624,108 @@ struct notation_modifiers {
}
};
static environment notation_cmd_core(parser & p, bool overload, bool reserve) {
check_not_in_parametric_section(p);
static environment notation_cmd_core(parser & p, bool overload, bool reserve, bool persistent) {
if (persistent)
check_not_in_parametric_section(p);
notation_modifiers mods;
mods.parse(p);
flet<bool> set_allow_local(g_allow_local, in_context(p.env()) || !mods.m_persistent);
flet<bool> set_allow_local(g_allow_local, in_context(p.env()) || !persistent);
environment env = p.env();
buffer<token_entry> new_tokens;
auto ne = parse_notation_core(p, overload, reserve, new_tokens, mods.m_parse_only);
for (auto const & te : new_tokens)
env = add_user_token(env, te, mods.m_persistent);
env = add_notation(env, ne, mods.m_persistent);
env = add_user_token(env, te, persistent);
env = add_notation(env, ne, persistent);
return env;
}
static environment mixfix_cmd(parser & p, mixfix_kind k, bool overload, bool reserve) {
check_not_in_parametric_section(p);
static environment mixfix_cmd(parser & p, mixfix_kind k, bool overload, bool reserve, bool persistent) {
if (persistent)
check_not_in_parametric_section(p);
notation_modifiers mods;
mods.parse(p);
flet<bool> set_allow_local(g_allow_local, in_context(p.env()) || !mods.m_persistent);
flet<bool> set_allow_local(g_allow_local, in_context(p.env()) || !persistent);
auto nt = parse_mixfix_notation(p, k, overload, reserve, mods.m_parse_only);
environment env = p.env();
if (nt.second)
env = add_user_token(env, *nt.second, mods.m_persistent);
env = add_notation(env, nt.first, mods.m_persistent);
env = add_user_token(env, *nt.second, persistent);
env = add_notation(env, nt.first, persistent);
return env;
}
static environment notation_cmd(parser & p) {
bool overload = !in_context(p.env());
bool reserve = false;
return notation_cmd_core(p, overload, reserve);
bool persistent = true;
return notation_cmd_core(p, overload, reserve, persistent);
}
static environment infixl_cmd(parser & p) {
bool overload = !in_context(p.env());
bool reserve = false;
return mixfix_cmd(p, mixfix_kind::infixl, overload, reserve);
bool persistent = true;
return mixfix_cmd(p, mixfix_kind::infixl, overload, reserve, persistent);
}
static environment infixr_cmd(parser & p) {
bool overload = !in_context(p.env());
bool reserve = false;
return mixfix_cmd(p, mixfix_kind::infixr, overload, reserve);
bool persistent = true;
return mixfix_cmd(p, mixfix_kind::infixr, overload, reserve, persistent);
}
static environment postfix_cmd(parser & p) {
bool overload = !in_context(p.env());
bool reserve = false;
return mixfix_cmd(p, mixfix_kind::postfix, overload, reserve);
bool persistent = true;
return mixfix_cmd(p, mixfix_kind::postfix, overload, reserve, persistent);
}
static environment prefix_cmd(parser & p) {
bool overload = !in_context(p.env());
bool reserve = false;
return mixfix_cmd(p, mixfix_kind::prefix, overload, reserve);
bool persistent = true;
return mixfix_cmd(p, mixfix_kind::prefix, overload, reserve, persistent);
}
// auxiliary procedure used by local_notation_cmd and reserve_cmd
static environment dispatch_notation_cmd(parser & p, bool overload, bool reserve, bool persistent) {
if (p.curr_is_token(get_notation_tk())) {
p.next();
return notation_cmd_core(p, overload, reserve, persistent);
} else if (p.curr_is_token(get_infixl_tk())) {
p.next();
return mixfix_cmd(p, mixfix_kind::infixl, overload, reserve, persistent);
} else if (p.curr_is_token(get_infix_tk())) {
p.next();
return mixfix_cmd(p, mixfix_kind::infixl, overload, reserve, persistent);
} else if (p.curr_is_token(get_infixr_tk())) {
p.next();
return mixfix_cmd(p, mixfix_kind::infixr, overload, reserve, persistent);
} else if (p.curr_is_token(get_prefix_tk())) {
p.next();
return mixfix_cmd(p, mixfix_kind::prefix, overload, reserve, persistent);
} else if (p.curr_is_token(get_postfix_tk())) {
p.next();
return mixfix_cmd(p, mixfix_kind::postfix, overload, reserve, persistent);
} else {
throw parser_error("invalid local/reserve notation, 'infix', 'infixl', 'infixr', 'prefix', "
"'postfix' or 'notation' expected", p.pos());
}
}
environment local_notation_cmd(parser & p) {
// TODO(Leo)
return p.env();
bool overload = !in_context(p.env());
bool reserve = false;
bool persistent = false;
return dispatch_notation_cmd(p, overload, reserve, persistent);
}
static environment reserve_cmd(parser & p) {
bool overload = false;
bool reserve = true;
if (p.curr_is_token(get_notation_tk())) {
p.next();
return notation_cmd_core(p, overload, reserve);
} else if (p.curr_is_token(get_infixl_tk())) {
p.next();
return mixfix_cmd(p, mixfix_kind::infixl, overload, reserve);
} else if (p.curr_is_token(get_infix_tk())) {
p.next();
return mixfix_cmd(p, mixfix_kind::infixl, overload, reserve);
} else if (p.curr_is_token(get_infixr_tk())) {
p.next();
return mixfix_cmd(p, mixfix_kind::infixr, overload, reserve);
} else if (p.curr_is_token(get_prefix_tk())) {
p.next();
return mixfix_cmd(p, mixfix_kind::prefix, overload, reserve);
} else if (p.curr_is_token(get_postfix_tk())) {
p.next();
return mixfix_cmd(p, mixfix_kind::postfix, overload, reserve);
} else {
throw parser_error("invalid reserve notation, 'infix', 'infixl', 'infixr', 'prefix', "
"'postfix' or 'notation' expected", p.pos());
}
bool overload = false;
bool reserve = true;
bool persistent = true;
return dispatch_notation_cmd(p, overload, reserve, persistent);
}
static environment precedence_cmd(parser & p) {

View file

@ -90,7 +90,7 @@ void init_token_table(token_table & t) {
{"theorem", "axiom", "variable", "protected", "private", "opaque", "definition", "example", "coercion",
"variables", "parameter", "parameters", "constant", "constants", "[persistent]", "[visible]", "[instance]",
"[off]", "[on]", "[none]", "[class]", "[coercion]", "[reducible]", "[irreducible]", "[parsing-only]", "[multiple-instances]",
"evaluate", "check", "eval", "[wf]", "[whnf]", "[strict]", "[local]", "[priority", "print", "end", "namespace", "section", "prelude",
"evaluate", "check", "eval", "[wf]", "[whnf]", "[strict]", "[priority", "print", "end", "namespace", "section", "prelude",
"import", "inductive", "record", "structure", "module", "universe", "universes", "local",
"precedence", "reserve", "infixl", "infixr", "infix", "postfix", "prefix", "notation", "context",
"exit", "set_option", "open", "export", "calc_subst", "calc_refl", "calc_trans", "calc_symm", "tactic_hint",

View file

@ -101,7 +101,6 @@ static name * g_prefix = nullptr;
static name * g_notation = nullptr;
static name * g_call = nullptr;
static name * g_persistent = nullptr;
static name * g_local = nullptr;
static name * g_root = nullptr;
static name * g_fields = nullptr;
static name * g_trust = nullptr;
@ -201,7 +200,6 @@ void initialize_tokens() {
g_notation = new name("notation");
g_call = new name("call");
g_persistent = new name("[persistent]");
g_local = new name("[local]");
g_root = new name("_root_");
g_fields = new name("fields");
g_trust = new name("trust");
@ -209,7 +207,6 @@ void initialize_tokens() {
void finalize_tokens() {
delete g_persistent;
delete g_local;
delete g_root;
delete g_fields;
delete g_trust;
@ -402,7 +399,6 @@ name const & get_prefix_tk() { return *g_prefix; }
name const & get_notation_tk() { return *g_notation; }
name const & get_call_tk() { return *g_call; }
name const & get_persistent_tk() { return *g_persistent; }
name const & get_local_tk() { return *g_local; }
name const & get_root_tk() { return *g_root; }
name const & get_fields_tk() { return *g_fields; }
name const & get_trust_tk() { return *g_trust; }

View file

@ -103,7 +103,6 @@ name const & get_prefix_tk();
name const & get_notation_tk();
name const & get_call_tk();
name const & get_persistent_tk();
name const & get_local_tk();
name const & get_root_tk();
name const & get_fields_tk();
name const & get_trust_tk();

View file

@ -33,7 +33,7 @@ inv_image lt tree_forest_height
definition tree_forest.subterm.wf [instance] (A : Type) : well_founded (@tree_forest.subterm A) :=
inv_image.wf tree_forest_height lt.wf
infix [local] `≺`:50 := tree_forest.subterm
local infix `≺`:50 := tree_forest.subterm
definition tree_forest.height_lt.node {A : Type} (a : A) (f : forest A) : sum.inr f ≺ sum.inl (tree.node a f) :=
have aux : forest.height f < tree.height (tree.node a f), from

View file

@ -3,7 +3,7 @@ import logic
section
variables {A : Type}
variables f : A → A → A
infixl [local] `+++`:10 := f
local infixl `+++`:10 := f
variables a b c : A
check f a b