Skip to content

Commit f7b803c

Browse files
committed
---
yaml --- r: 32398 b: refs/heads/dist-snap c: 69b363e h: refs/heads/master v: v3
1 parent 1b44dac commit f7b803c

File tree

4 files changed

+164
-152
lines changed

4 files changed

+164
-152
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
88
refs/heads/try2: d0c6ce338884ee21843f4b40bf6bf18d222ce5df
99
refs/heads/incoming: d9317a174e434d4c99fc1a37fd7dc0d2f5328d37
10-
refs/heads/dist-snap: 9db44454541a9bcf1b1bed6cdda3c3213f355a25
10+
refs/heads/dist-snap: 69b363e02a29184641789598877409844736a7a1
1111
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1212
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
# Macros
2+
3+
Functions are the programmer's primary tool of abstraction, but there are
4+
cases in which they are insufficient, because the programmer wants to
5+
abstract over concepts not represented as values. Consider the following
6+
example:
7+
8+
~~~~
9+
# enum t { special_a(uint), special_b(uint) };
10+
# fn f() -> uint {
11+
# let input_1 = special_a(0), input_2 = special_a(0);
12+
match input_1 {
13+
special_a(x) => { return x; }
14+
_ => {}
15+
}
16+
// ...
17+
match input_2 {
18+
special_b(x) => { return x; }
19+
_ => {}
20+
}
21+
# return 0u;
22+
# }
23+
~~~~
24+
25+
This code could become tiresome if repeated many times. However, there is
26+
no reasonable function that could be written to solve this problem. In such a
27+
case, it's possible to define a macro to solve the problem. Macros are
28+
lightweight custom syntax extensions, themselves defined using the
29+
`macro_rules!` syntax extension:
30+
31+
~~~~
32+
# enum t { special_a(uint), special_b(uint) };
33+
# fn f() -> uint {
34+
# let input_1 = special_a(0), input_2 = special_a(0);
35+
macro_rules! early_return(
36+
($inp:expr $sp:ident) => ( //invoke it like `(input_5 special_e)`
37+
match $inp {
38+
$sp(x) => { return x; }
39+
_ => {}
40+
}
41+
);
42+
);
43+
// ...
44+
early_return!(input_1 special_a);
45+
// ...
46+
early_return!(input_2 special_b);
47+
# return 0;
48+
# }
49+
~~~~
50+
51+
Macros are defined in pattern-matching style:
52+
53+
## Invocation syntax
54+
55+
On the left-hand-side of the `=>` is the macro invocation syntax. It is
56+
free-form, excepting the following rules:
57+
58+
1. It must be surrounded in parentheses.
59+
2. `$` has special meaning.
60+
3. The `()`s, `[]`s, and `{}`s it contains must balance. For example, `([)` is
61+
forbidden.
62+
63+
To take as an argument a fragment of Rust code, write `$` followed by a name
64+
(for use on the right-hand side), followed by a `:`, followed by the sort of
65+
fragment to match (the most common ones are `ident`, `expr`, `ty`, `pat`, and
66+
`block`). Anything not preceeded by a `$` is taken literally. The standard
67+
rules of tokenization apply,
68+
69+
So `($x:ident => (($e:expr)))`, though excessively fancy, would create a macro
70+
that could be invoked like `my_macro!(i=>(( 2+2 )))`.
71+
72+
## Transcription syntax
73+
74+
The right-hand side of the `=>` follows the same rules as the left-hand side,
75+
except that `$` need only be followed by the name of the syntactic fragment
76+
to transcribe.
77+
78+
The right-hand side must be surrounded by delimiters of some kind, and must be
79+
an expression; currently, user-defined macros can only be invoked in
80+
expression position (even though `macro_rules!` itself can be in item
81+
position).
82+
83+
## Multiplicity
84+
85+
### Invocation
86+
87+
Going back to the motivating example, suppose that we wanted each invocation
88+
of `early_return` to potentially accept multiple "special" identifiers. The
89+
syntax `$(...)*` accepts zero or more occurences of its contents, much like
90+
the Kleene star operator in regular expressions. It also supports a separator
91+
token (a comma-separated list could be written `$(...),*`), and `+` instead of
92+
`*` to mean "at least one".
93+
94+
~~~~
95+
# enum t { special_a(uint),special_b(uint),special_c(uint),special_d(uint)};
96+
# fn f() -> uint {
97+
# let input_1 = special_a(0), input_2 = special_a(0);
98+
macro_rules! early_return(
99+
($inp:expr, [ $($sp:ident)|+ ]) => (
100+
match $inp {
101+
$(
102+
$sp(x) => { return x; }
103+
)+
104+
_ => {}
105+
}
106+
);
107+
);
108+
// ...
109+
early_return!(input_1, [special_a|special_c|special_d]);
110+
// ...
111+
early_return!(input_2, [special_b]);
112+
# return 0;
113+
# }
114+
~~~~
115+
116+
### Transcription
117+
118+
As the above example demonstrates, `$(...)*` is also valid on the right-hand
119+
side of a macro definition. The behavior of Kleene star in transcription,
120+
especially in cases where multiple stars are nested, and multiple different
121+
names are involved, can seem somewhat magical and intuitive at first. The
122+
system that interprets them is called "Macro By Example". The two rules to
123+
keep in mind are (1) the behavior of `$(...)*` is to walk through one "layer"
124+
of repetitions for all of the `$name`s it contains in lockstep, and (2) each
125+
`$name` must be under at least as many `$(...)*`s as it was matched against.
126+
If it is under more, it'll will be repeated, as appropriate.
127+
128+
## Parsing limitations
129+
130+
The parser used by the macro system is reasonably powerful, but the parsing of
131+
Rust syntax is restricted in two ways:
132+
133+
1. The parser will always parse as much as possible. For example, if the comma
134+
were omitted from the syntax of `early_return!` above, `input_1 [` would've
135+
been interpreted as the beginning of an array index. In fact, invoking the
136+
macro would have been impossible.
137+
2. The parser must have eliminated all ambiguity by the time it reaches a
138+
`$name:fragment_specifier`. This most often affects them when they occur in
139+
the beginning of, or immediately after, a `$(...)*`; requiring a distinctive
140+
token in front can solve the problem.
141+
142+
## A final note
143+
144+
Macros, as currently implemented, are not for the faint of heart. Even
145+
ordinary syntax errors can be more difficult to debug when they occur inside
146+
a macro, and errors caused by parse problems in generated code can be very
147+
tricky. Invoking the `log_syntax!` macro can help elucidate intermediate
148+
states, using `trace_macros!(true)` will automatically print those
149+
intermediate states out, and using `--pretty expanded` as an argument to the
150+
compiler will show the result of expansion.
151+
152+

branches/dist-snap/doc/tutorial.md

Lines changed: 0 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -1897,157 +1897,6 @@ This makes it possible to rebind a variable without actually mutating
18971897
it, which is mostly useful for destructuring (which can rebind, but
18981898
not assign).
18991899

1900-
# Macros
1901-
1902-
Functions are the programmer's primary tool of abstraction, but there are
1903-
cases in which they are insufficient, because the programmer wants to
1904-
abstract over concepts not represented as values. Consider the following
1905-
example:
1906-
1907-
~~~~
1908-
# enum t { special_a(uint), special_b(uint) };
1909-
# fn f() -> uint {
1910-
# let input_1 = special_a(0), input_2 = special_a(0);
1911-
match input_1 {
1912-
special_a(x) => { return x; }
1913-
_ => {}
1914-
}
1915-
// ...
1916-
match input_2 {
1917-
special_b(x) => { return x; }
1918-
_ => {}
1919-
}
1920-
# return 0u;
1921-
# }
1922-
~~~~
1923-
1924-
This code could become tiresome if repeated many times. However, there is
1925-
no reasonable function that could be written to solve this problem. In such a
1926-
case, it's possible to define a macro to solve the problem. Macros are
1927-
lightweight custom syntax extensions, themselves defined using the
1928-
`macro_rules!` syntax extension:
1929-
1930-
~~~~
1931-
# enum t { special_a(uint), special_b(uint) };
1932-
# fn f() -> uint {
1933-
# let input_1 = special_a(0), input_2 = special_a(0);
1934-
macro_rules! early_return(
1935-
($inp:expr $sp:ident) => ( //invoke it like `(input_5 special_e)`
1936-
match $inp {
1937-
$sp(x) => { return x; }
1938-
_ => {}
1939-
}
1940-
);
1941-
);
1942-
// ...
1943-
early_return!(input_1 special_a);
1944-
// ...
1945-
early_return!(input_2 special_b);
1946-
# return 0;
1947-
# }
1948-
~~~~
1949-
1950-
Macros are defined in pattern-matching style:
1951-
1952-
## Invocation syntax
1953-
1954-
On the left-hand-side of the `=>` is the macro invocation syntax. It is
1955-
free-form, excepting the following rules:
1956-
1957-
1. It must be surrounded in parentheses.
1958-
2. `$` has special meaning.
1959-
3. The `()`s, `[]`s, and `{}`s it contains must balance. For example, `([)` is
1960-
forbidden.
1961-
1962-
To take as an argument a fragment of Rust code, write `$` followed by a name
1963-
(for use on the right-hand side), followed by a `:`, followed by the sort of
1964-
fragment to match (the most common ones are `ident`, `expr`, `ty`, `pat`, and
1965-
`block`). Anything not preceeded by a `$` is taken literally. The standard
1966-
rules of tokenization apply,
1967-
1968-
So `($x:ident => (($e:expr)))`, though excessively fancy, would create a macro
1969-
that could be invoked like `my_macro!(i=>(( 2+2 )))`.
1970-
1971-
## Transcription syntax
1972-
1973-
The right-hand side of the `=>` follows the same rules as the left-hand side,
1974-
except that `$` need only be followed by the name of the syntactic fragment
1975-
to transcribe.
1976-
1977-
The right-hand side must be surrounded by delimiters of some kind, and must be
1978-
an expression; currently, user-defined macros can only be invoked in
1979-
expression position (even though `macro_rules!` itself can be in item
1980-
position).
1981-
1982-
## Multiplicity
1983-
1984-
### Invocation
1985-
1986-
Going back to the motivating example, suppose that we wanted each invocation
1987-
of `early_return` to potentially accept multiple "special" identifiers. The
1988-
syntax `$(...)*` accepts zero or more occurences of its contents, much like
1989-
the Kleene star operator in regular expressions. It also supports a separator
1990-
token (a comma-separated list could be written `$(...),*`), and `+` instead of
1991-
`*` to mean "at least one".
1992-
1993-
~~~~
1994-
# enum t { special_a(uint),special_b(uint),special_c(uint),special_d(uint)};
1995-
# fn f() -> uint {
1996-
# let input_1 = special_a(0), input_2 = special_a(0);
1997-
macro_rules! early_return(
1998-
($inp:expr, [ $($sp:ident)|+ ]) => (
1999-
match $inp {
2000-
$(
2001-
$sp(x) => { return x; }
2002-
)+
2003-
_ => {}
2004-
}
2005-
);
2006-
);
2007-
// ...
2008-
early_return!(input_1, [special_a|special_c|special_d]);
2009-
// ...
2010-
early_return!(input_2, [special_b]);
2011-
# return 0;
2012-
# }
2013-
~~~~
2014-
2015-
### Transcription
2016-
2017-
As the above example demonstrates, `$(...)*` is also valid on the right-hand
2018-
side of a macro definition. The behavior of Kleene star in transcription,
2019-
especially in cases where multiple stars are nested, and multiple different
2020-
names are involved, can seem somewhat magical and intuitive at first. The
2021-
system that interprets them is called "Macro By Example". The two rules to
2022-
keep in mind are (1) the behavior of `$(...)*` is to walk through one "layer"
2023-
of repetitions for all of the `$name`s it contains in lockstep, and (2) each
2024-
`$name` must be under at least as many `$(...)*`s as it was matched against.
2025-
If it is under more, it'll will be repeated, as appropriate.
2026-
2027-
## Parsing limitations
2028-
2029-
The parser used by the macro system is reasonably powerful, but the parsing of
2030-
Rust syntax is restricted in two ways:
2031-
2032-
1. The parser will always parse as much as possible. For example, if the comma
2033-
were omitted from the syntax of `early_return!` above, `input_1 [` would've
2034-
been interpreted as the beginning of an array index. In fact, invoking the
2035-
macro would have been impossible.
2036-
2. The parser must have eliminated all ambiguity by the time it reaches a
2037-
`$name:fragment_specifier`. This most often affects them when they occur in
2038-
the beginning of, or immediately after, a `$(...)*`; requiring a distinctive
2039-
token in front can solve the problem.
2040-
2041-
## A final note
2042-
2043-
Macros, as currently implemented, are not for the faint of heart. Even
2044-
ordinary syntax errors can be more difficult to debug when they occur inside
2045-
a macro, and errors caused by parse problems in generated code can be very
2046-
tricky. Invoking the `log_syntax!` macro can help elucidate intermediate
2047-
states, using `trace_macros!(true)` will automatically print those
2048-
intermediate states out, and using `--pretty expanded` as an argument to the
2049-
compiler will show the result of expansion.
2050-
20511900
# Traits
20521901

20531902
Traits are Rust's take on value polymorphism—the thing that

branches/dist-snap/mk/docs.mk

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,17 @@ doc/tutorial.html: tutorial.md doc/version_info.html doc/rust.css
8282
--include-before-body=doc/version_info.html \
8383
--output=$@
8484

85+
DOCS += doc/tutorial-macros.html
86+
doc/tutorial-macros.html: tutorial-macros.md doc/version_info.html \
87+
doc/rust.css
88+
@$(call E, pandoc: $@)
89+
$(Q)$(CFG_NODE) $(S)doc/prep.js --highlight $< | \
90+
$(CFG_PANDOC) --standalone --toc \
91+
--section-divs --number-sections \
92+
--from=markdown --to=html --css=rust.css \
93+
--include-before-body=doc/version_info.html \
94+
--output=$@
95+
8596
endif
8697
endif
8798

0 commit comments

Comments
 (0)