Can macros know if a variable is local or global?

I’m writing a macro that walks the expression tree of a function definition, and would like to know if certain variables are local or global, e.g. if it saw

@mymacro function foo()
    x = 1
    return x + y
end

it needs to know that x is a local variable while y is a global one. The information seems like its all there in the expression, so this should be fair game for a macro. However, I’m not sure if scoping happens further down the compile chain after macro expansion, such that there’s no easy / automatic way to do this. Any ideas?

1 Like

No, because you can’t judge purely from the expression the macro captures whether a corresponding binding in the outer expression (where the macro is contained) exists. At best you can say if a global lookup may be necessary (the variable is read from before written to), but you can’t tell whether that will succeed or throw an UndefVarError.

Scoping happens after AST transforms like macros, which is why you have to apply macro hygiene with esc in the first place.

Indeed, that’s all I need, I don’t need to know if it exists (which can only be known at runtime). I think its the exact thing that @code_lowered is doing:

julia> @code_lowered foo()
CodeInfo(
1 ─      x = 1
│   %2 = x + Main.y
└──      return %2
)

I think @code_lowered is a little smarter here than that, might want to check @macroexpand and subsequent calls.