From 6a9104a1067a8fc946558b28d2159f73dcfa2a7c Mon Sep 17 00:00:00 2001 From: Sebastian Pfitzner Date: Mon, 25 Jul 2022 23:10:12 +0200 Subject: [PATCH 1/7] fix (typed_)ncat prime parsing --- src/components/operators.jl | 6 +++++- test/parser.jl | 5 ++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/components/operators.jl b/src/components/operators.jl index 61488411..0a31f532 100644 --- a/src/components/operators.jl +++ b/src/components/operators.jl @@ -471,7 +471,11 @@ function parse_operator(ps::ParseState, ret::EXPR, op::EXPR) ret = EXPR(op, EXPR[ret], nothing) elseif is_prime(op) if isidentifier(ret) || isliteral(ret) || - headof(ret) in (:call, :tuple, :brackets, :ref, :vect, :vcat, :hcat, :typed_vcat, :typed_hcat, :comprehension, :typed_comprehension, :curly, :braces, :braces_cat) || + headof(ret) in ( + :call, :tuple, :brackets, :ref, :vect, :vcat, :hcat, :ncat, :typed_vcat, + :typed_hcat, :typed_ncat, :comprehension, :typed_comprehension, :curly, + :braces, :braces_cat + ) || headof(ret) === :do || is_dot(headof(ret)) || is_prime(headof(ret)) diff --git a/test/parser.jl b/test/parser.jl index e4d71853..a827ef63 100644 --- a/test/parser.jl +++ b/test/parser.jl @@ -511,9 +511,7 @@ end @test "[x;;]" |> test_expr @test "[x;; y;; z]" |> test_expr @test "[x;;; y;;;z]" |> test_expr - end - - @testset "ncat" begin + @test "[x;;; y;;;z]'" |> test_expr @test "[1 2; 3 4]" |> test_expr @test "[1;2;;3;4;;5;6;;;;9]" |> test_expr end @@ -527,6 +525,7 @@ end @test "t[x;;; y;;;z]" |> test_expr @test "t[x;;\ny]" |> test_expr @test "t[x y;;\nz a]" |> test_expr + @test "t[x y;;\nz a]'" |> test_expr end end From f8b47efb2b7eb2458999d03a361ae87d785f2bb7 Mon Sep 17 00:00:00 2001 From: Sebastian Pfitzner Date: Mon, 25 Jul 2022 23:10:52 +0200 Subject: [PATCH 2/7] NFC: Improve length(EXPR) code --- src/spec.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/spec.jl b/src/spec.jl index 026283d4..f7350b33 100644 --- a/src/spec.jl +++ b/src/spec.jl @@ -280,8 +280,8 @@ end function Base.length(x::EXPR) headof(x) === :NONSTDIDENTIFIER && return 0 headof(x) === :flatten && return length(Iterating._flatten_lhs(x)) - n = x.args isa Nothing ? 0 : length(x.args) - n += x.trivia !== nothing ? length(x.trivia) : 0 + n = x.args === nothing ? 0 : length(x.args) + n += x.trivia === nothing ? 0 : length(x.trivia) x.head isa EXPR && !(x.head.span === 0) && (n += 1) return n end From 79d5733e3df01b93f980979000cd53eb81cc5b9a Mon Sep 17 00:00:00 2001 From: Sebastian Pfitzner Date: Mon, 25 Jul 2022 23:20:05 +0200 Subject: [PATCH 3/7] NFC: rename allow_const_field -> allow_no_assignment --- src/CSTParser.jl | 4 ++-- src/components/internals.jl | 4 ++-- src/components/keywords.jl | 18 +++++++++--------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/CSTParser.jl b/src/CSTParser.jl index be584c0e..7e2fb6bc 100644 --- a/src/CSTParser.jl +++ b/src/CSTParser.jl @@ -38,7 +38,7 @@ Acceptable starting tokens are: + An `@`. """ -function parse_expression(ps::ParseState, esc_on_error = false; allow_const_field = false) +function parse_expression(ps::ParseState, esc_on_error = false; allow_no_assignment = false) if kindof(ps.nt) === Tokens.ENDMARKER ret = mErrorToken(ps, UnexpectedToken) elseif (esc_on_error && ps.nt.kind == Tokens.ERROR) @@ -48,7 +48,7 @@ function parse_expression(ps::ParseState, esc_on_error = false; allow_const_fiel else next(ps) if iskeyword(kindof(ps.t)) && kindof(ps.t) != Tokens.DO - ret = parse_kw(ps; allow_const_field = allow_const_field) + ret = parse_kw(ps; allow_no_assignment = allow_no_assignment) elseif kindof(ps.t) === Tokens.LPAREN ret = parse_paren(ps) elseif kindof(ps.t) === Tokens.LSQUARE diff --git a/src/components/internals.jl b/src/components/internals.jl index 0b7e28a3..9b22362b 100644 --- a/src/components/internals.jl +++ b/src/components/internals.jl @@ -4,7 +4,7 @@ const term_c = (Tokens.RPAREN, Tokens.RSQUARE, Tokens.RBRACE, Tokens.END, Tokens Continue parsing statements until an element of `closers` is hit (usually `end`). Statements are grouped in a `Block` EXPR. """ -function parse_block(ps::ParseState, ret::Vector{EXPR}=EXPR[], closers=(Tokens.END,), docable=false; allow_const_field = false) +function parse_block(ps::ParseState, ret::Vector{EXPR}=EXPR[], closers=(Tokens.END,), docable=false; allow_no_assignment = false) prevpos = position(ps) while kindof(ps.nt) ∉ closers # loop until an expected closer is hit if kindof(ps.nt) ∈ term_c # error handling if an unexpected closer is hit @@ -17,7 +17,7 @@ function parse_block(ps::ParseState, ret::Vector{EXPR}=EXPR[], closers=(Tokens.E if docable a = parse_doc(ps) else - a = parse_expression(ps; allow_const_field = allow_const_field) + a = parse_expression(ps; allow_no_assignment = allow_no_assignment) end push!(ret, a) end diff --git a/src/components/keywords.jl b/src/components/keywords.jl index c79dc7ee..65a9a4bc 100644 --- a/src/components/keywords.jl +++ b/src/components/keywords.jl @@ -3,7 +3,7 @@ Dispatch function for when the parser has reached a keyword. """ -function parse_kw(ps::ParseState; allow_const_field = false) +function parse_kw(ps::ParseState; allow_no_assignment = false) k = kindof(ps.t) if ps.closer.precedence == 20 && ps.lt.kind === Tokens.EX_OR && k !== Tokens.END return EXPR(:IDENTIFIER, ps) @@ -52,7 +52,7 @@ function parse_kw(ps::ParseState; allow_const_field = false) elseif k === Tokens.BAREMODULE return @default ps @closer ps :block parse_blockexpr(ps, :baremodule) elseif k === Tokens.CONST - return @default ps parse_const(ps; allow_const_field = allow_const_field) + return @default ps parse_const(ps; allow_no_assignment = allow_no_assignment) elseif k === Tokens.GLOBAL return @default ps parse_local_global(ps, false) elseif k === Tokens.LOCAL @@ -75,7 +75,7 @@ function parse_kw(ps::ParseState; allow_const_field = false) elseif k === Tokens.TYPE return EXPR(:IDENTIFIER, ps) elseif k === Tokens.STRUCT - return @default ps @closer ps :block parse_blockexpr(ps, :struct, allow_const_field = true) + return @default ps @closer ps :block parse_blockexpr(ps, :struct, allow_no_assignment = true) elseif k === Tokens.MUTABLE return @default ps @closer ps :block parse_mutable(ps) elseif k === Tokens.OUTER @@ -85,10 +85,10 @@ function parse_kw(ps::ParseState; allow_const_field = false) end end -function parse_const(ps::ParseState; allow_const_field = false) +function parse_const(ps::ParseState; allow_no_assignment = false) kw = EXPR(ps) arg = parse_expression(ps) - if !allow_const_field && !(isassignment(unwrapbracket(arg)) || (headof(arg) === :global && length(arg.args) > 0 && isassignment(unwrapbracket(arg.args[1])))) + if !allow_no_assignment && !(isassignment(unwrapbracket(arg)) || (headof(arg) === :global && length(arg.args) > 0 && isassignment(unwrapbracket(arg.args[1])))) arg = mErrorToken(ps, arg, ExpectedAssignment) end ret = EXPR(:const, EXPR[arg], EXPR[kw]) @@ -154,7 +154,7 @@ function parse_mutable(ps::ParseState) if kindof(ps.nt) === Tokens.STRUCT kw = EXPR(ps) next(ps) - ret = parse_blockexpr(ps, :mutable, allow_const_field = true) + ret = parse_blockexpr(ps, :mutable, allow_no_assignment = true) pushfirst!(ret.trivia, setparent!(kw, ret)) update_span!(ret) else @@ -308,15 +308,15 @@ function parse_do(ps::ParseState, pre::EXPR) end """ - parse_blockexpr(ps::ParseState, head; allow_const_field = false) + parse_blockexpr(ps::ParseState, head; allow_no_assignment = false) General function for parsing block expressions comprised of a series of statements terminated by an `end`. """ -function parse_blockexpr(ps::ParseState, head; allow_const_field = false) +function parse_blockexpr(ps::ParseState, head; allow_no_assignment = false) kw = EXPR(ps) sig = parse_blockexpr_sig(ps, head) - blockargs = parse_block(ps, EXPR[], (Tokens.END,), docable(head); allow_const_field = allow_const_field) + blockargs = parse_block(ps, EXPR[], (Tokens.END,), docable(head); allow_no_assignment = allow_no_assignment) if head === :begin EXPR(:block, blockargs, EXPR[kw, accept_end(ps)]) elseif sig === nothing From 9c318e1278518a2a08f15552aada3c9273b7c9a8 Mon Sep 17 00:00:00 2001 From: Sebastian Pfitzner Date: Tue, 26 Jul 2022 00:22:05 +0200 Subject: [PATCH 4/7] Fix allow_no_assignment logic for quoted global consts --- src/CSTParser.jl | 4 ++-- src/components/internals.jl | 4 ++-- src/components/keywords.jl | 27 +++++++++++++++++++-------- src/components/operators.jl | 2 ++ src/lexer.jl | 31 +++++++++++++++++++------------ test/parser.jl | 8 ++++++++ 6 files changed, 52 insertions(+), 24 deletions(-) diff --git a/src/CSTParser.jl b/src/CSTParser.jl index 7e2fb6bc..04c159cc 100644 --- a/src/CSTParser.jl +++ b/src/CSTParser.jl @@ -38,7 +38,7 @@ Acceptable starting tokens are: + An `@`. """ -function parse_expression(ps::ParseState, esc_on_error = false; allow_no_assignment = false) +function parse_expression(ps::ParseState, esc_on_error = false) if kindof(ps.nt) === Tokens.ENDMARKER ret = mErrorToken(ps, UnexpectedToken) elseif (esc_on_error && ps.nt.kind == Tokens.ERROR) @@ -48,7 +48,7 @@ function parse_expression(ps::ParseState, esc_on_error = false; allow_no_assignm else next(ps) if iskeyword(kindof(ps.t)) && kindof(ps.t) != Tokens.DO - ret = parse_kw(ps; allow_no_assignment = allow_no_assignment) + ret = parse_kw(ps) elseif kindof(ps.t) === Tokens.LPAREN ret = parse_paren(ps) elseif kindof(ps.t) === Tokens.LSQUARE diff --git a/src/components/internals.jl b/src/components/internals.jl index 9b22362b..9cb9c5cc 100644 --- a/src/components/internals.jl +++ b/src/components/internals.jl @@ -4,7 +4,7 @@ const term_c = (Tokens.RPAREN, Tokens.RSQUARE, Tokens.RBRACE, Tokens.END, Tokens Continue parsing statements until an element of `closers` is hit (usually `end`). Statements are grouped in a `Block` EXPR. """ -function parse_block(ps::ParseState, ret::Vector{EXPR}=EXPR[], closers=(Tokens.END,), docable=false; allow_no_assignment = false) +function parse_block(ps::ParseState, ret::Vector{EXPR}=EXPR[], closers=(Tokens.END,), docable=false) prevpos = position(ps) while kindof(ps.nt) ∉ closers # loop until an expected closer is hit if kindof(ps.nt) ∈ term_c # error handling if an unexpected closer is hit @@ -17,7 +17,7 @@ function parse_block(ps::ParseState, ret::Vector{EXPR}=EXPR[], closers=(Tokens.E if docable a = parse_doc(ps) else - a = parse_expression(ps; allow_no_assignment = allow_no_assignment) + a = parse_expression(ps) end push!(ret, a) end diff --git a/src/components/keywords.jl b/src/components/keywords.jl index 65a9a4bc..284c1dcf 100644 --- a/src/components/keywords.jl +++ b/src/components/keywords.jl @@ -3,7 +3,7 @@ Dispatch function for when the parser has reached a keyword. """ -function parse_kw(ps::ParseState; allow_no_assignment = false) +function parse_kw(ps::ParseState) k = kindof(ps.t) if ps.closer.precedence == 20 && ps.lt.kind === Tokens.EX_OR && k !== Tokens.END return EXPR(:IDENTIFIER, ps) @@ -52,7 +52,7 @@ function parse_kw(ps::ParseState; allow_no_assignment = false) elseif k === Tokens.BAREMODULE return @default ps @closer ps :block parse_blockexpr(ps, :baremodule) elseif k === Tokens.CONST - return @default ps parse_const(ps; allow_no_assignment = allow_no_assignment) + return @default ps parse_const(ps) elseif k === Tokens.GLOBAL return @default ps parse_local_global(ps, false) elseif k === Tokens.LOCAL @@ -75,7 +75,10 @@ function parse_kw(ps::ParseState; allow_no_assignment = false) elseif k === Tokens.TYPE return EXPR(:IDENTIFIER, ps) elseif k === Tokens.STRUCT - return @default ps @closer ps :block parse_blockexpr(ps, :struct, allow_no_assignment = true) + enable!(ps, ParserFlags.AllowConstWithoutAssignment) + ret = @default ps @closer ps :block parse_blockexpr(ps, :struct) + disable!(ps, ParserFlags.AllowConstWithoutAssignment) + return ret elseif k === Tokens.MUTABLE return @default ps @closer ps :block parse_mutable(ps) elseif k === Tokens.OUTER @@ -85,9 +88,13 @@ function parse_kw(ps::ParseState; allow_no_assignment = false) end end -function parse_const(ps::ParseState; allow_no_assignment = false) +function parse_const(ps::ParseState) kw = EXPR(ps) + lt = ps.lt + nt = ps.nt arg = parse_expression(ps) + allow_no_assignment = has_flag(ps, ParserFlags.AllowConstWithoutAssignment) || + has_flag(ps, ParserFlags.InQuote) && (kindof(nt) === Tokens.GLOBAL || kindof(lt) === Tokens.GLOBAL) if !allow_no_assignment && !(isassignment(unwrapbracket(arg)) || (headof(arg) === :global && length(arg.args) > 0 && isassignment(unwrapbracket(arg.args[1])))) arg = mErrorToken(ps, arg, ExpectedAssignment) end @@ -154,7 +161,11 @@ function parse_mutable(ps::ParseState) if kindof(ps.nt) === Tokens.STRUCT kw = EXPR(ps) next(ps) - ret = parse_blockexpr(ps, :mutable, allow_no_assignment = true) + + enable!(ps, ParserFlags.AllowConstWithoutAssignment) + ret = parse_blockexpr(ps, :mutable) + disable!(ps, ParserFlags.AllowConstWithoutAssignment) + pushfirst!(ret.trivia, setparent!(kw, ret)) update_span!(ret) else @@ -308,15 +319,15 @@ function parse_do(ps::ParseState, pre::EXPR) end """ - parse_blockexpr(ps::ParseState, head; allow_no_assignment = false) + parse_blockexpr(ps::ParseState, head) General function for parsing block expressions comprised of a series of statements terminated by an `end`. """ -function parse_blockexpr(ps::ParseState, head; allow_no_assignment = false) +function parse_blockexpr(ps::ParseState, head) kw = EXPR(ps) sig = parse_blockexpr_sig(ps, head) - blockargs = parse_block(ps, EXPR[], (Tokens.END,), docable(head); allow_no_assignment = allow_no_assignment) + blockargs = parse_block(ps, EXPR[], (Tokens.END,), docable(head)) if head === :begin EXPR(:block, blockargs, EXPR[kw, accept_end(ps)]) elseif sig === nothing diff --git a/src/components/operators.jl b/src/components/operators.jl index 0a31f532..c8e29cac 100644 --- a/src/components/operators.jl +++ b/src/components/operators.jl @@ -249,7 +249,9 @@ function parse_unary_colon(ps::ParseState, op::EXPR) ret = op else prev_errored = ps.errored + enable!(ps, ParserFlags.InQuote) arg = @precedence ps 20 @nocloser ps :inref parse_expression(ps) + disable!(ps, ParserFlags.InQuote) if isbracketed(arg) && headof(arg.args[1]) === :errortoken && errorof(arg.args[1]) === UnexpectedAssignmentOp ps.errored = prev_errored arg.args[1] = arg.args[1].args[1] diff --git a/src/lexer.jl b/src/lexer.jl index 0b2d637c..cf02edc3 100644 --- a/src/lexer.jl +++ b/src/lexer.jl @@ -42,9 +42,10 @@ mutable struct ParseState nnws::RawToken closer::Closer errored::Bool + flags::UInt64 end function ParseState(str::Union{IOBuffer,String}) - ps = ParseState(tokenize(str, RawToken), false, RawToken(), RawToken(), RawToken(), RawToken(), RawToken(), RawToken(), RawToken(), RawToken(), Closer(), false) + ps = ParseState(tokenize(str, RawToken), false, RawToken(), RawToken(), RawToken(), RawToken(), RawToken(), RawToken(), RawToken(), RawToken(), Closer(), false, 0) return next(next(ps)) end @@ -58,6 +59,15 @@ function ParseState(str::Union{IOBuffer,String}, loc::Int) return ps end +module ParserFlags + const AllowConstWithoutAssignment = 0x1 + const InQuote = 0x2 +end + +enable!(ps::ParseState, flag::Integer) = ps.flags |= flag +disable!(ps::ParseState, flag::Integer) = ps.flags &= ~flag +has_flag(ps::ParseState, flag::Integer) = ps.flags & flag > 0 + function Base.show(io::IO, ps::ParseState) println(io, "ParseState at $(position(ps.l.io))") println(io, "last : ", kindof(ps.lt), " ($(ps.lt))", " ($(wstype(ps.lws)))") @@ -66,21 +76,18 @@ function Base.show(io::IO, ps::ParseState) end peekchar(ps::ParseState) = peekchar(ps.l) if !applicable(Base.peek, Tuple{IOBuffer, Char}) -function _peek(s::IO, ::Type{T}) where T - mark(s) - try read(s, T)::T - finally - reset(s) + function _peek(s::IO, ::Type{T}) where T + mark(s) + try read(s, T)::T + finally + reset(s) + end end -end -peekchar(io) = _peek(io, Char) + peekchar(io) = _peek(io, Char) else -peekchar(io) = peek(io, Char) + peekchar(io) = peek(io, Char) end - - - wstype(t::AbstractToken) = kindof(t) == EmptyWS ? "empty" : kindof(t) == NewLineWS ? "ws w/ newline" : kindof(t) == SemiColonWS ? "ws w/ semicolon" : "ws" diff --git a/test/parser.jl b/test/parser.jl index a827ef63..62e4789f 100644 --- a/test/parser.jl +++ b/test/parser.jl @@ -179,6 +179,14 @@ end @test ":(;;;)" |> test_expr end + # this errors during *lowering*, not parsing. + @testset "parse const without assignment in quote" begin + @test ":(global const x)" |> test_expr + @test ":(global const x::Int)" |> test_expr + @test ":(const global x)" |> test_expr + @test ":(const global x::Int)" |> test_expr + end + @testset "where precedence" begin @test "a = b where c = d" |> test_expr @test "a = b where c" |> test_expr From bfc4161a5cdd7955c9188f27300e9237039f6e3d Mon Sep 17 00:00:00 2001 From: pfitzseb Date: Sun, 31 Jul 2022 15:11:52 +0200 Subject: [PATCH 5/7] Fix global tuple iteration --- src/iterate.jl | 16 +++++++++++++--- test/iterate.jl | 12 ++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/iterate.jl b/src/iterate.jl index 3d270db8..06d0a1a0 100644 --- a/src/iterate.jl +++ b/src/iterate.jl @@ -257,10 +257,20 @@ function _const(x, i) end function _global(x, i) - if hastrivia(x) && (headof(first(x.trivia)) === :GLOBAL || headof(first(x.trivia)) === :LOCAL) - oddt_evena(x, i) + if length(x.trivia) > length(x.args) # probably :tuple + if i <= 2 + x.trivia[i] + elseif isodd(i) + x.args[div(i - 1, 2)] + else + x.trivia[div(i - 2, 2) + 2] + end else - odda_event(x, i) + if hastrivia(x) && (headof(first(x.trivia)) === :GLOBAL || headof(first(x.trivia)) === :LOCAL) + oddt_evena(x, i) + else + odda_event(x, i) + end end end diff --git a/test/iterate.jl b/test/iterate.jl index 9d5c8b84..c894c2f2 100644 --- a/test/iterate.jl +++ b/test/iterate.jl @@ -29,6 +29,18 @@ end @test x[1] === x.trivia[1] @test x[2] === x.args[1] end + + @testset "global tuple" begin + x = cst"global (a = 1,b = 2)" + @test length(x) == 6 + @test x[1] === x.trivia[1] + @test x[2] === x.trivia[2] + @test x[3] === x.args[1] + @test x[4] === x.trivia[3] + @test x[5] === x.args[2] + @test x[6] === x.trivia[4] + end + @testset "const" begin x = cst"const a = 1" @test length(x) == 2 From e41b7851c4de7bfd3c6f13fd605b114b1f481067 Mon Sep 17 00:00:00 2001 From: pfitzseb Date: Sun, 31 Jul 2022 19:25:19 +0200 Subject: [PATCH 6/7] Fix let block parsing in comprehension --- src/components/lists.jl | 3 +-- test/parser.jl | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/components/lists.jl b/src/components/lists.jl index eaa95acb..b9952dd6 100644 --- a/src/components/lists.jl +++ b/src/components/lists.jl @@ -118,8 +118,7 @@ function parse_array_outer(ps::ParseState, trivia, isref) max_bp = -typemax(Int) is_start = true while kindof(ps.nt) !== Tokens.RSQUARE && kindof(ps.nt) !== Tokens.ENDMARKER - a = @nocloser ps :newline @nocloser ps :newline @closesquare ps @closer ps :insquare @closer ps :ws @closer ps :wsop @closer ps :comma parse_expression(ps) - + a = @nocloser ps :semicolon @nocloser ps :newline @closesquare ps @closer ps :insquare @closer ps :ws @closer ps :wsop @closer ps :comma parse_expression(ps) if is_start args = EXPR[] if isref && _do_kw_convert(ps, a) diff --git a/test/parser.jl b/test/parser.jl index 62e4789f..074e7b0b 100644 --- a/test/parser.jl +++ b/test/parser.jl @@ -522,6 +522,8 @@ end @test "[x;;; y;;;z]'" |> test_expr @test "[1 2; 3 4]" |> test_expr @test "[1;2;;3;4;;5;6;;;;9]" |> test_expr + @test "[let; x; end;; y]" |> test_expr + @test "[let; x; end;;;; y]" |> test_expr end @testset "typed_ncat" begin @@ -534,20 +536,34 @@ end @test "t[x;;\ny]" |> test_expr @test "t[x y;;\nz a]" |> test_expr @test "t[x y;;\nz a]'" |> test_expr + @test "t[let; x; end;; y]" |> test_expr + @test "t[let; x; end;;;; y]" |> test_expr end end @testset "hcat" begin @test "[x y]" |> test_expr + @test "[let; x; end y]" |> test_expr + @test "[let; x; end; y]" |> test_expr end @testset "typed_hcat" begin @test "t[x y]" |> test_expr + @test "t[let; x; end y]" |> test_expr + @test "t[let; x; end; y]" |> test_expr end @testset "Comprehension" begin @test "[i for i = 1:10]" |> test_expr @test "Int[i for i = 1:10]" |> test_expr + @test """[ + [ + let l = min((d-k),k); + binomial(d-l,l); + end; for k in 1:d-1 + ] for d in 2:9 + ] + """ |> test_expr end end From a6fd41d56b6ce7fde5d53000baa0110f45759848 Mon Sep 17 00:00:00 2001 From: Sebastian Pfitzner Date: Mon, 1 Aug 2022 09:36:22 +0200 Subject: [PATCH 7/7] Disable comprehension tests on old Julia versions --- test/parser.jl | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/test/parser.jl b/test/parser.jl index 074e7b0b..c72edbeb 100644 --- a/test/parser.jl +++ b/test/parser.jl @@ -522,8 +522,10 @@ end @test "[x;;; y;;;z]'" |> test_expr @test "[1 2; 3 4]" |> test_expr @test "[1;2;;3;4;;5;6;;;;9]" |> test_expr - @test "[let; x; end;; y]" |> test_expr - @test "[let; x; end;;;; y]" |> test_expr + if VERSION > v"1.7-" + @test "[let; x; end;; y]" |> test_expr + @test "[let; x; end;;;; y]" |> test_expr + end end @testset "typed_ncat" begin @@ -556,14 +558,19 @@ end @testset "Comprehension" begin @test "[i for i = 1:10]" |> test_expr @test "Int[i for i = 1:10]" |> test_expr - @test """[ - [ - let l = min((d-k),k); - binomial(d-l,l); - end; for k in 1:d-1 - ] for d in 2:9 - ] - """ |> test_expr + @test "[let;x;end for x in x]" |> test_expr + @test "[let; x; end for x in x]" |> test_expr + @test "[let x=x; x+x; end for x in x]" |> test_expr + if VERSION > v"1.7-" + @test """[ + [ + let l = min((d-k),k); + binomial(d-l,l); + end; for k in 1:d-1 + ] for d in 2:9 + ] + """ |> test_expr + end end end