Skip to content

Commit 2ef0ed7

Browse files
committed
Add chapter on attributes.
1 parent edc2afc commit 2ef0ed7

File tree

5 files changed

+904
-0
lines changed

5 files changed

+904
-0
lines changed

lean/extra/attributes.lean

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import lean.extra.attrs.dummy
2+
import lean.extra.attrs.tag
3+
/-
4+
# Attributes
5+
6+
Attributes in Lean allows one to perform preprocessing on definitions.
7+
They are similar to Python's decorators and Rust's proc-macros.
8+
9+
Unfortunately, it turns out that attributes must be defined in a separate module, so
10+
we will bounce between this file and the files in the `attrs/` folder which
11+
contain the implementations of the attributes. We'll see you at
12+
[`./attrs/tag.lean`](./attrs/tag.lean).
13+
14+
## Using `myTag`
15+
16+
see that we've created a tagging infrastructure based on Lean's `TagAttribute`s, which exists
17+
explicitly to allow us to create 'simple' attributes that wish to keep track of
18+
definitions that have been tagged with a given attribute, and nothing more.
19+
20+
-/
21+
@[myTag]
22+
def tag1 : Int := 1
23+
24+
@[myTag]
25+
def tag2 : Int := 2
26+
27+
@[myTag]
28+
def tag3 : Int := 3
29+
30+
/-
31+
See that we can access all the declarations that have been tagged with @[myTag].
32+
This simplified mechanism exists to allow us to easily tag definitions of interest.
33+
-/
34+
35+
-- decl: tag3 | find? OfNat.ofNat.{0} Int 3 (Int.instOfNatInt 3)
36+
-- decl: tag1 | find? OfNat.ofNat.{0} Int 1 (Int.instOfNatInt 1)
37+
-- decl: tag2 | find? OfNat.ofNat.{0} Int 2 (Int.instOfNatInt 2)
38+
39+
40+
/-
41+
## Using `dummy_attr`
42+
43+
We'll see you at [`./attrs/dummy.lean`](./attrs/dummy.lean).
44+
45+
46+
We run the `dummy_attr <number>`, and we see that we get access to the
47+
attribute argument <number>, the name of the declaration (`foo`), the type
48+
of the declaration (`int`), and the value of the declaration, which
49+
is the raw syntax tree.
50+
-/
51+
52+
@[dummy_attr 0]
53+
def foo : Int := 42
54+
-- number + 1: 1
55+
-- src: foo | stx: (Attr.dummy_attr "dummy_attr" (num "0")) | kind: global
56+
-- srcDecl:
57+
-- name: foo
58+
-- type: Int
59+
-- value?: (some (OfNat.ofNat.{0} Int 42 (Int.instOfNatInt 42)))
60+
61+
62+
/-
63+
Below is an example of a declaration that does not have any value.
64+
-/
65+
66+
@[dummy_attr 52]
67+
class bar
68+
-- number + 1: 53
69+
-- src: bar | stx: (Attr.dummy_attr "dummy_attr" (num "52")) | kind: global
70+
-- srcDecl:
71+
-- name: bar
72+
-- type: Type
73+
-- value?: none
74+
75+
76+
/-
77+
## Modifying the `value` with the `around` attribute
78+
79+
We're going to write an attribute that will modify a given definition
80+
-/
81+

0 commit comments

Comments
 (0)