Is there any way to run name resolution on an arbitrary expression without running it? e.g. I would like to take an expression such as
quote
x = 1
y = 2*x + 1
z = x^2 - 1
f(x) = 2*x + 1
end
and be told that the names defined in the scope of this block are x, y, z, f
and the names *, +, ^, -
are pulled in from outside the scope of this block. Bonus points if it can tell me that there's a sub-scope defined in the body of f
which creates it's own name x
and pulls in +
from an enclosing scope.
This question appeared in the Julia Zulip community
A scope is a region of the program and broadly speaking there are three places, where variables can be declared: Inside a function or a block which is called local variables, In the definition of function parameters which is called formal parameters. Outside of all functions which is called global variables.
A return type can be specified in the function declaration using the :: operator. This converts the return value to the specified type. This function will always return an Int8 regardless of the types of x and y .
Thanks to Takafumi for showing me how to solve this on Zulip
We can get a list of locally defined names in the outermost scope of a julia expression like so:
ex = quote
x = 1
y = 2*x + 1
z = x^2 - 1
f(x) = 2*x + 1
end
using JuliaVariables, MLStyle
function get_locals(ex::Expr)
vars = (solve_from_local ∘ simplify_ex)(ex).args[1].bounds
map(x -> x.name, vars)
end
julia> get_locals(ex)
4-element Array{Symbol,1}:
:f
:y
:z
:x
and we can get the symbols pulled in from outside the scope like this:
_get_outers(_) = Symbol[]
_get_outers(x::Var) = x.is_global ? [x.name] : Symbol[]
function _get_outers(ex::Expr)
@match ex begin
Expr(:(=), _, rhs) => _get_outers(rhs)
Expr(:tuple, _..., Expr(:(=), _, rhs)) => _get_outers(rhs)
Expr(_, args...) => mapreduce(_get_outers, vcat, args)
end
end
get_outers(ex) = (unique! ∘ _get_outers ∘ solve_from_local ∘ simplify_ex)(ex)
julia> get_outers(ex)
6-element Array{Symbol,1}:
:+
:*
:-
:^
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With