Skip to content

Commit

Permalink
ExEx: Track function calls in assignment lhs. (#2604)
Browse files Browse the repository at this point in the history
  • Loading branch information
Pangoraw authored Jul 16, 2023
1 parent a5c3227 commit f76efd4
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 6 deletions.
13 changes: 7 additions & 6 deletions src/analysis/ExpressionExplorer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ function get_assignees(ex::Expr)::FunctionName
# e.g. (x, y) in the ex (x, y) = (1, 23)
args = ex.args
end
union!(Symbol[], Iterators.map(get_assignees, args)...)
mapfoldl(get_assignees, union!, args; init=Symbol[])
# filter(s->s isa Symbol, ex.args)
elseif ex.head == :(::)
# TODO: type is referenced
Expand All @@ -156,7 +156,7 @@ function get_assignees(ex::Expr)::FunctionName
elseif ex.head == :...
# Handles splat assignments. e.g. _, y... = 1:5
args = ex.args
union!(Symbol[], Iterators.map(get_assignees, args)...)
mapfoldl(get_assignees, union!, args; init=Symbol[])
else
@warn "unknown use of `=`. Assignee is unrecognised." ex
Symbol[]
Expand Down Expand Up @@ -373,12 +373,13 @@ function explore_assignment!(ex::Expr, scopestate::ScopeState)::SymbolsState
global_assignees = get_global_assignees(assignees, scopestate)

# If we are _not_ assigning a global variable, then this symbol hides any global definition with that name
push!(scopestate.hiddenglobals, setdiff(assignees, global_assignees)...)
union!(scopestate.hiddenglobals, setdiff(assignees, global_assignees))
assigneesymstate = explore!(ex.args[1], scopestate)

push!(scopestate.hiddenglobals, global_assignees...)
push!(symstate.assignments, global_assignees...)
push!(symstate.references, setdiff(assigneesymstate.references, global_assignees)...)
union!(scopestate.hiddenglobals, global_assignees)
union!(symstate.assignments, global_assignees)
union!(symstate.references, setdiff(assigneesymstate.references, global_assignees))
union!(symstate.funccalls, filter!(call -> length(call) != 1 || only(call) global_assignees, assigneesymstate.funccalls))
filter!(!all_underscores, symstate.references) # Never record _ as a reference

return symstate
Expand Down
15 changes: 15 additions & 0 deletions test/ExpressionExplorer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,9 @@ Some of these @test_broken lines are commented out to prevent printing to the te
@test testee(:(x = let a = 1; a += b end), [:b], [:x], [:+], [])
@test testee(:(_ = a + 1), [:a], [], [:+], [])
@test testee(:(a = _ + 1), [], [:a], [:+], [])

@test testee(:(f()[] = 1), [], [], [:f], [])
@test testee(:(x[f()] = 1), [:x], [], [:f], [])
end
@testset "Multiple assignments" begin
# Note that using the shorthand syntax :(a = 1, b = 2) to create an expression
Expand Down Expand Up @@ -206,6 +209,18 @@ Some of these @test_broken lines are commented out to prevent printing to the te
@test testee(quote
a, b... = 0:5
end, [],[:a, :b], [[:(:)]], [])
@test testee(quote
a[x], x = 1, 2
end, [:a], [:x], [], [])
@test testee(quote
x, a[x] = 1, 2
end, [:a], [:x], [], [])
@test testee(quote
f, a[f()] = g
end, [:g, :a], [:f], [], [])
@test testee(quote
a[f()], f = g
end, [:g, :a], [:f], [], [])
@test testee(quote (; a, b) = x end, [:x], [:a, :b], [], [])
@test testee(quote a = (b, c) end, [:b, :c], [:a], [], [])

Expand Down

0 comments on commit f76efd4

Please sign in to comment.