diff --git a/src/expr.jl b/src/expr.jl index b779a490..6d1e8ed6 100644 --- a/src/expr.jl +++ b/src/expr.jl @@ -526,7 +526,7 @@ end function _to_expr(node) file = sourcefile(node) - if !haschildren(node) + if is_leaf(node) offset, txtbuf = _unsafe_wrap_substring(sourcetext(file)) return _leaf_to_Expr(file, txtbuf, head(node), byte_range(node) .+ offset, node) end diff --git a/src/green_tree.jl b/src/green_tree.jl index c4df5163..8a4b4634 100644 --- a/src/green_tree.jl +++ b/src/green_tree.jl @@ -23,16 +23,16 @@ As implementation choices, we choose that: struct GreenNode{Head} head::Head span::UInt32 - args::Union{Tuple{},Vector{GreenNode{Head}}} + args::Union{Nothing,Vector{GreenNode{Head}}} end -function GreenNode(head::Head, span::Integer, args) where {Head} +function GreenNode(head::Head, span::Integer, args=nothing) where {Head} GreenNode{Head}(head, span, args) end # Accessors / predicates -haschildren(node::GreenNode) = !(node.args isa Tuple{}) -children(node::GreenNode) = node.args +is_leaf(node::GreenNode) = isnothing(node.args) +children(node::GreenNode) = isnothing(node.args) ? () : node.args span(node::GreenNode) = node.span head(node::GreenNode) = node.head @@ -49,19 +49,19 @@ function _show_green_node(io, node, indent, pos, str, show_trivia) return end posstr = "$(lpad(pos, 6)):$(rpad(pos+span(node)-1, 6)) │" - is_leaf = !haschildren(node) - if is_leaf + leaf = is_leaf(node) + if leaf line = string(posstr, indent, summary(node)) else line = string(posstr, indent, '[', summary(node), ']') end - if !is_trivia(node) && is_leaf + if !is_trivia(node) && leaf line = rpad(line, 40) * "✔" end if is_error(node) line = rpad(line, 41) * "✘" end - if is_leaf && !isnothing(str) + if leaf && !isnothing(str) line = string(rpad(line, 43), ' ', repr(str[pos:prevind(str, pos + span(node))])) end line = line*"\n" @@ -70,7 +70,7 @@ function _show_green_node(io, node, indent, pos, str, show_trivia) else print(io, line) end - if !is_leaf + if !leaf new_indent = indent*" " p = pos for x in children(node) @@ -91,7 +91,7 @@ end function build_tree(::Type{GreenNode}, stream::ParseStream; kws...) build_tree(GreenNode{SyntaxHead}, stream; kws...) do h, srcrange, cs span = length(srcrange) - isnothing(cs) ? GreenNode(h, span, ()) : + isnothing(cs) ? GreenNode(h, span) : GreenNode(h, span, collect(GreenNode{SyntaxHead}, cs)) end end diff --git a/src/hooks.jl b/src/hooks.jl index c87d32b0..97189321 100644 --- a/src/hooks.jl +++ b/src/hooks.jl @@ -10,7 +10,7 @@ function _first_error(t::SyntaxNode) if is_error(t) return 0,t end - if haschildren(t) + if !is_leaf(t) for (i,c) in enumerate(children(t)) if is_error(c) return i,c diff --git a/src/syntax_tree.jl b/src/syntax_tree.jl index dc9a7375..af2d3e31 100644 --- a/src/syntax_tree.jl +++ b/src/syntax_tree.jl @@ -76,7 +76,7 @@ end function _to_SyntaxNode(source::SourceFile, txtbuf::Vector{UInt8}, offset::Int, raw::GreenNode{SyntaxHead}, position::Int, keep_parens::Bool) - if !haschildren(raw) + if is_leaf(raw) # Here we parse the values eagerly rather than representing them as # strings. Maybe this is good. Maybe not. valrange = position:position + span(raw) - 1 @@ -106,7 +106,7 @@ function _to_SyntaxNode(source::SourceFile, txtbuf::Vector{UInt8}, offset::Int, end end -haschildren(node::TreeNode) = node.children !== nothing +is_leaf(node::TreeNode) = node.children === nothing children(node::TreeNode) = (c = node.children; return c === nothing ? () : c) numchildren(node::TreeNode) = (isnothing(node.children) ? 0 : length(node.children)) @@ -134,7 +134,7 @@ function _show_syntax_node(io, current_filename, node::AbstractSyntaxNode, posstr *= "$(lpad(first_byte(node),6)):$(rpad(last_byte(node),6))│" end val = node.val - nodestr = haschildren(node) ? "[$(untokenize(head(node)))]" : + nodestr = !is_leaf(node) ? "[$(untokenize(head(node)))]" : isa(val, Symbol) ? string(val) : repr(val) treestr = string(indent, nodestr) # Add filename if it's changed from the previous node @@ -144,7 +144,7 @@ function _show_syntax_node(io, current_filename, node::AbstractSyntaxNode, current_filename[] = fname end println(io, posstr, treestr) - if haschildren(node) + if !is_leaf(node) new_indent = indent*" " for n in children(node) _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, end function _show_syntax_node_sexpr(io, node::AbstractSyntaxNode) - if !haschildren(node) + if is_leaf(node) if is_error(node) print(io, "(", untokenize(head(node)), ")") else @@ -186,7 +186,7 @@ function Base.show(io::IO, node::AbstractSyntaxNode) end function Base.push!(node::SN, child::SN) where SN<:AbstractSyntaxNode - if !haschildren(node) + if is_leaf(node) error("Cannot add children") end args = children(node) @@ -196,7 +196,7 @@ end function Base.copy(node::TreeNode) # copy the container but not the data (ie, deep copy the tree, shallow copy the data). copy(::Expr) is similar # copy "un-parents" the top-level `node` that you're copying - newnode = typeof(node)(nothing, haschildren(node) ? typeof(node)[] : nothing, copy(node.data)) + newnode = typeof(node)(nothing, is_leaf(node) ? nothing : typeof(node)[], copy(node.data)) for child in children(node) newchild = copy(child) newchild.parent = newnode diff --git a/test/green_node.jl b/test/green_node.jl index 8dc79455..020c212d 100644 --- a/test/green_node.jl +++ b/test/green_node.jl @@ -2,7 +2,7 @@ t = parsestmt(GreenNode, "aa + b") @test span(t) == 6 - @test haschildren(t) + @test !is_leaf(t) @test head(t) == SyntaxHead(K"call", 0x0008) @test span.(children(t)) == [2,1,1,1,1] @test head.(children(t)) == [ diff --git a/test/test_utils.jl b/test/test_utils.jl index 28a69923..9d666fbd 100644 --- a/test/test_utils.jl +++ b/test/test_utils.jl @@ -28,7 +28,7 @@ using .JuliaSyntax: SyntaxHead, is_trivia, sourcetext, - haschildren, + is_leaf, children, child, fl_parseall, @@ -276,14 +276,14 @@ function _reduce_tree(failing_subtrees, tree; exprs_equal=exprs_equal_no_linenum if equals_flisp_parse(exprs_equal, tree) return false end - if !haschildren(tree) + if is_leaf(tree) push!(failing_subtrees, tree) return true end had_failing_subtrees = false - if haschildren(tree) + if !is_leaf(tree) for child in children(tree) - if is_trivia(child) || !haschildren(child) + if is_trivia(child) || is_leaf(child) continue end had_failing_subtrees |= _reduce_tree(failing_subtrees, child; exprs_equal=exprs_equal)