Skip to content

Commit d8796c6

Browse files
authored
Rename haschildren() to is_leaf() (#483)
Unfortunately, `haschildren(x)` was a terrible name because it's not testing the same thing as `numchildren(x) == 0`! In our ASTs * Leaves of the tree correspond to tokens in the source text * Internal nodes are containers for a range of tokens or other internal nodes. Occasionally we can have internal nodes which have no tokens and thus have `numchildren(node) == 0`. These are, however, still "internal nodes" and we have `haschildren(node) === true` for these which makes no sense!
1 parent 38fc0fa commit d8796c6

File tree

6 files changed

+24
-24
lines changed

6 files changed

+24
-24
lines changed

src/expr.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,7 @@ end
526526

527527
function _to_expr(node)
528528
file = sourcefile(node)
529-
if !haschildren(node)
529+
if is_leaf(node)
530530
offset, txtbuf = _unsafe_wrap_substring(sourcetext(file))
531531
return _leaf_to_Expr(file, txtbuf, head(node), byte_range(node) .+ offset, node)
532532
end

src/green_tree.jl

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,16 @@ As implementation choices, we choose that:
2323
struct GreenNode{Head}
2424
head::Head
2525
span::UInt32
26-
args::Union{Tuple{},Vector{GreenNode{Head}}}
26+
args::Union{Nothing,Vector{GreenNode{Head}}}
2727
end
2828

29-
function GreenNode(head::Head, span::Integer, args) where {Head}
29+
function GreenNode(head::Head, span::Integer, args=nothing) where {Head}
3030
GreenNode{Head}(head, span, args)
3131
end
3232

3333
# Accessors / predicates
34-
haschildren(node::GreenNode) = !(node.args isa Tuple{})
35-
children(node::GreenNode) = node.args
34+
is_leaf(node::GreenNode) = isnothing(node.args)
35+
children(node::GreenNode) = isnothing(node.args) ? () : node.args
3636
span(node::GreenNode) = node.span
3737
head(node::GreenNode) = node.head
3838

@@ -49,19 +49,19 @@ function _show_green_node(io, node, indent, pos, str, show_trivia)
4949
return
5050
end
5151
posstr = "$(lpad(pos, 6)):$(rpad(pos+span(node)-1, 6))"
52-
is_leaf = !haschildren(node)
53-
if is_leaf
52+
leaf = is_leaf(node)
53+
if leaf
5454
line = string(posstr, indent, summary(node))
5555
else
5656
line = string(posstr, indent, '[', summary(node), ']')
5757
end
58-
if !is_trivia(node) && is_leaf
58+
if !is_trivia(node) && leaf
5959
line = rpad(line, 40) * ""
6060
end
6161
if is_error(node)
6262
line = rpad(line, 41) * ""
6363
end
64-
if is_leaf && !isnothing(str)
64+
if leaf && !isnothing(str)
6565
line = string(rpad(line, 43), ' ', repr(str[pos:prevind(str, pos + span(node))]))
6666
end
6767
line = line*"\n"
@@ -70,7 +70,7 @@ function _show_green_node(io, node, indent, pos, str, show_trivia)
7070
else
7171
print(io, line)
7272
end
73-
if !is_leaf
73+
if !leaf
7474
new_indent = indent*" "
7575
p = pos
7676
for x in children(node)
@@ -91,7 +91,7 @@ end
9191
function build_tree(::Type{GreenNode}, stream::ParseStream; kws...)
9292
build_tree(GreenNode{SyntaxHead}, stream; kws...) do h, srcrange, cs
9393
span = length(srcrange)
94-
isnothing(cs) ? GreenNode(h, span, ()) :
94+
isnothing(cs) ? GreenNode(h, span) :
9595
GreenNode(h, span, collect(GreenNode{SyntaxHead}, cs))
9696
end
9797
end

src/hooks.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ function _first_error(t::SyntaxNode)
1010
if is_error(t)
1111
return 0,t
1212
end
13-
if haschildren(t)
13+
if !is_leaf(t)
1414
for (i,c) in enumerate(children(t))
1515
if is_error(c)
1616
return i,c

src/syntax_tree.jl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ end
7676
function _to_SyntaxNode(source::SourceFile, txtbuf::Vector{UInt8}, offset::Int,
7777
raw::GreenNode{SyntaxHead},
7878
position::Int, keep_parens::Bool)
79-
if !haschildren(raw)
79+
if is_leaf(raw)
8080
# Here we parse the values eagerly rather than representing them as
8181
# strings. Maybe this is good. Maybe not.
8282
valrange = position:position + span(raw) - 1
@@ -106,7 +106,7 @@ function _to_SyntaxNode(source::SourceFile, txtbuf::Vector{UInt8}, offset::Int,
106106
end
107107
end
108108

109-
haschildren(node::TreeNode) = node.children !== nothing
109+
is_leaf(node::TreeNode) = node.children === nothing
110110
children(node::TreeNode) = (c = node.children; return c === nothing ? () : c)
111111
numchildren(node::TreeNode) = (isnothing(node.children) ? 0 : length(node.children))
112112

@@ -134,7 +134,7 @@ function _show_syntax_node(io, current_filename, node::AbstractSyntaxNode,
134134
posstr *= "$(lpad(first_byte(node),6)):$(rpad(last_byte(node),6))"
135135
end
136136
val = node.val
137-
nodestr = haschildren(node) ? "[$(untokenize(head(node)))]" :
137+
nodestr = !is_leaf(node) ? "[$(untokenize(head(node)))]" :
138138
isa(val, Symbol) ? string(val) : repr(val)
139139
treestr = string(indent, nodestr)
140140
# Add filename if it's changed from the previous node
@@ -144,7 +144,7 @@ function _show_syntax_node(io, current_filename, node::AbstractSyntaxNode,
144144
current_filename[] = fname
145145
end
146146
println(io, posstr, treestr)
147-
if haschildren(node)
147+
if !is_leaf(node)
148148
new_indent = indent*" "
149149
for n in children(node)
150150
_show_syntax_node(io, current_filename, n, new_indent, show_byte_offsets)
@@ -153,7 +153,7 @@ function _show_syntax_node(io, current_filename, node::AbstractSyntaxNode,
153153
end
154154

155155
function _show_syntax_node_sexpr(io, node::AbstractSyntaxNode)
156-
if !haschildren(node)
156+
if is_leaf(node)
157157
if is_error(node)
158158
print(io, "(", untokenize(head(node)), ")")
159159
else
@@ -186,7 +186,7 @@ function Base.show(io::IO, node::AbstractSyntaxNode)
186186
end
187187

188188
function Base.push!(node::SN, child::SN) where SN<:AbstractSyntaxNode
189-
if !haschildren(node)
189+
if is_leaf(node)
190190
error("Cannot add children")
191191
end
192192
args = children(node)
@@ -196,7 +196,7 @@ end
196196
function Base.copy(node::TreeNode)
197197
# copy the container but not the data (ie, deep copy the tree, shallow copy the data). copy(::Expr) is similar
198198
# copy "un-parents" the top-level `node` that you're copying
199-
newnode = typeof(node)(nothing, haschildren(node) ? typeof(node)[] : nothing, copy(node.data))
199+
newnode = typeof(node)(nothing, is_leaf(node) ? nothing : typeof(node)[], copy(node.data))
200200
for child in children(node)
201201
newchild = copy(child)
202202
newchild.parent = newnode

test/green_node.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
t = parsestmt(GreenNode, "aa + b")
33

44
@test span(t) == 6
5-
@test haschildren(t)
5+
@test !is_leaf(t)
66
@test head(t) == SyntaxHead(K"call", 0x0008)
77
@test span.(children(t)) == [2,1,1,1,1]
88
@test head.(children(t)) == [

test/test_utils.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ using .JuliaSyntax:
2828
SyntaxHead,
2929
is_trivia,
3030
sourcetext,
31-
haschildren,
31+
is_leaf,
3232
children,
3333
child,
3434
fl_parseall,
@@ -276,14 +276,14 @@ function _reduce_tree(failing_subtrees, tree; exprs_equal=exprs_equal_no_linenum
276276
if equals_flisp_parse(exprs_equal, tree)
277277
return false
278278
end
279-
if !haschildren(tree)
279+
if is_leaf(tree)
280280
push!(failing_subtrees, tree)
281281
return true
282282
end
283283
had_failing_subtrees = false
284-
if haschildren(tree)
284+
if !is_leaf(tree)
285285
for child in children(tree)
286-
if is_trivia(child) || !haschildren(child)
286+
if is_trivia(child) || is_leaf(child)
287287
continue
288288
end
289289
had_failing_subtrees |= _reduce_tree(failing_subtrees, child; exprs_equal=exprs_equal)

0 commit comments

Comments
 (0)