Skip to content

Commit

Permalink
normalize parsing of --> (JuliaLang#36793)
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Aug 5, 2020
1 parent d862442 commit 371bfa8
Show file tree
Hide file tree
Showing 6 changed files with 24 additions and 12 deletions.
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ New language features
Language changes
----------------

* The `-->` operator now lowers to a `:call` expression, so it can be defined as
a function like other operators. The dotted version `.-->` is now parsed as well.
For backwards compatibility, `-->` still parses using its own expression head
instead of `:call`.

Compiler/Runtime improvements
-----------------------------
Expand Down
2 changes: 1 addition & 1 deletion base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1077,7 +1077,7 @@ const uni_ops = Set{Symbol}([:(+), :(-), :(!), :(¬), :(~), :(<:), :(>:), :(√)
const expr_infix_wide = Set{Symbol}([
:(=), :(+=), :(-=), :(*=), :(/=), :(\=), :(^=), :(&=), :(|=), :(÷=), :(%=), :(>>>=), :(>>=), :(<<=),
:(.=), :(.+=), :(.-=), :(.*=), :(./=), :(.\=), :(.^=), :(.&=), :(.|=), :(.÷=), :(.%=), :(.>>>=), :(.>>=), :(.<<=),
:(&&), :(||), :(<:), :($=), :(⊻=), :(>:)])
:(&&), :(||), :(<:), :($=), :(⊻=), :(>:), :(-->)])
const expr_infix = Set{Symbol}([:(:), :(->), Symbol("::")])
const expr_infix_any = union(expr_infix, expr_infix_wide)
const expr_calls = Dict(:call => ('(',')'), :calldecl => ('(',')'),
Expand Down
2 changes: 1 addition & 1 deletion src/ast.scm
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
(string #\( (deparse (caddr e)) #\))))))
((memq (car e) '(... |'|))
(string (deparse (cadr e)) (car e)))
((or (syntactic-op? (car e)) (eq? (car e) '|<:|) (eq? (car e) '|>:|))
((or (syntactic-op? (car e)) (eq? (car e) '|<:|) (eq? (car e) '|>:|) (eq? (car e) '-->))
(if (length= e 2)
(string (car e) (deparse (cadr e)))
(string (deparse (cadr e)) " " (car e) " " (deparse (caddr e)))))
Expand Down
19 changes: 9 additions & 10 deletions src/julia-parser.scm
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,14 @@
; for most operators X there is a .X "elementwise" equivalent
(define (add-dots ops) (append! ops (map (lambda (op) (symbol (string "." op))) ops)))

;; note: there are some strange-looking things in here because
;; the way the lexer works, every prefix of an operator must also
;; be an operator.
(define prec-assignment
(append! (add-dots '(= += -= *= /= //= |\\=| ^= ÷= %= <<= >>= >>>= |\|=| &= ⊻= ≔ ⩴ ≕))
(add-dots '(~))
'(:= $=)))
;; comma - higher than assignment outside parentheses, lower when inside
(define prec-pair (add-dots '(=>)))
(define prec-conditional '(?))
(define prec-arrow (append!
'(-- -->)
(add-dots '(← → ↔ ↚ ↛ ↞ ↠ ↢ ↣ ↦ ↤ ↮ ⇎ ⇍ ⇏ ⇐ ⇒ ⇔ ⇴ ⇶ ⇷ ⇸ ⇹ ⇺ ⇻ ⇼ ⇽ ⇾ ⇿ ⟵ ⟶ ⟷ ⟹ ⟺ ⟻ ⟼ ⟽ ⟾ ⟿ ⤀ ⤁ ⤂ ⤃ ⤄ ⤅ ⤆ ⤇ ⤌ ⤍ ⤎ ⤏ ⤐ ⤑ ⤔ ⤕ ⤖ ⤗ ⤘ ⤝ ⤞ ⤟ ⤠ ⥄ ⥅ ⥆ ⥇ ⥈ ⥊ ⥋ ⥎ ⥐ ⥒ ⥓ ⥖ ⥗ ⥚ ⥛ ⥞ ⥟ ⥢ ⥤ ⥦ ⥧ ⥨ ⥩ ⥪ ⥫ ⥬ ⥭ ⥰ ⧴ ⬱ ⬰ ⬲ ⬳ ⬴ ⬵ ⬶ ⬷ ⬸ ⬹ ⬺ ⬻ ⬼ ⬽ ⬾ ⬿ ⭀ ⭁ ⭂ ⭃ ⭄ ⭇ ⭈ ⭉ ⭊ ⭋ ⭌ ← → ⇜ ⇝ ↜ ↝ ↩ ↪ ↫ ↬ ↼ ↽ ⇀ ⇁ ⇄ ⇆ ⇇ ⇉ ⇋ ⇌ ⇚ ⇛ ⇠ ⇢ ↷ ↶ ↺ ↻ <-- <-->))))
(define prec-arrow (add-dots '(← → ↔ ↚ ↛ ↞ ↠ ↢ ↣ ↦ ↤ ↮ ⇎ ⇍ ⇏ ⇐ ⇒ ⇔ ⇴ ⇶ ⇷ ⇸ ⇹ ⇺ ⇻ ⇼ ⇽ ⇾ ⇿ ⟵ ⟶ ⟷ ⟹ ⟺ ⟻ ⟼ ⟽ ⟾ ⟿ ⤀ ⤁ ⤂ ⤃ ⤄ ⤅ ⤆ ⤇ ⤌ ⤍ ⤎ ⤏ ⤐ ⤑ ⤔ ⤕ ⤖ ⤗ ⤘ ⤝ ⤞ ⤟ ⤠ ⥄ ⥅ ⥆ ⥇ ⥈ ⥊ ⥋ ⥎ ⥐ ⥒ ⥓ ⥖ ⥗ ⥚ ⥛ ⥞ ⥟ ⥢ ⥤ ⥦ ⥧ ⥨ ⥩ ⥪ ⥫ ⥬ ⥭ ⥰ ⧴ ⬱ ⬰ ⬲ ⬳ ⬴ ⬵ ⬶ ⬷ ⬸ ⬹ ⬺ ⬻ ⬼ ⬽ ⬾ ⬿ ⭀ ⭁ ⭂ ⭃ ⭄ ⭇ ⭈ ⭉ ⭊ ⭋ ⭌ ← → ⇜ ⇝ ↜ ↝ ↩ ↪ ↫ ↬ ↼ ↽ ⇀ ⇁ ⇄ ⇆ ⇇ ⇉ ⇋ ⇌ ⇚ ⇛ ⇠ ⇢ ↷ ↶ ↺ ↻ --> <-- <-->)))
(define prec-lazy-or '(|\|\||))
(define prec-lazy-and '(&&))
(define prec-comparison
Expand Down Expand Up @@ -66,7 +61,7 @@
; only allow/strip suffixes for some operators
(define no-suffix? (Set (append prec-assignment prec-conditional prec-lazy-or prec-lazy-and
prec-colon prec-decl prec-dot
'(-- --> -> |<:| |>:| in isa $)
'(-> |<:| |>:| in isa $)
(list ctrans-op trans-op vararg-op))))
(define (maybe-strip-op-suffix op)
(if (symbol? op)
Expand Down Expand Up @@ -115,7 +110,7 @@
; operators that are special forms, not function names
(define syntactic-operators
(append! (add-dots '(= += -= *= /= //= |\\=| ^= ÷= %= <<= >>= >>>= |\|=| &= ⊻=))
'(:= --> $= && |\|\|| |.| ... ->)))
'(:= $= && |\|\|| |.| ... ->)))
(define syntactic-unary-operators '($ & |::|))

(define syntactic-op? (Set syntactic-operators))
Expand Down Expand Up @@ -252,6 +247,12 @@
(if (or (operator? opsym)
(and (or (eq? opsym '<---) (eq? opsym '.<---))
(error (string "invalid operator \"" newop "\"")))
;; -- is not an operator but --> is
(and (or (eq? opsym '--) (eq? opsym '.--))
(read-char port)
(or (begin0 (eqv? (peek-char port) #\>)
(io.ungetc port #\-))
(error (string "invalid operator \"" newop "\""))))
;; <- is not an operator but <-- and <--> are
(and (or (eq? opsym '<-) (eq? opsym '.<-))
(read-char port)
Expand All @@ -261,8 +262,6 @@
(loop newop (peek-char port) sufchar?))
str))
str))))))
(if (equal? str "--")
(error (string "invalid operator \"" str "\"")))
(string->symbol str))))

(define (accum-digits c pred port _-digit-sep)
Expand Down
2 changes: 2 additions & 0 deletions src/julia-syntax.scm
Original file line number Diff line number Diff line change
Expand Up @@ -1960,6 +1960,8 @@
(lambda (e) (expand-forms `(call |<:| ,@(cdr e))))
'|>:|
(lambda (e) (expand-forms `(call |>:| ,@(cdr e))))
'-->
(lambda (e) (expand-forms `(call --> ,@(cdr e))))

'where
(lambda (e) (expand-forms (expand-wheres (cadr e) (cddr e))))
Expand Down
7 changes: 7 additions & 0 deletions test/syntax.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2297,5 +2297,12 @@ end
@test :(a .<-- b.<--c) == Expr(:call, :.<--, :a, Expr(:call, :.<--, :b, :c))
@test :(a<-->b<-->c) == Expr(:call, :<-->, :a, Expr(:call, :<-->, :b, :c))
@test :(a.<-->b .<--> c) == Expr(:call, :.<-->, :a, Expr(:call, :.<-->, :b, :c))
@test :(a --> b --> c) == Expr(:-->, :a, Expr(:-->, :b, :c))
@test :(a --> b.-->c) == Expr(:-->, :a, Expr(:call, :.-->, :b, :c))
let (-->) = (+)
@test (40 --> 2) == 42
end
@test_throws ParseError("invalid operator \"<---\"") Meta.parse("1<---2")
@test_throws ParseError("invalid operator \".<---\"") Meta.parse("1 .<--- 2")
@test_throws ParseError("invalid operator \"--\"") Meta.parse("a---b")
@test_throws ParseError("invalid operator \".--\"") Meta.parse("a.---b")

0 comments on commit 371bfa8

Please sign in to comment.