From 384f74545d8d2a530ba3ec4a3a82469c34ed597d Mon Sep 17 00:00:00 2001 From: c42f Date: Fri, 14 Oct 2022 15:45:05 +1000 Subject: [PATCH] Remove TRY_CATCH_FINALLY_FLAG (#123) A flag is a waste for this; we can just use a different kind for this horrible edge case. --- src/expr.jl | 7 ++++--- src/kinds.jl | 2 ++ src/parse_stream.jl | 3 --- src/parser.jl | 7 ++++--- test/parser.jl | 22 ++++++++++++++++------ 5 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/expr.jl b/src/expr.jl index 2766c736..748f3516 100644 --- a/src/expr.jl +++ b/src/expr.jl @@ -150,19 +150,19 @@ function _to_expr(node::SyntaxNode; iteration_spec=false, need_linenodes=true, pushfirst!(args, args[end]) pop!(args) end - elseif headsym == :try + elseif headsym in (:try, :try_finally_catch) # Try children in source order: # try_block catch_var catch_block else_block finally_block # Expr ordering: # try_block catch_var catch_block [finally_block] [else_block] catch_ = nothing - if has_flags(node, TRY_CATCH_AFTER_FINALLY_FLAG) + if headsym === :try_finally_catch catch_ = pop!(args) catch_var = pop!(args) end finally_ = pop!(args) else_ = pop!(args) - if has_flags(node, TRY_CATCH_AFTER_FINALLY_FLAG) + if headsym === :try_finally_catch pop!(args) pop!(args) push!(args, catch_var) @@ -176,6 +176,7 @@ function _to_expr(node::SyntaxNode; iteration_spec=false, need_linenodes=true, if else_ !== false push!(args, else_) end + headsym = :try elseif headsym == :filter pushfirst!(args, last(args)) pop!(args) diff --git a/src/kinds.jl b/src/kinds.jl index 86f2a931..26ab76a9 100644 --- a/src/kinds.jl +++ b/src/kinds.jl @@ -897,6 +897,8 @@ const _kind_names = "flatten" "comprehension" "typed_comprehension" + # Special kind for compatibility with the ever-ugly try-finally-catch ordering + "try_finally_catch" "END_SYNTAX_KINDS" ] diff --git a/src/parse_stream.jl b/src/parse_stream.jl index c62e64b2..00790f1d 100644 --- a/src/parse_stream.jl +++ b/src/parse_stream.jl @@ -15,8 +15,6 @@ const DOTOP_FLAG = RawFlags(1<<2) const TRIPLE_STRING_FLAG = RawFlags(1<<3) # Set when a string or identifier needs "raw string" unescaping const RAW_STRING_FLAG = RawFlags(1<<4) -# try-finally-catch -const TRY_CATCH_AFTER_FINALLY_FLAG = RawFlags(1<<5) # Record whether operator has a suffix const SUFFIXED_FLAG = RawFlags(1<<6) @@ -75,7 +73,6 @@ function untokenize(head::SyntaxHead; unique=true, include_flag_suff=true) is_infix(head) && (str = str*"i") has_flags(head, TRIPLE_STRING_FLAG) && (str = str*"s") has_flags(head, RAW_STRING_FLAG) && (str = str*"r") - has_flags(head, TRY_CATCH_AFTER_FINALLY_FLAG) && (str = str*"f") is_suffixed(head) && (str = str*"S") n = numeric_flags(head) n != 0 && (str = str*string(n)) diff --git a/src/parser.jl b/src/parser.jl index f5e202a6..9f968d03 100644 --- a/src/parser.jl +++ b/src/parser.jl @@ -2085,6 +2085,7 @@ end # # flisp: embedded in parse_resword function parse_try(ps) + out_kind = K"try" mark = position(ps) bump(ps, TRIVIA_FLAG) parse_block(ps) @@ -2132,15 +2133,15 @@ function parse_try(ps) # in which these blocks execute. bump_trivia(ps) if !has_catch && peek(ps) == K"catch" - # try x finally y catch e z end ==> (try-f (block x) false false false (block y) e (block z)) - flags |= TRY_CATCH_AFTER_FINALLY_FLAG + # try x finally y catch e z end ==> (try_finally_catch (block x) false false false (block y) e (block z)) + out_kind = K"try_finally_catch" m = position(ps) parse_catch(ps) emit_diagnostic(ps, m, position(ps), warning="`catch` after `finally` will execute out of order") end bump_closing_token(ps, K"end") - emit(ps, mark, K"try", flags) + emit(ps, mark, out_kind, flags) end function parse_catch(ps::ParseState) diff --git a/test/parser.jl b/test/parser.jl index f523b6d3..082198fa 100644 --- a/test/parser.jl +++ b/test/parser.jl @@ -1,13 +1,17 @@ -function test_parse(production, code; v=v"1.6") +function test_parse(production, code; v=v"1.6", expr=false) stream = ParseStream(code, version=v) production(ParseState(stream)) t = build_tree(GreenNode, stream, wrap_toplevel_as_kind=K"None") source = SourceFile(code) s = SyntaxNode(source, t) - if kind(s) == K"None" - join([sprint(show, MIME("text/x.sexpression"), c) for c in children(s)], ' ') + if expr + JuliaSyntax.remove_linenums!(Expr(s)) else - sprint(show, MIME("text/x.sexpression"), s) + if kind(s) == K"None" + join([sprint(show, MIME("text/x.sexpression"), c) for c in children(s)], ' ') + else + sprint(show, MIME("text/x.sexpression"), s) + end end end @@ -482,7 +486,8 @@ tests = [ ((v=v"1.8",), "try else end") => "(try (block) false false (error (block)) false)" ((v=v"1.7",), "try catch ; else end") => "(try (block) false (block) (error (block)) false)" # finally before catch :-( - "try x finally y catch e z end" => "(try-f (block x) false false false (block y) e (block z))" + "try x finally y catch e z end" => "(try_finally_catch (block x) false false false (block y) e (block z))" => + Expr(:try, Expr(:block, :x), :e, Expr(:block, :z), Expr(:block, :y)) ], JuliaSyntax.parse_imports => [ "import A as B: x" => "(import (: (error (as (. A) B)) (. x)))" @@ -816,7 +821,12 @@ broken_tests = [ else opts = NamedTuple() end - @test test_parse(production, input; opts...) == output + if output isa Pair + @test test_parse(production, input; opts...) == output[1] + @test test_parse(production, input; opts..., expr=true) == output[2] + else + @test test_parse(production, input; opts...) == output + end end end @testset "Broken $production" for (production, test_specs) in broken_tests