diff --git a/base/show.jl b/base/show.jl index 879916d794f96..4dc3e8f09cc63 100644 --- a/base/show.jl +++ b/base/show.jl @@ -2542,6 +2542,8 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int, quote_level::In # we want to show bad ASTs reasonably to make errors understandable. lambda_io = IOContext(io, :SOURCE_SLOTNAMES => false) show_unquoted_expr_fallback(lambda_io, ex, indent, quote_level) + elseif get(io, beginsym, false) && head in (:begin, :end) + print(io, head) else unhandled = true end diff --git a/base/views.jl b/base/views.jl index 6898abdda1471..3dfcd6794193d 100644 --- a/base/views.jl +++ b/base/views.jl @@ -18,16 +18,14 @@ replace_ref_begin_end!(ex) = replace_ref_begin_end_!(ex, nothing)[1] # replace_ref_begin_end_!(ex,withex) returns (new ex, whether withex was used) function replace_ref_begin_end_!(ex, withex) used_withex = false - if isa(ex,Symbol) - if ex === :begin + if isa(ex,Expr) + if ex.head === :begin withex === nothing && error("Invalid use of begin") return withex[1], true - elseif ex === :end + elseif ex.head === :end withex === nothing && error("Invalid use of end") return withex[2], true - end - elseif isa(ex,Expr) - if ex.head === :ref + elseif ex.head === :ref ex.args[1], used_withex = replace_ref_begin_end_!(ex.args[1], withex) S = isa(ex.args[1],Symbol) ? ex.args[1]::Symbol : gensym(:S) # temp var to cache ex.args[1] if needed used_S = false # whether we actually need S diff --git a/deps/JuliaSyntax.version b/deps/JuliaSyntax.version index 9487754d8a617..bcec4a18d8283 100644 --- a/deps/JuliaSyntax.version +++ b/deps/JuliaSyntax.version @@ -1,4 +1,4 @@ -JULIASYNTAX_BRANCH = main -JULIASYNTAX_SHA1 = 46723f071d5b2efcb21ca6757788028afb91cc13 +JULIASYNTAX_BRANCH = mlechu/fix-end-parsing +JULIASYNTAX_SHA1 = 17be4e33b713d4e0f41f5ae3c5abcaef68bd9c90 JULIASYNTAX_GIT_URL := https://github.com/JuliaLang/JuliaSyntax.jl.git JULIASYNTAX_TAR_URL = https://api.github.com/repos/JuliaLang/JuliaSyntax.jl/tarball/$1 diff --git a/deps/checksums/JuliaSyntax-17be4e33b713d4e0f41f5ae3c5abcaef68bd9c90.tar.gz/md5 b/deps/checksums/JuliaSyntax-17be4e33b713d4e0f41f5ae3c5abcaef68bd9c90.tar.gz/md5 new file mode 100644 index 0000000000000..0fb8cf22d1717 --- /dev/null +++ b/deps/checksums/JuliaSyntax-17be4e33b713d4e0f41f5ae3c5abcaef68bd9c90.tar.gz/md5 @@ -0,0 +1 @@ +45dd003f87f340d4316fa97e920e1c91 diff --git a/deps/checksums/JuliaSyntax-17be4e33b713d4e0f41f5ae3c5abcaef68bd9c90.tar.gz/sha512 b/deps/checksums/JuliaSyntax-17be4e33b713d4e0f41f5ae3c5abcaef68bd9c90.tar.gz/sha512 new file mode 100644 index 0000000000000..876c82fabded4 --- /dev/null +++ b/deps/checksums/JuliaSyntax-17be4e33b713d4e0f41f5ae3c5abcaef68bd9c90.tar.gz/sha512 @@ -0,0 +1 @@ +b80b06044dbacef4ca17140ba7fd3e7ca867dfeebae77e972e5287e3ff18d328884c9f6a5377a4e9c65642614a586c38dd91226a079aa60d74db0225f7ef9fa9 diff --git a/deps/checksums/JuliaSyntax-46723f071d5b2efcb21ca6757788028afb91cc13.tar.gz/md5 b/deps/checksums/JuliaSyntax-46723f071d5b2efcb21ca6757788028afb91cc13.tar.gz/md5 deleted file mode 100644 index ff40f520dfe85..0000000000000 --- a/deps/checksums/JuliaSyntax-46723f071d5b2efcb21ca6757788028afb91cc13.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -2a0921e59edfab54554aa173f091c5b7 diff --git a/deps/checksums/JuliaSyntax-46723f071d5b2efcb21ca6757788028afb91cc13.tar.gz/sha512 b/deps/checksums/JuliaSyntax-46723f071d5b2efcb21ca6757788028afb91cc13.tar.gz/sha512 deleted file mode 100644 index 64e90d0edaba0..0000000000000 --- a/deps/checksums/JuliaSyntax-46723f071d5b2efcb21ca6757788028afb91cc13.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -17050e23216335f6599f009f71e9614a11b6686e455554b1efd287cd8526a7ebece06dc473e34cd50f61bf52085ff72bb4279144a9fdb3a234d3d589a10fddaf diff --git a/src/ast.scm b/src/ast.scm index a20f8f87f955c..fb2c2630a3876 100644 --- a/src/ast.scm +++ b/src/ast.scm @@ -405,7 +405,8 @@ ;; identify some expressions that are safe to repeat (define (effect-free? e) - (or (not (pair? e)) (ssavalue? e) (sym-dot? e) (quoted? e) (memq (car e) '(null true false)))) + (or (not (pair? e)) (ssavalue? e) (sym-dot? e) (quoted? e) + (memq (car e) '(null true false begin end)))) ;; get the variable name part of a declaration, x::int => x (define (decl-var v) diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 4415dc8686065..57d769aa934a1 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -182,7 +182,7 @@ (define space-sensitive #f) ; seeing `for` stops parsing macro arguments and makes a generator (define for-generator #f) -; treat 'end' like a normal symbol instead of a reserved word +; treat begin/end like special symbols instead of reserved words (define end-symbol #f) ; treat newline like ordinary whitespace instead of as a potential separator (define whitespace-newline #f) @@ -1624,7 +1624,7 @@ (parse-imports s word)) ((do) (error "invalid \"do\" syntax")) - (else (error "unhandled reserved word"))))))) + (else (error (string "unhandled reserved word " word)))))))) (define (parse-do s) (with-bindings @@ -2545,6 +2545,10 @@ (symbol str))) ((eq? t 'true) '(true)) ((eq? t 'false) '(false)) + ;; issue #57269: a[var"begin"] -> 'begin + ;; a[begin] -> '(begin) + ((and end-symbol (eq? t 'begin)) '(begin)) + ((and end-symbol (eq? t 'end)) '(end)) (else t))) ;; parens or tuple diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 4fa6dc2e14a70..5b6b7b4976494 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -113,8 +113,8 @@ ;; replace `begin` and `end` for the closest ref expression, so doesn't go inside nested refs (define (replace-beginend ex a n tuples last) - (cond ((eq? ex 'end) (end-val a n tuples last)) - ((eq? ex 'begin) (begin-val a n tuples last)) + (cond ((equal? ex '(begin)) (begin-val a n tuples last)) + ((equal? ex '(end)) (end-val a n tuples last)) ((or (atom? ex) (quoted? ex)) ex) ((eq? (car ex) 'ref) ;; inside ref only replace within the first argument @@ -1612,7 +1612,7 @@ (idxs (cddr lhs)) (rhs (caddr e))) (let* ((reuse (and (pair? a) - (contains (lambda (x) (eq? x 'end)) + (contains (lambda (x) (equal? x '(end))) idxs))) (arr (if reuse (make-ssavalue) a)) (stmts (if reuse `((= ,arr ,(expand-forms a))) '())) @@ -1870,7 +1870,9 @@ (let ((a (cadr e)) (idxs (cddr e))) (let* ((reuse (and (pair? a) - (contains (lambda (x) (or (eq? x 'begin) (eq? x 'end))) + (contains (lambda (x) + (or (equal? x '(begin)) + (equal? x '(end)))) idxs))) (arr (if reuse (make-ssavalue) a)) (stmts (if reuse `((= ,arr ,a)) '()))) diff --git a/test/show.jl b/test/show.jl index 17f0e2bfbf5e3..3026dcdaa2079 100644 --- a/test/show.jl +++ b/test/show.jl @@ -2377,13 +2377,14 @@ end # begin/end indices @weak_test_repr "a[begin, end, (begin; end)]" -@test_broken repr(Base.remove_linenums!(:(a[begin, end, (begin; end)]))) == ":(a[begin, end, (begin;\n end)])" +@test repr(Base.remove_linenums!(:(a[begin, end, (begin; end)]))) == ":(a[begin, end, (begin;\n end)])" @weak_test_repr "a[begin, end, let x=1; (x+1;); end]" -@test_broken repr(Base.remove_linenums!(:(a[begin, end, let x=1; (x+1;); end]))) == +@test repr(Base.remove_linenums!(:(a[begin, end, let x=1; (x+1;); end]))) == ":(a[begin, end, let x = 1\n begin\n x + 1\n end\n end])" @test_repr "a[(bla;)]" @test_repr "a[(;;)]" @weak_test_repr "a[x -> f(x)]" +@test_broken @weak_test_repr """:([1,2,3,4][:end === :end ? end : var"end"])""" @testset "Base.Iterators" begin @test sprint(show, enumerate("test")) == "enumerate(\"test\")" diff --git a/test/syntax.jl b/test/syntax.jl index 7a7ca63f797da..39ff6fb78b661 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -4198,6 +4198,16 @@ module Ambig57404 end @test Ambig57404.S == 1 +# #57269 +@testset """var"begin"/var"end" in array index""" begin + @test (let var"end" = 1; (1:10)[var"end"]; end) === 1 + @test (let var"end" = 1; (1:10)[end]; end) === 10 + @test (let var"begin" = 2; (1:10)[2var"begin" + 1]; end) === 5 + @test ((1:10)[end === 10 ? end : begin]) === 10 + @test_throws ArgumentError (let var"begin" = nothing; (1:10)[var"begin"]; end) + @test (let a=[1]; a[end]::Int = 100; end) === 100 +end + # Issue #56904 - lambda linearized twice @test (let; try 3; finally try 1; f(() -> x); catch x; end; end; x = 7; end) === 7 @test (let; try 3; finally try 4; finally try 1; f(() -> x); catch x; end; end; end; x = 7; end) === 7