Skip to content

Commit 774be18

Browse files
authored
get rid of two core boxes in JuliaSyntax (#60835)
Changes recursive closures into proper methods. Best to review without whitespace. Found via #60478: ``` julia> Test.detect_closure_boxes_all_modules() 8-element Vector{Pair{Method, Vector{Symbol}}}: prune(graph1_a::Base.JuliaSyntax.SyntaxGraph, entrypoints_a::Vector{Int64}) @ Base.JuliaSyntax /JuliaSyntax/src/porcelain/syntax_graph.jl:816 => [:get_resolved!] _stm_check_usage(pats::Expr) @ Base.JuliaSyntax /JuliaSyntax/src/porcelain/syntax_graph.jl:1095 => [:_stm_check_pattern] ```
1 parent e1b5299 commit 774be18

File tree

1 file changed

+62
-57
lines changed

1 file changed

+62
-57
lines changed

JuliaSyntax/src/porcelain/syntax_graph.jl

Lines changed: 62 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -845,32 +845,35 @@ function prune(graph1_a::SyntaxGraph, entrypoints_a::Vector{NodeId})
845845

846846
# Resolve provenance. Tricky to avoid dangling `.source` references.
847847
resolved_sources = Dict{NodeId, SourceAttrType}() # graph1 id => graph2 src
848-
function get_resolved!(id1::NodeId)
849-
out = get(resolved_sources, id1, nothing)
850-
if isnothing(out)
851-
src1 = graph1.source[id1]
852-
out = if haskey(map12, src1)
853-
map12[src1]
854-
elseif src1 isa NodeId
855-
get_resolved!(src1)
856-
elseif src1 isa Tuple
857-
map(get_resolved!, src1)
858-
else
859-
src1
860-
end
861-
resolved_sources[id1] = out
862-
end
863-
return out
864-
end
865848

866849
for (n2, n1) in enumerate(nodes1)
867-
graph2.source[n2] = get_resolved!(n1)
850+
graph2.source[n2] = _prune_get_resolved!(n1, graph1, map12, resolved_sources)
868851
end
869852

870853
# The first n entries in nodes1 were our entrypoints, unique from unaliasing
871854
return SyntaxList(graph2, 1:length(entrypoints))
872855
end
873856

857+
function _prune_get_resolved!(id1::NodeId, graph1::SyntaxGraph,
858+
map12::Dict{NodeId, Int},
859+
resolved_sources::Dict{NodeId, SourceAttrType})
860+
out = get(resolved_sources, id1, nothing)
861+
if isnothing(out)
862+
src1 = graph1.source[id1]
863+
out = if haskey(map12, src1)
864+
map12[src1]
865+
elseif src1 isa NodeId
866+
_prune_get_resolved!(src1, graph1, map12, resolved_sources)
867+
elseif src1 isa Tuple
868+
map(s -> _prune_get_resolved!(s, graph1, map12, resolved_sources), src1)
869+
else
870+
src1
871+
end
872+
resolved_sources[id1] = out
873+
end
874+
return out
875+
end
876+
874877
"""
875878
Give each descendent of `st` a `parent::NodeId` attribute.
876879
"""
@@ -1092,47 +1095,49 @@ function _stm_assigns(p, st_rhs_expr; assigns=Expr(:block))
10921095
end
10931096

10941097
# Check for correct pattern syntax. Not needed outside of development.
1095-
function _stm_check_usage(pats::Expr)
1096-
function _stm_check_pattern(p; syms=Set{Symbol}())
1097-
if Meta.isexpr(p, :(...), 1)
1098-
p = p.args[1]
1099-
@assert(p isa Symbol, "Expected symbol before `...` in $p")
1100-
end
1101-
if p isa Symbol
1102-
# No support for duplicate syms for now (user is either looking for
1103-
# some form of equality we don't implement, or they made a mistake)
1104-
dup = p in syms && p !== :_
1105-
push!(syms, p)
1106-
@assert(!dup, "invalid duplicate non-underscore identifier $p")
1107-
return nothing
1108-
elseif Meta.isexpr(p, :vect)
1109-
@assert(length(p.args) === 1,
1110-
"use spaces, not commas, in @stm []-patterns")
1111-
elseif Meta.isexpr(p, :hcat)
1112-
@assert(length(p.args) >= 2)
1113-
elseif Meta.isexpr(p, :vcat)
1114-
p = _stm_vcat_to_hcat(p)
1115-
@assert(length(p.args) >= 2)
1116-
else
1117-
@assert(false, "malformed pattern $p")
1118-
end
1119-
@assert(count(x->Meta.isexpr(x, :(...)), p.args[2:end]) <= 1,
1120-
"Multiple `...` in a pattern is ambiguous")
1121-
1122-
# This exact `K"kind"` syntax is not necessary since the kind can't be
1123-
# provided by a variable, but requiring [K"kinds"] is consistent with
1124-
# `@ast` and allows us to implement list matching later.
1125-
@assert(Meta.isexpr(p.args[1], :macrocall, 3) &&
1126-
p.args[1].args[1] === Symbol("@K_str") &&
1127-
p.args[1].args[3] isa String, "first pattern elt must be K\"\"")
1128-
1129-
for subp in p.args[2:end]
1130-
_stm_check_pattern(subp; syms)
1131-
end
1098+
function _stm_check_pattern(p, syms::Set{Symbol})
1099+
if Meta.isexpr(p, :(...), 1)
1100+
p = p.args[1]
1101+
@assert(p isa Symbol, "Expected symbol before `...` in $p")
11321102
end
1103+
if p isa Symbol
1104+
# No support for duplicate syms for now (user is either looking for
1105+
# some form of equality we don't implement, or they made a mistake)
1106+
dup = p in syms && p !== :_
1107+
push!(syms, p)
1108+
@assert(!dup, "invalid duplicate non-underscore identifier $p")
1109+
return nothing
1110+
elseif Meta.isexpr(p, :vect)
1111+
@assert(length(p.args) === 1,
1112+
"use spaces, not commas, in @stm []-patterns")
1113+
elseif Meta.isexpr(p, :hcat)
1114+
@assert(length(p.args) >= 2)
1115+
elseif Meta.isexpr(p, :vcat)
1116+
p = _stm_vcat_to_hcat(p)
1117+
@assert(length(p.args) >= 2)
1118+
else
1119+
@assert(false, "malformed pattern $p")
1120+
end
1121+
@assert(count(x->Meta.isexpr(x, :(...)), p.args[2:end]) <= 1,
1122+
"Multiple `...` in a pattern is ambiguous")
1123+
1124+
# This exact `K"kind"` syntax is not necessary since the kind can't be
1125+
# provided by a variable, but requiring [K"kinds"] is consistent with
1126+
# `@ast` and allows us to implement list matching later.
1127+
@assert(Meta.isexpr(p.args[1], :macrocall, 3) &&
1128+
p.args[1].args[1] === Symbol("@K_str") &&
1129+
p.args[1].args[3] isa String, "first pattern elt must be K\"\"")
1130+
1131+
for subp in p.args[2:end]
1132+
_stm_check_pattern(subp, syms)
1133+
end
1134+
return nothing
1135+
end
11331136

1137+
function _stm_check_usage(pats::Expr)
11341138
@assert Meta.isexpr(pats, :block) "Usage: @stm st begin; ...; end"
1135-
for pcr in filter(e->!isa(e, LineNumberNode), pats.args)
1139+
for pcr in pats.args
1140+
pcr isa LineNumberNode && continue
11361141
@assert(Meta.isexpr(pcr, :(->), 2), "Expected pat -> res, got malformed case: $pcr")
11371142
if Meta.isexpr(pcr.args[1], :tuple)
11381143
@assert(length(pcr.args[1].args) === 2,
@@ -1144,7 +1149,7 @@ function _stm_check_usage(pats::Expr)
11441149
else
11451150
p = pcr.args[1]
11461151
end
1147-
_stm_check_pattern(p)
1152+
_stm_check_pattern(p, Set{Symbol}())
11481153
end
11491154
end
11501155

0 commit comments

Comments
 (0)