macros: move examples into separate chapters. Enable playpen.
diff --git a/.gitignore b/.gitignore
index 482a026..2e99eab 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
bin/*
stage/*
+*~
diff --git a/examples/staging/macros/designators.rs b/examples/staging/macros/arguments/designators.rs
similarity index 100%
rename from examples/staging/macros/designators.rs
rename to examples/staging/macros/arguments/designators.rs
diff --git a/examples/staging/macros/arguments/input.md b/examples/staging/macros/arguments/input.md
new file mode 100644
index 0000000..93f7efa
--- /dev/null
+++ b/examples/staging/macros/arguments/input.md
@@ -0,0 +1,18 @@
+The arguments of a macro are prefixed by a dollar sign `$` and type annotated
+with a *designator*:
+
+{designators.play}
+
+This is a list of all the designators:
+
+* `block`
+* `expr` is used for expressions
+* `ident` is used for variable/function names
+* `item`
+* `matchers` (lhs of the => in macro rules)
+* `pat`
+* `path`
+* `stmt`
+* `tt` (*token tree*) is used for operators and tokens
+* `ty` (*type*)
+
diff --git a/examples/staging/macros/input.md b/examples/staging/macros/input.md
index 729882d..819a4a5 100644
--- a/examples/staging/macros/input.md
+++ b/examples/staging/macros/input.md
@@ -5,45 +5,5 @@
Macros are created using the `macro_rules!` macro.
-{simple.rs}
+{simple.play}
-{simple.out}
-
-The arguments of a macro are prefixed by a dollar sign `$` and type annotated
-with a *designator*.
-
-{designators.rs}
-
-{designators.out}
-
-Macros can be overloaded to accept different combinations of arguments.
-
-{overload.rs}
-
-{overload.out}
-
-Macros can use `+` in the argument list, to indicate that an argument may
-repeat at least once, or `*`, to indicate that the argument may repeat zero or
-more times.
-
-{repeat.rs}
-
-{repeat.out}
-
-Macros allow writing DRY code, by factoring out the common parts of functions
-and/or test suites. Here is an example that implements and tests the `+=`, `*=`
-and `-=` operators on `Vec<T>`.
-
-{dry.rs}
-
-{dry.out}
-
-```
-$ rustc --test dry.rs && ./dry
-running 3 tests
-test test::mul_assign ... ok
-test test::add_assign ... ok
-test test::sub_assign ... ok
-
-test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured
-```
diff --git a/examples/staging/macros/repetition/input.md b/examples/staging/macros/repetition/input.md
new file mode 100644
index 0000000..bcc71bb
--- /dev/null
+++ b/examples/staging/macros/repetition/input.md
@@ -0,0 +1,51 @@
+Macros can also match and return repeated patterns. This is similar but
+different from a regex. `$($x:expr),+` is a matching example. It uses the
+`$()` grouping operator to mark `x` as repeatable. `+` or `*` denotes
+repetition amount; one or more and zero or more respectively. `,`
+is the only separator token available.
+
+```rust
+// The separator only checks separation; this is
+// not a regex.
+$($x:expr),+ // matches `1, 2, 3` but not `1, 2,`
+```
+
+When returned, it uses a similar notation: `$($x:expr),+` => `$($x),+`
+however, a returned list will not be re-expanded whereas, matching
+will find the whole thing.
+
+```rust
+#![feature(macro_rules)]
+
+macro_rules! echo_broken {
+ // Attempt to match and return with one compact expression
+ ($($x:expr),+) => { $($x),+ };
+}
+
+macro_rules! echo_works {
+ ($x:expr) => { $x }; // one element list
+ // $x is the first element. `$($y:expr),+` is the tail
+ ($x:expr, $($y:expr),+) => {
+ // pass the tail to `echo_works` so it can be expanded
+ ($x, echo_works!($($y),+))
+ };
+}
+
+fn main() {
+ println!("{}", echo_broken!(1u)); // Works for single elements
+
+ // Errors: `,` ignored. A list is never re-expanded so when
+ // the `,` is reached, the rest of the line is ignored.
+ // Rust does not allow incomplete expansion, so it errors. To
+ // handle this, recursion is needed.
+ //println!("{}", echo_broken!(1u, 2u));
+
+ println!("{}", echo_works!(1u));
+ // Would like it flat but it nests the results...
+ println!("{}", echo_works!(1u, 2u, 3u, 4u, 5u, 6u));
+}
+```
+
+Another example making a min macro:
+{repeat.play}
+
diff --git a/examples/staging/macros/repeat.rs b/examples/staging/macros/repetition/repeat.rs
similarity index 100%
rename from examples/staging/macros/repeat.rs
rename to examples/staging/macros/repetition/repeat.rs
diff --git a/examples/staging/macros/separators/input.md b/examples/staging/macros/separators/input.md
new file mode 100644
index 0000000..82fb09b
--- /dev/null
+++ b/examples/staging/macros/separators/input.md
@@ -0,0 +1,4 @@
+Macros can be overloaded to accept different combinations of arguments.
+
+{overload.play}
+
diff --git a/examples/staging/macros/overload.rs b/examples/staging/macros/separators/overload.rs
similarity index 100%
rename from examples/staging/macros/overload.rs
rename to examples/staging/macros/separators/overload.rs
diff --git a/examples/staging/macros/dry.rs b/examples/staging/macros/test_suite/dry.rs
similarity index 95%
rename from examples/staging/macros/dry.rs
rename to examples/staging/macros/test_suite/dry.rs
index d28eae4..5bc52db 100644
--- a/examples/staging/macros/dry.rs
+++ b/examples/staging/macros/test_suite/dry.rs
@@ -1,6 +1,7 @@
#![feature(macro_rules)]
macro_rules! assert_equal_len {
+ // The `tt` (token tree) designator is used for operators and tokens
($a:ident, $b: ident, $func:ident, $op:tt) => {
assert!($a.len() == $b.len(),
"{}: dimension mismatch: {} {} {}",
@@ -59,3 +60,4 @@
test!(mul_assign, 2u, 3u, 6u)
test!(sub_assign, 3u, 2u, 1u)
}
+
diff --git a/examples/staging/macros/test_suite/input.md b/examples/staging/macros/test_suite/input.md
new file mode 100644
index 0000000..cd965b0
--- /dev/null
+++ b/examples/staging/macros/test_suite/input.md
@@ -0,0 +1,16 @@
+Macros allow writing DRY code, by factoring out the common parts of functions
+and/or test suites. Here is an example that implements and tests the `+=`, `*=`
+and `-=` operators on `Vec<T>`.
+
+{dry.play}
+
+```
+$ rustc --test dry.rs && ./dry
+running 3 tests
+test test::mul_assign ... ok
+test test::add_assign ... ok
+test test::sub_assign ... ok
+
+test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured
+```
+
diff --git a/examples/staging/macros/variable_args/input.md b/examples/staging/macros/variable_args/input.md
new file mode 100644
index 0000000..d8d0b20
--- /dev/null
+++ b/examples/staging/macros/variable_args/input.md
@@ -0,0 +1,13 @@
+Variadic (variable number of arguments) functions can be implemented via
+macros. Here we implement a macro similar to Python's overloaded
+[range](https://docs.python.org/3/tutorial/controlflow.html#the-range-function) function:
+
+```rust
+// Here is how it should work
+range!(10i) // Returns 0..9
+range!(3i, 10) // Returns 3..9
+range!(3i, 10, 2) // Returns 3, 5, 7, 9 (3..9 in increments of 2)
+```
+
+{range.play}
+
diff --git a/examples/staging/macros/variable_args/range.rs b/examples/staging/macros/variable_args/range.rs
new file mode 100644
index 0000000..5eb4205
--- /dev/null
+++ b/examples/staging/macros/variable_args/range.rs
@@ -0,0 +1,28 @@
+#![feature(macro_rules)]
+
+use std::iter::range_step;
+
+// range! will take up to 3 inputs and call range
+// function depending on inputs
+macro_rules! range (
+ ($end:expr) => {
+ range(0, $end)
+ };
+ ($start:expr, $end:expr) => {
+ range($start, $end)
+ };
+ ($start:expr, $end:expr, $step:expr) => {
+ range_step($start, $end, $step)
+ };
+)
+
+fn main() {
+ for i in range!(10i) { print!("{}", i) }
+ println!("");
+
+ for i in range!(3i, 10) { print!("{}", i) }
+ println!("");
+
+ for i in range!(3i, 10, 2) { print!("{}", i) }
+}
+
diff --git a/examples/structure.json b/examples/structure.json
index 3454e7f..207823a 100644
--- a/examples/structure.json
+++ b/examples/structure.json
@@ -103,7 +103,13 @@
{ "id": "staging", "title": "Staging Area", "children": [
{ "id": "bench", "title": "Benchmarking", "children": null },
{ "id": "ffi", "title": "Foreign Function Interface", "children": null },
- { "id": "macros", "title": "macro_rules!", "children": null },
+ { "id": "macros", "title": "macro_rules!", "children": [
+ { "id": "arguments", "title": "Arguments and designators", "children": null },
+ { "id": "variable_args", "title": "Variadic macros", "children": null },
+ { "id": "separators", "title": "Variable separator options", "children": null },
+ { "id": "repetition", "title": "Repetition and expansion", "children": null },
+ { "id": "test_suite", "title": "Generating generic test suite implementations", "children": null }
+ ] },
{ "id": "rand", "title": "Random", "children": null },
{ "id": "simd", "title": "SIMD", "children": null },
{ "id": "test", "title": "Testing", "children": null },