Skip to content

Commit

Permalink
Fixes for line number node insertion in short form blocks
Browse files Browse the repository at this point in the history
Copy some peculiar behaviors of the reference parser for compatibility:
* Top level blocks like `a;b;c` don't have any line numbers
* Blocks like `(a;b;c)` omit the first line number node

As part of this, add a new flag `TOPLEVEL_SEMICOLONS_FLAG` to
distinguish semicolon-delimited toplevel statements from
newline-delimited.
  • Loading branch information
c42f committed May 13, 2023
1 parent 0dcca2a commit fcfb942
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 2 deletions.
5 changes: 4 additions & 1 deletion src/expr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ function _internal_node_to_Expr(source, srcrange, head, childranges, childheads,
elseif k == K"macrocall"
_reorder_parameters!(args, 2)
insert!(args, 2, loc)
elseif k == K"block" || k == K"toplevel"
elseif k == K"block" || (k == K"toplevel" && !has_flags(head, TOPLEVEL_SEMICOLONS_FLAG))
if isempty(args)
push!(args, loc)
else
Expand All @@ -225,6 +225,9 @@ function _internal_node_to_Expr(source, srcrange, head, childranges, childheads,
args[2*i-1] = source_location(LineNumberNode, source, first(childranges[i]))
end
end
if k == K"block" && has_flags(head, PARENS_FLAG)
popfirst!(args)
end
elseif k == K"doc"
headsym = :macrocall
args = [GlobalRef(Core, Symbol("@doc")), loc, args...]
Expand Down
4 changes: 4 additions & 0 deletions src/parse_stream.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ const RAW_STRING_FLAG = RawFlags(1<<6)
const PARENS_FLAG = RawFlags(1<<5)
# Set for K"quote" for the short form `:x` as oppsed to long form `quote x end`
const COLON_QUOTE = RawFlags(1<<5)
# Set for K"toplevel" which is delimited by parentheses
const TOPLEVEL_SEMICOLONS_FLAG = RawFlags(1<<5)

# Set for K"struct" when mutable
const MUTABLE_FLAG = RawFlags(1<<5)
Expand Down Expand Up @@ -99,6 +101,8 @@ function untokenize(head::SyntaxHead; unique=true, include_flag_suff=true)
has_flags(head, PARENS_FLAG) && (str = str*"-p")
elseif kind(head) == K"quote"
has_flags(head, COLON_QUOTE) && (str = str*"-:")
elseif kind(head) == K"toplevel"
has_flags(head, TOPLEVEL_SEMICOLONS_FLAG) && (str = str*"-;")
elseif kind(head) == K"struct"
has_flags(head, MUTABLE_FLAG) && (str = str*"-mut")
elseif kind(head) == K"module"
Expand Down
2 changes: 1 addition & 1 deletion src/parser.jl
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ function parse_stmts(ps::ParseState)
error="extra tokens after end of expression")
end
if do_emit
emit(ps, mark, K"toplevel")
emit(ps, mark, K"toplevel", TOPLEVEL_SEMICOLONS_FLAG)
end
end

Expand Down
12 changes: 12 additions & 0 deletions test/expr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,20 @@
LineNumberNode(4),
:c,
)
@test parsestmt("(a;b;c)") ==
Expr(:block,
:a,
LineNumberNode(1),
:b,
LineNumberNode(1),
:c,
)
@test parsestmt("begin end") ==
Expr(:block,
LineNumberNode(1)
)
@test parsestmt("(;;)") ==
Expr(:block)

@test parseall("a\n\nb") ==
Expr(:toplevel,
Expand All @@ -45,6 +55,8 @@
LineNumberNode(3),
:b,
)
@test parsestmt("a;b") ==
Expr(:toplevel, :a, :b)

@test parsestmt("module A\n\nbody\nend") ==
Expr(:module,
Expand Down

0 comments on commit fcfb942

Please sign in to comment.