17-scopes.M1pp (1588B)
1 # Lexical scopes: `::name` / `&::name` rewrite at emit time against the 2 # current scope stack, joined by `__`. Resolution is anaphoric: a `::foo` 3 # token inside a macro body resolves against the caller's scope, not the 4 # macro's expansion id. 5 # 6 # Covers: 7 # - empty-stack pass-through: `::foo` -> `:foo`, `&::bar` -> `&bar` 8 # - basic scope: `::start` -> `:parse_number__start` 9 # - nested scopes: `::a` under [outer, inner] -> `:outer__inner__a` 10 # - scope name from a macro argument (loop_scoped pattern) 11 # - anaphoric macros: %break / %continue reach the caller's innermost scope 12 # - nested scope-introducing macros: innermost scope wins for %break 13 # - hygienic `:@` and anaphoric `::` coexist in one macro 14 15 %macro loop_scoped(name, body) 16 %scope name 17 ::top 18 body 19 LA_BR &::top 20 B 21 ::end 22 %endscope 23 %endm 24 25 %macro break() 26 LA_BR &::end 27 B 28 %endm 29 30 %macro continue() 31 LA_BR &::top 32 B 33 %endm 34 35 %macro while_scoped_nez(name, ra, body) 36 %scope name 37 LA_BR &@top 38 B 39 :@body 40 body 41 :@top 42 LA_BR &@body 43 BNEZ ra 44 ::end 45 %endscope 46 %endm 47 48 # Empty-stack pass-through. 49 ::foo 50 &::bar 51 52 # Basic scope. 53 %scope parse_number 54 ::start 55 LA_BR &::done 56 BEQZ a0 57 ::done 58 ERET 59 %endscope 60 61 # Nested scopes. 62 %scope outer 63 ::before 64 %scope inner 65 ::a 66 LA_BR &::a 67 B 68 %endscope 69 ::after 70 %endscope 71 72 # Scope name from macro arg; anaphoric %break / %continue. 73 %loop_scoped(scan, { 74 LI t0, 0 75 %break() 76 %continue() 77 }) 78 79 # Nested scope-introducing macro intercepts inner %break. 80 %loop_scoped(outer, { 81 %loop_scoped(inner, { 82 %break() 83 }) 84 %break() 85 }) 86 87 # Hygienic `@` and anaphoric `::` together. 88 %while_scoped_nez(retry, a0, { 89 LI t1, 1 90 %break() 91 }) 92 93 END