# What variables (like @type) are available in macros?

**URL:** <https://forum.crystal-lang.org/t/what-variables-like-type-are-available-in-macros/6233>\
**Category:** Help & Support\
**Created:** [December 21, 2023, 10:50am UTC](https://forum.crystal-lang.org/t/what-variables-like-type-are-available-in-macros/6233 "2023-12-21T10:50:55Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jochen](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jochen/32/3490_2.png) [@Jochen](https://forum.crystal-lang.org/u/Jochen)\
**Post date:** [December 21, 2023, 10:50am UTC](https://forum.crystal-lang.org/t/what-variables-like-type-are-available-in-macros/6233/1 "2023-12-21T10:50:55Z")

</div>

Hi, I read about @type in macros in the docs, and found @def in the code, but are there any other variables available?

I’m preparing a pull request to update the docs, if there are any others that should be added it would be nice to know about them.

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [December 21, 2023, 11:18am UTC](https://forum.crystal-lang.org/t/what-variables-like-type-are-available-in-macros/6233/2 "2023-12-21T11:18:43Z")

</div>

That’s great, thanks for picking this up 🫶

There’s also `@top_level` which refers to the `Program` i.e. the top level scope.  
All macro meta vars are defined in a single place in the macro interpreter:

> <https://github.com/crystal-lang/crystal/blob/b41fda9081f6118fca23f9623010c0bd28361114/src/compiler/crystal/macros/interpreter.cr#L534-L546>

There’s an additional var, `@caller` coming in ([Expose macro `Call` context via new `@caller` macro ivar by Blacksmoke16 · Pull Request #14048 · crystal-lang/crystal · GitHub](https://github.com/crystal-lang/crystal/pull/14048)) and it already has a docs PR: [Document new `@caller` macro ivar by Blacksmoke16 · Pull Request #724 · crystal-lang/crystal-book · GitHub](https://github.com/crystal-lang/crystal-book/pull/724)  
You might want to start working on top of that (not required, but could be easier in order to incorporate everything).

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [December 21, 2023, 11:20am UTC](https://forum.crystal-lang.org/t/what-variables-like-type-are-available-in-macros/6233/3 "2023-12-21T11:20:52Z")

</div>

And please note that the semantics of `@type` are a bit… _wanky_. This may need refinement.

> <https://github.com/crystal-lang/crystal/issues/14060>
>
> The \[documentation for \`@type\`\](https://crystal-lang.org/reference/1.10/syntax\_a…nd\_semantics/macros/index.html#type-information) reads:
> \> When a macro is invoked you can access the current scope, or type, with a special instance variable: \`@type\`. \[...\]
> \> Note that \`@type\` is always the \*instance\* type, even when the macro is invoked in a class method.
> 
> This is a bit unspecific about what "current scope" actually means. It could be the scope where the macro is defined or the caller scope.
> The note about the instance type seems to point towards the latter, though because it doesn't seem to make sense for the macro scope.
> The attached example also shows "current scope" as the caller's scope. However, this was added at a later point (in https://github.com/crystal-lang/crystal-book/pull/153) and just documents the actual behaviour, not necessarily the original intention.
> 
> This is quite different from \`@type\` in a \[macro method\](https://crystal-lang.org/reference/1.10/syntax\_and\_semantics/macros/macro\_methods.html) (a \`def\` with \`{% @type %}\`) which refers to the def's scope.
> 
> Either way, the actual behaviour is quite surprising. The caller scope semantics seems to apply only in macros defined in the top-level scope. Otherwise \`@type\` actually refers to the macro's scope!
> 
> In the following example, the caller's scope would be \`\<Program\>\` and \`C\`, respectively. But \`@type\` in \`M.foo\` is always \`M\`.
> 
> \`\`\`cr
> module M
> macro foo
> {% p @type %}
> end
> end
> 
> macro bar
> {% p @type %}
> end
> 
> bar # =\> \<Program\>
> M.foo # =\> M
> 
> class C
> bar # =\> C
> M.foo # =\> M
> end
> \`\`\`
> 
> This seems pretty wrong. The semantics of \`@type\` should not depend on whether the macro is defined in the top-level scope or not.
> 
> However, it's not immediately clear which semantics are actually intended / "correct". The documentation seems to indicate the caller's scope, but that contradics with \`@type\` in macro methods. It's quite disturbing for the same feature to swap semantics depending on context.
> 
> A related discussion is the introduction of the \`@caller\` meta var (#14048). It references a macro's caller. A reference to the caller's scope could be well integrated for example as \`@caller\_scope\`, \`@caller.@scope\` or the like (IMO \`scope\` fits better than \`type\` and clearly distinguishes from \`@type\`.
> 
> So I think I would tend to prefer \`@type\` to mean the macro's scope as the ideal semantics, exactly like in macro methods.
> 
> But it's not trivial to resolve this to a congruent state either way because it may break existing code depending on one semantic or the other.

---

<div class="post-metadata">

**Author:** ![Jochen](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jochen/32/3490_2.png) [@Jochen](https://forum.crystal-lang.org/u/Jochen)\
**Post date:** [December 23, 2023, 1:02am UTC](https://forum.crystal-lang.org/t/what-variables-like-type-are-available-in-macros/6233/4 "2023-12-23T01:02:30Z")

</div>

Well, it seems to magically have resolved itself 🙂
