blob: 972e7cc13bdf0e07f3758bb707d4f3cbed0e036f (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
% Macro Hygiene rules and notes
Use-cases
=========
A variable defined within the macro won't collide with one in a capture
```rust
macro_rules! foo {
($v:expr) => {{ let a = 123; a + $v }};
}
fn bar(a: usize) -> usize {
// `a` here must resolve to the argument, not the macro parameter
foo!(a)
}
```
Macros within functions can access values defined before the invocation
```rust
fn bar(a: usize) -> usize {
let b = 1;
macro_rules! foo {
($v:expr) => {{ a + b + $v }};
}
let a = 123;
// `a` here must resolve to the local above, while the one in the macro resolves to the argument
foo!(a)
}
```
Macros in outer scope can access any outer-scope name
Identifiers introduced within macros are inaccessible outside
```rust
fn bar() {
macro_rules! foo {
($v:expr) => {let a = $v;};
}
foo!(123);
//let b = a; // ERROR
}
```
Implementation Notes
===================
Idea 1: Index list
-------------------
Lexer maintains a stack of counts - incremented after every TT end (closing bracket) and for every IDENT lexed. The stack grows into each TT.
This stack is the hygiene information for an identifier. During lookup a symbol is only usable if its hygiene information is a superset or before yours.
```
if( item_hygine[..-1].is_subset_of(my_hygine) && item_hygiene[-1] < my_hygiene[item_hygiene.len] ) {
/* allowed */
}
```
Hygiene storage points:
- Relative paths (of the leading node)
- Pattern bindings (variable definitions)
- _TODO: Where else?_
- ?Generic definitions
- Items? (when would that be checked? They're "globally" addressable)
Problem: Destructuring patterns end up with an incorrect hygiene using this system.
Idea 2: Hygiene is directly related to the parser state
--------------------------
- Each lexer has a hygiene tag
- Token trees carry with them the hygiene tag for the contained tokens
- :ident captures a TT with associated hygiene context
<!-- vim: ft=markdown
-->
|