From 49840658c7e5a1c72bc2b448a6d42c4105420476 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Fri, 24 May 2024 21:20:52 +0200 Subject: [PATCH] Format HexInt literals. --- src/Runic.jl | 40 +++++++++++++++++++++++++++++++++++----- src/main.jl | 1 + 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/Runic.jl b/src/Runic.jl index 8d8efb3..423559d 100644 --- a/src/Runic.jl +++ b/src/Runic.jl @@ -41,6 +41,15 @@ function accept_node!(ctx::Context, node::JuliaSyntax.GreenNode) return end +# Write formatted thing and reset the output stream +function write_and_reset(ctx::Context, bytes::Union{String, SubString{String}, Vector{UInt8}}) + fmt_pos = position(ctx.fmt_io) + nb = write(ctx.fmt_io, bytes) + seek(ctx.fmt_io, fmt_pos) + @assert nb == (bytes isa Vector{UInt8} ? length(bytes) : sizeof(bytes)) + return nb +end + struct NullNode end const nullnode = NullNode() @@ -113,17 +122,15 @@ end function format_node!(ctx::Context, node::JuliaSyntax.GreenNode) node_kind = JuliaSyntax.kind(node) + # TODO: Split these into matchers and a handlers and move to another file # Normalize line endings and remove trailing whitespace if node_kind === K"NewlineWs" - @assert JuliaSyntax.children(node) === () + @assert !JuliaSyntax.haschildren(node) str = String(node_bytes(ctx, node)) str′ = replace(str, r"\h*(\r\n|\r|\n)" => '\n') if str != str′ # Write new bytes and reset the stream - fmt_pos = position(ctx.fmt_io) - nb = write(ctx.fmt_io, str′) - seek(ctx.fmt_io, fmt_pos) - @assert nb == sizeof(str′) + nb = write_and_reset(ctx, str′) @assert nb != JuliaSyntax.span(node) # Create new node and return it node′ = JuliaSyntax.GreenNode(JuliaSyntax.head(node), nb, ()) @@ -131,6 +138,29 @@ function format_node!(ctx::Context, node::JuliaSyntax.GreenNode) end end + # Hex literals + if node_kind === K"HexInt" + @assert JuliaSyntax.flags(node) == 0 + @assert !JuliaSyntax.haschildren(node) + span = JuliaSyntax.span(node) + @assert span > 2 # 0x prefix + target_spans = 2 .+ (2, 4, 8, 16, 32) # 0x + expected chars + if span < 34 && !(span in target_spans) + i::Int = findfirst(x -> x > span, target_spans) + bytes = node_bytes(ctx, node) + while length(bytes) < target_spans[i] + insert!(bytes, 3, '0') + end + nb = write_and_reset(ctx, bytes) + @assert nb == length(bytes) == target_spans[i] + # Create new node and return it + node′ = JuliaSyntax.GreenNode(JuliaSyntax.head(node), nb, ()) + return node′ + else + # Do nothing: correctly formatted or a BigInt literal + end + end + # If the node is unchanged, just keep going. # Nodes that always recurse! diff --git a/src/main.jl b/src/main.jl index 797ce5e..cb248b6 100644 --- a/src/main.jl +++ b/src/main.jl @@ -125,6 +125,7 @@ function (@main)(argv) ctx catch err panic(err) + continue end # Write the output, but skip if inplace and it didn't change