Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sanitize the ternary operator and question mark parsing situation (deprecations only) #22712

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,13 @@ Deprecated or removed
and the Base signal processing functions which used FFTs are now in DSP.jl ([#21956]).

* The `corrected` positional argument to `cov` has been deprecated in favor of
a keyword argument with the same name (#21709).
a keyword argument with the same name ([#21709]).

* Omitting a space between the condition and `?` in a ternary expression has been deprecated.
* Omitting spaces around the `?` and the `:` tokens in a ternary expression has been deprecated.
Ternaries must now include some amount of whitespace, e.g. `x ? a : b` rather than
`x? a : b` ([#22523]).
`x?a:b` ([#22523] and [#22712]).

* `?` can no longer be used as an identifier name ([#22712])

* The method `replace(s::AbstractString, pat, r, count)` with `count <= 0` is deprecated
in favor of `replace(s::AbstractString, pat, r, typemax(Int))` ([#22325]).
Expand Down Expand Up @@ -994,4 +996,6 @@ Command-line option changes
[#22310]: https://github.com/JuliaLang/julia/issues/22310
[#22523]: https://github.com/JuliaLang/julia/issues/22523
[#22532]: https://github.com/JuliaLang/julia/issues/22532
[#22709]: https://github.com/JuliaLang/julia/issues/22709
[#22712]: https://github.com/JuliaLang/julia/issues/22712
[#22732]: https://github.com/JuliaLang/julia/issues/22732
4 changes: 2 additions & 2 deletions base/docs/helpdb/Base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ the byte representation is different.
This would create a 25-by-30000 `BitArray`, linked to the file associated with stream `s`.
"""
Mmap.mmap(io, ::BitArray, dims = ?, offset = ?)
Mmap.mmap(io, ::BitArray, dims, offset)

"""
sizeof(T)
Expand Down Expand Up @@ -2151,7 +2151,7 @@ julia> pop!(d, "e", 4)
4
```
"""
pop!(collection,key,?)
pop!(collection,key,default)

"""
pop!(collection) -> item
Expand Down
2 changes: 1 addition & 1 deletion base/grisu/bignum.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ function generateshortestdigits!(num,den,minus,plus,is_even,buffer)
in_delta_room_minus = is_even ?
Bignums.lessequal(num,minus) : Bignums.less(num,minus)
in_delta_room_plus = is_even ?
Bignums.pluscompare(num,plus,den) >= 0: Bignums.pluscompare(num,plus,den) > 0
Bignums.pluscompare(num,plus,den) >= 0 : Bignums.pluscompare(num,plus,den) > 0
if !in_delta_room_minus && !in_delta_room_plus
Bignums.times10!(num)
Bignums.times10!(minus)
Expand Down
2 changes: 1 addition & 1 deletion base/libgit2/repository.jl
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ function reset!(repo::GitRepo, obj::Nullable{<:GitObject}, pathspecs::AbstractSt
@check ccall((:git_reset_default, :libgit2), Cint,
(Ptr{Void}, Ptr{Void}, Ptr{StrArrayStruct}),
repo.ptr,
isnull(obj) ? C_NULL: Base.get(obj).ptr,
isnull(obj) ? C_NULL : Base.get(obj).ptr,
collect(pathspecs))
return head_oid(repo)
end
Expand Down
2 changes: 1 addition & 1 deletion base/linalg/matmul.jl
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ end
# blas.jl defines matmul for floats; other integer and mixed precision
# cases are handled here

lapack_size(t::Char, M::AbstractVecOrMat) = (size(M, t=='N' ? 1:2), size(M, t=='N' ? 2:1))
lapack_size(t::Char, M::AbstractVecOrMat) = (size(M, t=='N' ? 1 : 2), size(M, t=='N' ? 2 : 1))

function copy!(B::AbstractVecOrMat, ir_dest::UnitRange{Int}, jr_dest::UnitRange{Int}, tM::Char, M::AbstractVecOrMat, ir_src::UnitRange{Int}, jr_src::UnitRange{Int})
if tM == 'N'
Expand Down
2 changes: 1 addition & 1 deletion base/linalg/special.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ end

convert(::Type{Tridiagonal}, A::Bidiagonal{T}) where {T} =
Tridiagonal(A.uplo == 'U' ? zeros(T, size(A.dv,1)-1) : A.ev, A.dv,
A.uplo == 'U' ? A.ev:zeros(T, size(A.dv,1)-1))
A.uplo == 'U' ? A.ev : zeros(T, size(A.dv,1)-1))

function convert(::Type{Bidiagonal}, A::SymTridiagonal)
if !iszero(A.ev)
Expand Down
2 changes: 1 addition & 1 deletion base/parse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ function parse(str::AbstractString, pos::Int; greedy::Bool=true, raise::Bool=tru
bstr = String(str)
ex, pos = ccall(:jl_parse_string, Any,
(Ptr{UInt8}, Csize_t, Int32, Int32),
bstr, sizeof(bstr), pos-1, greedy ? 1:0)
bstr, sizeof(bstr), pos-1, greedy ? 1 : 0)
if raise && isa(ex,Expr) && ex.head === :error
throw(ParseError(ex.args[1]))
end
Expand Down
2 changes: 1 addition & 1 deletion base/version.jl
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ function banner(io::IO = STDOUT)
commit_string = "$(branch)/$(commit) (fork: $(distance) commits, $(days) $(unit))"
end
end
commit_date = !isempty(GIT_VERSION_INFO.date_string) ? " ($(GIT_VERSION_INFO.date_string))": ""
commit_date = !isempty(GIT_VERSION_INFO.date_string) ? " ($(GIT_VERSION_INFO.date_string))" : ""

if have_color
c = text_colors
Expand Down
4 changes: 3 additions & 1 deletion doc/src/manual/control-flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,9 @@ a ? b : c

The expression `a`, before the `?`, is a condition expression, and the ternary operation evaluates
the expression `b`, before the `:`, if the condition `a` is `true` or the expression `c`, after
the `:`, if it is `false`.
the `:`, if it is `false`. Note that the spaces around `?` and `:` are mandatory: an expression
like `a?b:c` is not a valid ternary expression (but a newline is acceptable after both the `?` and
the `:`).

The easiest way to understand this behavior is to see an example. In the previous example, the
`println` call is shared by all three branches: the only real choice is which literal string to
Expand Down
23 changes: 17 additions & 6 deletions src/julia-parser.scm
Original file line number Diff line number Diff line change
Expand Up @@ -736,11 +736,20 @@
(cond ((eq? (peek-token s) '?)
(begin (if (not (ts:space? s))
(syntax-deprecation s (string (deparse ex) "?") (string (deparse ex) " ?")))
(take-token s)
(take-token s) ; take the ?
(let ((t (with-whitespace-newline (without-range-colon (peek-token s)))))
(if (not (ts:space? s))
(syntax-deprecation s (string (deparse ex) " ?" (deparse t)) (string (deparse ex) " ? " (deparse t)))))
(let ((then (without-range-colon (parse-eq* s))))
(if (not (eq? (take-token s) ':))
(error "colon expected in \"?\" expression")
(list 'if ex then (parse-eq* s))))))
(if (not (eq? (peek-token s) ':))
(error "colon expected in \"?\" expression"))
(if (not (ts:space? s))
(syntax-deprecation s (string (deparse ex) " ? " (deparse then) ":") (string (deparse ex) " ? " (deparse then) " :")))
(take-token s) ; take the :
(let ((t (with-whitespace-newline (peek-token s))))
(if (not (ts:space? s))
(syntax-deprecation s (string (deparse ex) " ? " (deparse then) " :" t) (string (deparse ex) " ? " (deparse then) " : " t))))
(list 'if ex then (parse-eq* s)))))
(else ex))))

(define (parse-arrow s) (parse-RtoL s parse-or is-prec-arrow? (eq? t '-->) parse-arrow))
Expand Down Expand Up @@ -1996,8 +2005,10 @@
(read (open-input-string (string #\" s #\"))))))

(define-macro (check-identifier ex)
`(if (or (syntactic-op? ,ex) (eq? ,ex '....))
(error (string "invalid identifier name \"" ,ex "\""))))
`(begin (if (or (syntactic-op? ,ex) (eq? ,ex '....))
(error (string "invalid identifier name \"" ,ex "\"")))
(if (eq? ,ex '?)
(syntax-deprecation s "`?` used as an identifier" "")))) ; merge with above check in v1.0

;; parse numbers, identifiers, parenthesized expressions, lists, vectors, etc.
(define (parse-atom s (checked #t))
Expand Down
2 changes: 1 addition & 1 deletion test/enums.jl
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ end
@test Integer(_zerobi) == 1

# can't use non-identifiers as enum members
@test_throws ArgumentError eval(:(@enum(Test2, ?)))
@test_throws ArgumentError eval(:(@enum Test2 x ? 1 : 2))
@test_throws ArgumentError eval(:(@enum Test22 1=2))

# other Integer types of enum members
Expand Down