Skip to content

Commit

Permalink
Add hygiene chapter code background highlighting back
Browse files Browse the repository at this point in the history
  • Loading branch information
Veykril committed Sep 20, 2020
1 parent 3e93996 commit 38cc5cb
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 40 deletions.
2 changes: 1 addition & 1 deletion book.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ build-dir = "book"
default-theme = "ayu"
git-repository-url = "https://github.com/veykril/tlborm/"
# unfortunately the "Source Code Pro" font doesn't seem to work well with box characters
additional-css = ["res/code-font-patch.css"]
additional-css = ["res/code-font-patch.css", "res/rust-syntax-bg-highlight.css"]
36 changes: 36 additions & 0 deletions res/rust-syntax-bg-highlight.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
* file at the top-level directory of this distribution and at
* http://rust-lang.org/COPYRIGHT.
* With elements taken from Bootstrap v3.0.2 (MIT licensed).
*
* Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
* http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
* <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
* option. This file may not be copied, modified, or distributed
* except according to those terms.
*
* Modified by Daniel Keep.
*/


/* Code highlighting */
pre.rust .kw { color: #f92672; }
pre.rust .kw-2 { color: #f92672; }
pre.rust .prelude-ty { color: #66d9ef; }
pre.rust .number { color: #EFD6AB; }
pre.rust .string { color: #F8E9A5; }
pre.rust .self { color: #f92672; }
pre.rust .boolval { color: #EFD6AB; }
pre.rust .prelude-val { color: #66d9ef; }
pre.rust .attribute { color: #C7AFD1; }
pre.rust .attribute .ident { color: #D4BBDE; }
pre.rust .comment { color: #75715e; }
pre.rust .doccomment { color: #75715e; }
pre.rust .macro { color: #AC7FE7; }
pre.rust .macro-nonterminal { color: #CFC0E2; }
pre.rust .lifetime { color: #B76514; }
pre.rust .op { color: #f92672; }

pre.rust .synctx-0 { background-color: rgba(255, 0, 0, 0.1); }
pre.rust .synctx-1 { background-color: rgba(0, 255, 0, 0.1); }
50 changes: 11 additions & 39 deletions src/macros/minutiae/hygiene.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,12 @@ identical for the two to be considered equal.

To illustrate this, consider the following code:

```rust
macro_rules! using_a {
($e:expr) => {
{
let a = 42;
$e
}
}
}
<pre class="rust rust-example-rendered"><span class="synctx-0"><span class="macro">macro_rules</span><span class="macro">!</span> <span class="ident">using_a</span> {&#xa; (<span class="macro-nonterminal">$</span><span class="macro-nonterminal">e</span>:<span class="ident">expr</span>) <span class="op">=&gt;</span> {&#xa; {&#xa; <span class="kw">let</span> <span class="ident">a</span> <span class="op">=</span> <span class="number">42</span>;&#xa; <span class="macro-nonterminal">$</span><span class="macro-nonterminal">e</span>&#xa; }&#xa; }&#xa;}&#xa;&#xa;<span class="kw">let</span> <span class="ident">four</span> <span class="op">=</span> <span class="macro">using_a</span><span class="macro">!</span>(<span class="ident">a</span> <span class="op">/</span> <span class="number">10</span>);</span></pre>

let four = using_a!(a / 10);
```

Now, let's expand the macro invocation:
We will use the background colour to denote the syntax context. Now, let's expand the macro
invocation:

```rust,ignore
let four = {
let a = 42;
a / 10
};
```
<pre class="rust rust-example-rendered"><span class="synctx-0"><span class="kw">let</span> <span class="ident">four</span> <span class="op">=</span> </span><span class="synctx-1">{&#xa; <span class="kw">let</span> <span class="ident">a</span> <span class="op">=</span> <span class="number">42</span>;&#xa; </span><span class="synctx-0"><span class="ident">a</span> <span class="op">/</span> <span class="number">10</span></span><span class="synctx-1">&#xa;}</span><span class="synctx-0">;</span></pre>

First, recall that `macro_rules!` invocations effectively *disappear* during expansion.

Expand All @@ -44,33 +29,20 @@ error[E0425]: cannot find value `a` in this scope
| ^ not found in this scope
```

Each macro expansion is given a new, unique syntax context for its contents. As a result, there are
*two different `a`s* in the expanded code: one in the first syntax context, the second in the other.
Note that the background colour (*i.e.* syntax context) for the expanded macro *changes* as part of
expansion. Each macro expansion is given a new, unique syntax context for its contents. As a result,
there are *two different `a`s* in the expanded code: one in the first syntax context, the second in
the other. In other words, <code><span class="synctx-0">a</span></code> is not the same identifier
as <code><span class="synctx-1">a</span></code>, however similar they may appear.

That said, tokens that were substituted *into* the expanded output *retain* their original syntax
context (by virtue of having been provided to the macro as opposed to being part of the macro itself).
Thus, the solution is to modify the macro as follows:

```rust
macro_rules! using_a {
($a:ident, $e:expr) => {
{
let $a = 42;
$e
}
}
}

let four = using_a!(a, a / 10);
```
<pre class="rust rust-example-rendered"><span class="synctx-0"><span class="macro">macro_rules</span><span class="macro">!</span> <span class="ident">using_a</span> {&#xa; (<span class="macro-nonterminal">$</span><span class="macro-nonterminal">a</span>:<span class="ident">ident</span>, <span class="macro-nonterminal">$</span><span class="macro-nonterminal">e</span>:<span class="ident">expr</span>) <span class="op">=&gt;</span> {&#xa; {&#xa; <span class="kw">let</span> <span class="macro-nonterminal">$</span><span class="macro-nonterminal">a</span> <span class="op">=</span> <span class="number">42</span>;&#xa; <span class="macro-nonterminal">$</span><span class="macro-nonterminal">e</span>&#xa; }&#xa; }&#xa;}&#xa;&#xa;<span class="kw">let</span> <span class="ident">four</span> <span class="op">=</span> <span class="macro">using_a</span><span class="macro">!</span>(<span class="ident">a</span>, <span class="ident">a</span> <span class="op">/</span> <span class="number">10</span>);</span></pre>

Which, upon expansion becomes:

```rust,ignore
let four = {
let a = 42;
a / 10
};
```
<pre class="rust rust-example-rendered"><span class="synctx-0"><span class="kw">let</span> <span class="ident">four</span> <span class="op">=</span> </span><span class="synctx-1">{&#xa; <span class="kw">let</span> </span><span class="synctx-0"><span class="ident">a</span></span><span class="synctx-1"> <span class="op">=</span> <span class="number">42</span>;&#xa; </span><span class="synctx-0"><span class="ident">a</span> <span class="op">/</span> <span class="number">10</span></span><span class="synctx-1">&#xa;}</span><span class="synctx-0">;</span></pre>

The compiler will accept this code because there is only one `a` being used.

0 comments on commit 38cc5cb

Please sign in to comment.