diff --git a/NEWS.md b/NEWS.md index 50bef68b74857..28de3044263b8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -32,6 +32,9 @@ Language changes * A warning is always given when a method is overwritten (previously, this was done only when the new and old definitions were in separate modules) ([#14759]). + * `A <: B` is parsed as `Expr(:(<:), :A, :B)` in all cases ([#9503]). This also applies to the + `>:` operator. + Command-line option changes --------------------------- @@ -1690,6 +1693,7 @@ Too numerous to mention. [#9434]: https://github.com/JuliaLang/julia/issues/9434 [#9452]: https://github.com/JuliaLang/julia/issues/9452 [#9487]: https://github.com/JuliaLang/julia/issues/9487 +[#9503]: https://github.com/JuliaLang/julia/issues/9503 [#9569]: https://github.com/JuliaLang/julia/issues/9569 [#9575]: https://github.com/JuliaLang/julia/issues/9575 [#9578]: https://github.com/JuliaLang/julia/issues/9578 @@ -1793,4 +1797,6 @@ Too numerous to mention. [#14469]: https://github.com/JuliaLang/julia/issues/14469 [#14759]: https://github.com/JuliaLang/julia/issues/14759 [#14798]: https://github.com/JuliaLang/julia/issues/14798 +[#15192]: https://github.com/JuliaLang/julia/issues/15192 [#15242]: https://github.com/JuliaLang/julia/issues/15242 +[#15258]: https://github.com/JuliaLang/julia/issues/15258 diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 566134e6f5eeb..e5643cbe457f6 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -780,12 +780,21 @@ (let loop ((ex (parse-pipes s)) (first #t)) (let ((t (peek-token s))) - (if (not (is-prec-comparison? t)) - ex - (begin (take-token s) - (if first - (loop (list 'comparison ex t (parse-pipes s)) #f) - (loop (append ex (list t (parse-pipes s))) #f))))))) + (cond ((is-prec-comparison? t) + (begin (take-token s) + (if first + (loop (list 'comparison ex t (parse-pipes s)) #f) + (loop (append ex (list t (parse-pipes s))) #f)))) + (first ex) + ((length= ex 4) + ;; only a single comparison; special chained syntax not required + (let ((op (caddr ex)) + (arg1 (cadr ex)) + (arg2 (cadddr ex))) + (if (or (eq? op '|<:|) (eq? op '|>:|)) + `(,op ,arg1 ,arg2) + ex))) + (else ex))))) (define closing-token? (let ((closer? (Set '(else elseif catch finally #\, #\) #\] #\} #\;)))) @@ -905,13 +914,6 @@ (else ex))))) -;; convert (comparison a <: b) to (<: a b) -(define (subtype-syntax e) - (if (and (pair? e) (eq? (car e) 'comparison) - (length= e 4) (eq? (caddr e) '|<:|)) - `(<: ,(cadr e) ,(cadddr e)) - e)) - (define (parse-unary-prefix s) (let ((op (peek-token s))) (if (syntactic-unary-op? op) @@ -1031,8 +1033,7 @@ (string (deparse ex) " " (deparse t)) (string (deparse ex) (deparse t)))) (take-token s) - (loop (list* 'curly ex - (map subtype-syntax (parse-arglist s #\} ))))) + (loop (list* 'curly ex (parse-arglist s #\} )))) ((#\") (if (and (symbol? ex) (not (operator? ex)) (not (ts:space? s))) @@ -1066,7 +1067,7 @@ " expected \"end\", got \"" t "\"")))))) (define (parse-subtype-spec s) - (subtype-syntax (parse-comparison s))) + (parse-comparison s)) ;; parse expressions or blocks introduced by syntactic reserved words (define (parse-resword s word) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 741d77b2698cf..234363df75e46 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1484,6 +1484,10 @@ `(call (top next) ,coll ,state)) ,body)))))))) +;; convert an operator parsed as (op a b) to (call op a b) +(define (syntactic-op-to-call e) + `(call ,(car e) ,(expand-forms (cadr e)) ,(expand-forms (caddr e)))) + ;; table mapping expression head to a function expanding that form (define expand-table (table @@ -1520,9 +1524,9 @@ (lambda (e) `(call (top getfield) ,(expand-forms (cadr e)) ,(expand-forms (caddr e)))) - 'in - (lambda (e) - `(call in ,(expand-forms (cadr e)) ,(expand-forms (caddr e)))) + 'in syntactic-op-to-call + '|<:| syntactic-op-to-call + '|>:| syntactic-op-to-call 'const expand-const-decl 'local expand-local-or-global-decl diff --git a/test/parse.jl b/test/parse.jl index d0ff8b9fa094e..7cf818a39c4c5 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -365,3 +365,9 @@ let a⊂b = reduce(&, x ∈ b for x in a) && length(b)>length(a) @test !([1,2] ⊂ [1,3,4]) @test !([1,2] ⊂ [1,2]) end + +# issue #9503 +@test parse("x<:y") == Expr(:(<:), :x, :y) +@test parse("x>:y") == Expr(:(>:), :x, :y) +@test parse("x<:y<:z").head === :comparison +@test parse("x>:y<:z").head === :comparison