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

rename colon to :, make other syntax call Base functions #25957

Closed
wants to merge 3 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
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ Language changes

* The parsing of `<|` is now right associative. `|>` remains left associative ([#24153]).

* `:` now parses like other operators, as a call to a function named `:`, instead of
calling `colon` ([#25947]).

* `{ }` expressions now use `braces` and `bracescat` as expression heads instead
of `cell1d` and `cell2d`, and parse similarly to `vect` and `vcat` ([#8470]).

Expand Down
3 changes: 2 additions & 1 deletion base/broadcast.jl
Original file line number Diff line number Diff line change
Expand Up @@ -817,7 +817,8 @@ Base.@propagate_inbounds dotview(args...) = Base.maybeview(args...)
# broadcasting "dot" calls/assignments:

dottable(x) = false # avoid dotting spliced objects (e.g. view calls inserted by @view)
dottable(x::Symbol) = !isoperator(x) || first(string(x)) != '.' || x == :.. # don't add dots to dot operators
# don't add dots to dot operators
dottable(x::Symbol) = (!isoperator(x) || first(string(x)) != '.' || x === :..) && x !== :(:)
dottable(x::Expr) = x.head != :$
undot(x) = x
function undot(x::Expr)
Expand Down
1 change: 1 addition & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ DEPRECATED: use @__MODULE__ instead
end
export current_module

@deprecate colon (:)

module Operators
for op in [:!, :(!=), :(!==), :%, :&, :*, :+, :-, :/, ://, :<, :<:, :<<, :(<=),
Expand Down
5 changes: 4 additions & 1 deletion base/essentials.jl
Original file line number Diff line number Diff line change
Expand Up @@ -591,8 +591,11 @@ Colons (:) are used to signify indexing entire objects or dimensions at once.
Very few operations are defined on Colons directly; instead they are converted
by [`to_indices`](@ref) to an internal vector type (`Base.Slice`) to represent the
collection of indices they span before being used.

The singleton instance of `Colon` is also a function used to construct ranges;
see [`:`](@ref).
"""
struct Colon
struct Colon <: Function
end
const (:) = Colon()

Expand Down
1 change: 0 additions & 1 deletion base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,6 @@ export
circshift,
circshift!,
clamp!,
colon,
conj!,
copy!,
copyto!,
Expand Down
49 changes: 20 additions & 29 deletions base/range.jl
Original file line number Diff line number Diff line change
@@ -1,33 +1,23 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

colon(a::Real, b::Real) = colon(promote(a,b)...)
(:)(a::Real, b::Real) = (:)(promote(a,b)...)

colon(start::T, stop::T) where {T<:Real} = UnitRange{T}(start, stop)
(:)(start::T, stop::T) where {T<:Real} = UnitRange{T}(start, stop)

range(a::Real, len::Integer) = UnitRange{typeof(a)}(a, oftype(a, a+len-1))

colon(start::T, stop::T) where {T} = colon(start, oftype(stop-start, 1), stop)
(:)(start::T, stop::T) where {T} = (:)(start, oftype(stop-start, 1), stop)

range(a, len::Integer) = range(a, oftype(a-a, 1), len)

# first promote start and stop, leaving step alone
colon(start::A, step, stop::C) where {A<:Real,C<:Real} =
colon(convert(promote_type(A,C),start), step, convert(promote_type(A,C),stop))
colon(start::T, step::Real, stop::T) where {T<:Real} = colon(promote(start, step, stop)...)
(:)(start::A, step, stop::C) where {A<:Real,C<:Real} =
(:)(convert(promote_type(A,C),start), step, convert(promote_type(A,C),stop))
(:)(start::T, step::Real, stop::T) where {T<:Real} = (:)(promote(start, step, stop)...)

"""
colon(start, [step], stop)

Called by `:` syntax for constructing ranges.

```jldoctest
julia> colon(1, 2, 5)
1:2:5
```
"""
colon(start::T, step::T, stop::T) where {T<:AbstractFloat} =
(:)(start::T, step::T, stop::T) where {T<:AbstractFloat} =
_colon(OrderStyle(T), ArithmeticStyle(T), start, step, stop)
colon(start::T, step::T, stop::T) where {T<:Real} =
(:)(start::T, step::T, stop::T) where {T<:Real} =
_colon(OrderStyle(T), ArithmeticStyle(T), start, step, stop)
_colon(::Ordered, ::Any, start::T, step, stop::T) where {T} = StepRange(start, step, stop)
# for T<:Union{Float16,Float32,Float64} see twiceprecision.jl
Expand All @@ -37,16 +27,17 @@ _colon(::Any, ::Any, start::T, step, stop::T) where {T} =
StepRangeLen(start, step, floor(Int, (stop-start)/step)+1)

"""
:(start, [step], stop)
(:)(start, [step], stop)

Range operator. `a:b` constructs a range from `a` to `b` with a step size of 1, and `a:s:b`
is similar but uses a step size of `s`. These syntaxes call the function `colon`. The colon
is also used in indexing to select whole dimensions.
is similar but uses a step size of `s`.

`:` is also used in indexing to select whole dimensions.
"""
colon(start::T, step, stop::T) where {T} = _colon(start, step, stop)
colon(start::T, step, stop::T) where {T<:Real} = _colon(start, step, stop)
(:)(start::T, step, stop::T) where {T} = _colon(start, step, stop)
(:)(start::T, step, stop::T) where {T<:Real} = _colon(start, step, stop)
# without the second method above, the first method above is ambiguous with
# colon(start::A, step, stop::C) where {A<:Real,C<:Real}
# (:)(start::A, step, stop::C) where {A<:Real,C<:Real}
function _colon(start::T, step, stop::T) where T
T′ = typeof(start+step)
StepRange(convert(T′,start), step, convert(T′,stop))
Expand All @@ -64,12 +55,12 @@ _range(::Any, ::Any, a::T, step::S, len::Integer) where {T,S} =
StepRangeLen{typeof(a+0*step),T,S}(a, step, len)

# AbstractFloat specializations
colon(a::T, b::T) where {T<:AbstractFloat} = colon(a, T(1), b)
(:)(a::T, b::T) where {T<:AbstractFloat} = (:)(a, T(1), b)
range(a::AbstractFloat, len::Integer) = range(a, oftype(a, 1), len)

colon(a::T, b::AbstractFloat, c::T) where {T<:Real} = colon(promote(a,b,c)...)
colon(a::T, b::AbstractFloat, c::T) where {T<:AbstractFloat} = colon(promote(a,b,c)...)
colon(a::T, b::Real, c::T) where {T<:AbstractFloat} = colon(promote(a,b,c)...)
(:)(a::T, b::AbstractFloat, c::T) where {T<:Real} = (:)(promote(a,b,c)...)
(:)(a::T, b::AbstractFloat, c::T) where {T<:AbstractFloat} = (:)(promote(a,b,c)...)
(:)(a::T, b::Real, c::T) where {T<:AbstractFloat} = (:)(promote(a,b,c)...)

range(a::AbstractFloat, st::AbstractFloat, len::Integer) = range(promote(a, st)..., len)
range(a::Real, st::AbstractFloat, len::Integer) = range(float(a), st, len)
Expand Down Expand Up @@ -887,7 +878,7 @@ end
Array{T,1}(r::AbstractRange{T}) where {T} = vcat(r)
collect(r::AbstractRange) = vcat(r)

reverse(r::OrdinalRange) = colon(last(r), -step(r), first(r))
reverse(r::OrdinalRange) = (:)(last(r), -step(r), first(r))
reverse(r::StepRangeLen) = StepRangeLen(r.ref, -r.step, length(r), length(r)-r.offset+1)
reverse(r::LinSpace) = LinSpace(r.stop, r.start, length(r))

Expand Down
10 changes: 5 additions & 5 deletions base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -971,8 +971,8 @@ end
# show a normal (non-operator) function call, e.g. f(x, y) or A[z]
function show_call(io::IO, head, func, func_args, indent)
op, cl = expr_calls[head]
if isa(func, Symbol) || (isa(func, Expr) &&
(func.head == :. || func.head == :curly))
if (isa(func, Symbol) && func !== :(:)) ||
(isa(func, Expr) && (func.head == :. || func.head == :curly))
show_unquoted(io, func, indent)
else
print(io, '(')
Expand Down Expand Up @@ -1153,7 +1153,7 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int)
end

# infix (i.e. "x <: y" or "x = y")
elseif (head in expr_infix_any && nargs==2) || (head === :(:) && nargs==3)
elseif (head in expr_infix_any && nargs==2)
func_prec = operator_precedence(head)
head_ = head in expr_infix_wide ? " $head " : head
if func_prec <= prec
Expand Down Expand Up @@ -1222,9 +1222,9 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int)
# binary operator (i.e. "x + y")
elseif func_prec > 0 # is a binary operator
na = length(func_args)
if (na == 2 || (na > 2 && func in (:+, :++, :*))) &&
if (na == 2 || (na > 2 && func in (:+, :++, :*)) || (na == 3 && func === :(:))) &&
all(!isa(a, Expr) || a.head !== :... for a in func_args)
sep = " $func "
sep = func === :(:) ? "$func" : " $func "

if func_prec <= prec
show_enclosed_list(io, '(', func_args, sep, ')', indent, func_prec, true)
Expand Down
2 changes: 1 addition & 1 deletion base/twiceprecision.jl
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ function floatrange(a::AbstractFloat, st::AbstractFloat, len::Real, divisor::Abs
steprangelen_hp(T, (a,divisor), (st,divisor), nbitslen(T, len, 1), Int(len), 1)
end

function colon(start::T, step::T, stop::T) where T<:Union{Float16,Float32,Float64}
function (:)(start::T, step::T, stop::T) where T<:Union{Float16,Float32,Float64}
step == 0 && throw(ArgumentError("range step cannot be zero"))
# see if the inputs have exact rational approximations (and if so,
# perform all computations in terms of the rationals)
Expand Down
2 changes: 1 addition & 1 deletion doc/src/base/math.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Base.denominator
Base.:(<<)
Base.:(>>)
Base.:(>>>)
Base.colon
Base.:(:)
Base.range
Base.OneTo
Base.StepRangeLen
Expand Down
6 changes: 3 additions & 3 deletions doc/src/base/punctuation.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ Extended documentation for mathematical symbols & functions is [here](@ref math-
| ``` ` ` ``` | delimit external process (command) specifications |
| `...` | splice arguments into a function call or declare a varargs function |
| `.` | access named fields in objects/modules (calling [`getproperty`](@ref Base.getproperty) or [`setproperty!`](@ref Base.setproperty!)), also prefixes elementwise function calls (calling [`broadcast`](@ref)) |
| `a:b` | range a, a+1, a+2, ..., b (calling [`colon`](@ref)) |
| `a:s:b` | range a, a+s, a+2s, ..., b (also calling [`colon`](@ref)) |
| `:` | index an entire dimension (firstindex:lastindex), see [`Colon`](@ref)) |
| `a:b` | range a, a+1, a+2, ..., b |
| `a:s:b` | range a, a+s, a+2s, ..., b |
| `:` | index an entire dimension (firstindex:lastindex), see [`Colon`](@ref)) |
| `::` | type annotation or [`typeassert`](@ref), depending on context |
| `:( )` | quoted expression |
| `:a` | symbol a |
Expand Down
1 change: 0 additions & 1 deletion doc/src/manual/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,6 @@ A few special expressions correspond to calls to functions with non-obvious name
| `[A; B; C; ...]` | [`vcat`](@ref) |
| `[A B; C D; ...]` | [`hvcat`](@ref) |
| `A'` | [`adjoint`](@ref) |
| `1:n` | [`colon`](@ref) |
| `A[i]` | [`getindex`](@ref) |
| `A[i] = x` | [`setindex!`](@ref) |
| `A.n` | [`getproperty`](@ref Base.getproperty) |
Expand Down
18 changes: 10 additions & 8 deletions src/ast.scm
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
(string.join (map deparse l) sep)))

(define (deparse-prefix-call head args opn cls)
(string (if (decl? head)
(string (if (or (decl? head) (eq? head ':))
(string "(" (deparse head) ")")
(deparse head))
opn (deparse-arglist args) cls))
Expand Down Expand Up @@ -73,20 +73,22 @@
(case (car e)
;; calls and operators
((call)
(if (and (length= e 4) (operator? (cadr e)))
(string #\( (deparse (caddr e)) " " (cadr e) " " (deparse (cadddr e)) #\) )
(deparse-prefix-call (cadr e) (cddr e) #\( #\))))
(cond ((and (eq? (cadr e) ':) (or (length= e 4) (length= e 5)))
(string (deparse (caddr e)) ': (deparse (cadddr e))
(if (length> e 4)
(string ': (deparse (caddddr e)))
"")))
((and (length= e 4) (operator? (cadr e)))
(string #\( (deparse (caddr e)) " " (cadr e) " " (deparse (cadddr e)) #\) ))
(else
(deparse-prefix-call (cadr e) (cddr e) #\( #\)))))
(($ &) (if (pair? (cadr e))
(string (car e) "(" (deparse (cadr e)) ")")
(string (car e) (deparse (cadr e)))))
((|::|) (if (length= e 2)
(string (car e) (deparse (cadr e)))
(string (deparse (cadr e)) (car e) (deparse (caddr e)))))
((comparison) (string.join (map deparse (cdr e)) " "))
((:) (string (deparse (cadr e)) ': (deparse (caddr e))
(if (length> e 3)
(string ': (deparse (cadddr e)))
"")))
((macrocall) (string (cadr e) " " (deparse-arglist (cddr e) " ")))
((kw) (string (deparse (cadr e)) " = " (deparse (caddr e))))
((where) (string (deparse (cadr e)) " where "
Expand Down
21 changes: 6 additions & 15 deletions src/julia-parser.scm
Original file line number Diff line number Diff line change
Expand Up @@ -819,21 +819,12 @@
(define (parse-pipe< s) (parse-RtoL s parse-pipe> is-prec-pipe<? #f parse-pipe<))
(define (parse-pipe> s) (parse-LtoR s parse-range is-prec-pipe>?))

; parse ranges and postfix ...
; colon is strange; 3 arguments with 2 colons yields one call:
; 1:2 => (: 1 2)
; 1:2:3 => (: 1 2 3)
; 1: => (: 1 :)
; 1:2: => (: 1 2 :)
;; not enabled:
;;; :2 => (: 2)
;;; :1:2 => (: (: 1 2))
;;; :1: => (: (: 1 :))
; a simple state machine is up to the task.
; we will leave : expressions as a syntax form, not a call to ':',
; so they can be processed by syntax passes.
;; parse ranges and postfix ...
;; colon is strange; 3 arguments with 2 colons yields one call:
;; 1:2 => (call : 1 2)
;; 1:2:3 => (call : 1 2 3)
(define (parse-range s)
(let loop ((ex (parse-expr s))
(let loop ((ex (parse-expr s))
(first? #t))
(let* ((t (peek-token s))
(spc (ts:space? s)))
Expand All @@ -860,7 +851,7 @@
(error (string "\":" argument "\" found instead of \""
argument ":\"")))
(if first?
(loop (list t ex argument) #f)
(loop (list 'call t ex argument) #f)
(loop (append ex (list argument)) #t)))))
((eq? t '...)
(take-token s)
Expand Down
Loading