# Library Metatheory

```
```

Library for programming languages metatheory.

Authors: Brian Aydemir and Arthur Charguéraud, with help from Aaron Bohannon, Benjamin Pierce, Jeffrey Vaughan, Dimitrios Vytiniotis, Stephanie Weirich, and Steve Zdancewic.

Authors: Brian Aydemir and Arthur Charguéraud, with help from Aaron Bohannon, Benjamin Pierce, Jeffrey Vaughan, Dimitrios Vytiniotis, Stephanie Weirich, and Steve Zdancewic.

```
```

Require Export AdditionalTactics.

Require Export Atom.

Require Export Environment.

```
```

Decidable equality on atoms and natural numbers may be written
using natural notation.

```
```

Notation "x == y" :=

(eq_atom_dec x y) (at level 67) : metatheory_scope.

Notation "i === j" :=

(Peano_dec.eq_nat_dec i j) (at level 67) : metatheory_scope.

Common set operations may be written using infix notation.

```
```

Notation "E `union` F" :=

(Atom.AtomSet.F.union E F)

(at level 69, right associativity, format "E `union` '/' F")

: set_scope.

Notation "x `in` E" :=

(Atom.AtomSet.F.In x E) (at level 69) : set_scope.

Notation "x `notin` E" :=

(~ Atom.AtomSet.F.In x E) (at level 69) : set_scope.

The empty set may be written similarly to informal practice.

```
```

Notation "{}" :=

(Atom.AtomSet.F.empty) : metatheory_scope.

It is useful to have an abbreviation for constructing singleton
sets.

```
```

Notation singleton := (Atom.AtomSet.F.singleton).

Open the notation scopes declared above.

```
```

Open Scope metatheory_scope.

Open Scope set_scope.

```
```

Consider a rule

The tactic

If we view

`H`

(equivalently, hypothesis, constructor, lemma,
etc.) of the form ```
(forall L ..., ... -> (forall y, y `notin` L ->
P) -> ... -> Q)
```

, where `Q`

's outermost constructor is not a
`forall`

. There may be multiple hypotheses of with the indicated
form in `H`

.
The tactic

`(pick fresh x and apply H)`

applies `H`

to the current
goal, instantiating `H`

's first argument (i.e., `L`

) with the
finite set of atoms `L'`

. In each new subgoal arising from a
hypothesis of the form `(forall y, y `notin` L -> P)`

, the atom
`y`

is introduced as `x`

, and `(y `notin` L)`

is introduced using
a generated name.
If we view

`H`

as a rule that uses cofinite quantification, the
tactic can be read as picking a sufficiently fresh atom to open a
term with.
```
```

Tactic Notation

"pick" "fresh" ident(atom_name)

"excluding" constr(L)

"and" "apply" constr(H) :=

let L := beautify_fset L in

first [apply (@H L) | eapply (@H L)];

match goal with

| |- forall _, _ `notin` _ -> _ =>

let Fr := fresh "Fr" in intros atom_name Fr

| |- forall _, _ `notin` _ -> _ =>

fail 1 "because" atom_name "is already defined"

| _ =>

idtac

end.

```
```

These hints should discharge many of the freshness and inequality
goals that arise in programming language metatheory proofs, in
particular those arising from cofinite quantification.

```
```

Hint Resolve notin_empty notin_singleton notin_union.

Hint Extern 4 (_ `notin` _) => simpl_env; notin_solve.

Hint Extern 4 (_ <> _ :> atom) => simpl_env; notin_solve.