Skip to content

Commit

Permalink
Back out a[begin] syntax
Browse files Browse the repository at this point in the history
It was decided to delay this syntax change until after 1.0, since it
is non-breaking. Once somebody wants to take this up again, they can
simply revert this commit.
  • Loading branch information
Keno committed Jan 25, 2018
1 parent 742a539 commit e016f11
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 40 deletions.
3 changes: 0 additions & 3 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,6 @@ New language features
* Values for `Enum`s can now be specified inside of a `begin` block when using the
`@enum` macro ([#25424]).

* `a[begin]` can now be used to address the first element of an integer-indexed collection `a`.
The index is computed by `firstindex(a)` ([#23554]).

Language changes
----------------

Expand Down
4 changes: 2 additions & 2 deletions doc/src/manual/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -692,8 +692,8 @@ the results (see [Pre-allocating outputs](@ref)). A convenient syntax for this i
is equivalent to `broadcast!(identity, X, ...)` except that, as above, the `broadcast!` loop is
fused with any nested "dot" calls. For example, `X .= sin.(Y)` is equivalent to `broadcast!(sin, X, Y)`,
overwriting `X` with `sin.(Y)` in-place. If the left-hand side is an array-indexing expression,
e.g. `X[begin+1:end] .= sin.(Y)`, then it translates to `broadcast!` on a `view`, e.g.
`broadcast!(sin, view(X, firstindex(X)+1:lastindex(X)), Y)`,
e.g. `X[2:end] .= sin.(Y)`, then it translates to `broadcast!` on a `view`, e.g.
`broadcast!(sin, view(X, 2:lastindex(X)), Y)`,
so that the left-hand side is updated in-place.

Since adding dots to many operations and function calls in an expression
Expand Down
9 changes: 4 additions & 5 deletions doc/src/manual/interfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,8 @@ julia> collect(Iterators.reverse(Squares(10)))' # transposed to save space
|:-------------------- |:-------------------------------- |
| `getindex(X, i)` | `X[i]`, indexed element access |
| `setindex!(X, v, i)` | `X[i] = v`, indexed assignment |
| `firstindex(X)` | The first index, used in `X[begin]` |
| `lastindex(X)` | The last index, used in `X[end]` |
| `firstindex(X)` | The first index |
| `lastindex(X)` | The last index, used in `X[end]` |

For the `Squares` iterable above, we can easily compute the `i`th element of the sequence by squaring
it. We can expose this as an indexing expression `S[i]`. To opt into this behavior, `Squares`
Expand All @@ -178,9 +178,8 @@ julia> Squares(100)[23]
529
```

Additionally, to support the syntax `S[begin]` and `S[end]`, we must define [`firstindex`](@ref) and
[`lastindex`](@ref) to specify the first and last valid
index, respectively:
Additionally, to support the syntax `S[end]`, we must define [`lastindex`](@ref) to specify the last
valid index. It is recommended to also define [`firstindex`](@ref) to specify the first valid index:

```jldoctest squaretype
julia> Base.firstindex(S::Squares) = 1
Expand Down
9 changes: 3 additions & 6 deletions doc/src/manual/strings.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,6 @@ julia> """Contains "quote" characters"""
If you want to extract a character from a string, you index into it:

```jldoctest helloworldstring
julia> str[begin]
'H': ASCII/Unicode U+0048 (category Lu: Letter, uppercase)
julia> str[1]
'H': ASCII/Unicode U+0048 (category Lu: Letter, uppercase)
Expand All @@ -183,8 +180,8 @@ julia> str[end]

Many Julia objects, including strings, can be indexed with integers. The index of the first
element is returned by [`firstindex(str)`](@ref), and the index of the last element
with [`lastindex(str)`](@ref). The keywords `begin` and `end` can be used inside an indexing
operation as shorthand for the first and last index along the given dimension.
with [`lastindex(str)`](@ref). The keyword`end` can be used inside an indexing
operation as shorthand for the last index along the given dimension.
Most indexing in Julia is 1-based: the first element of many integer-indexed objects is found at
index 1. (As we will see below, this does not necessarily mean that the last element is found
at index `n`, where `n` is the length of the string.)
Expand All @@ -203,7 +200,7 @@ julia> str[end÷2]
Using an index less than 1 or greater than `end` raises an error:

```jldoctest helloworldstring
julia> str[begin-1]
julia> str[0]
ERROR: BoundsError: attempt to access "Hello, world.\n"
at index [0]
[...]
Expand Down
36 changes: 12 additions & 24 deletions src/julia-syntax.scm
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,11 @@
(define (expand-compare-chain e)
(car (expand-vector-compare e)))

;; return the appropriate computation for a `begin` or `end` symbol for indexing
;; return the appropriate computation for an `end` symbol for indexing
;; the array `a` in the `n`th index.
;; `tuples` are a list of the splatted arguments that precede index `n`
;; `last` = is this last index?
;; returns a call to, e.g., lastindex(a) or last(axes(a,n))
;; returns a call to lastindex(a) or last(axes(a,n))
(define (end-val a n tuples last)
(if (null? tuples)
(if (and last (= n 1))
Expand All @@ -101,31 +101,20 @@
tuples))))
`(call (top last) (call (top axes) ,a ,dimno)))))

(define (begin-val a n tuples last)
(if (null? tuples)
(if (and last (= n 1))
`(call (top firstindex) ,a)
`(call (top first) (call (top axes) ,a ,n)))
(let ((dimno `(call (top +) ,(- n (length tuples))
,.(map (lambda (t) `(call (top length) ,t))
tuples))))
`(call (top first) (call (top axes) ,a ,dimno)))))

;; replace `begin` and `end` for the closest ref expression, so doesn't go inside nested refs
(define (replace-beginend ex a n tuples last)
;; replace `end` for the closest ref expression, so doesn't go inside nested refs
(define (replace-end ex a n tuples last)
(cond ((eq? ex 'end) (end-val a n tuples last))
((eq? ex 'begin) (begin-val a n tuples last))
((or (atom? ex) (quoted? ex)) ex)
((eq? (car ex) 'ref)
;; inside ref only replace within the first argument
(list* 'ref (replace-beginend (cadr ex) a n tuples last)
(list* 'ref (replace-end (cadr ex) a n tuples last)
(cddr ex)))
(else
(cons (car ex)
(map (lambda (x) (replace-beginend x a n tuples last))
(map (lambda (x) (replace-end x a n tuples last))
(cdr ex))))))

;; go through indices and replace the `begin` or `end` symbol
;; go through indices and replace the `end` symbol
;; a = array being indexed, i = list of indices
;; returns (values index-list stmts) where stmts are statements that need
;; to execute first.
Expand All @@ -144,17 +133,17 @@
(loop (cdr lst) (+ n 1)
stmts
(cons (cadr idx) tuples)
(cons `(... ,(replace-beginend (cadr idx) a n tuples last))
(cons `(... ,(replace-end (cadr idx) a n tuples last))
ret))
(let ((g (make-ssavalue)))
(loop (cdr lst) (+ n 1)
(cons `(= ,g ,(replace-beginend (cadr idx) a n tuples last))
(cons `(= ,g ,(replace-end (cadr idx) a n tuples last))
stmts)
(cons g tuples)
(cons `(... ,g) ret))))
(loop (cdr lst) (+ n 1)
stmts tuples
(cons (replace-beginend idx a n tuples last) ret)))))))
(cons (replace-end idx a n tuples last) ret)))))))

;; GF method does not need to keep decl expressions on lambda args
;; except for rest arg
Expand Down Expand Up @@ -1511,8 +1500,7 @@
(idxs (cddr e)))
(let* ((reuse (and (pair? a)
(contains (lambda (x)
(or (eq? x 'begin)
(eq? x 'end)
(or (eq? x 'end)
(eq? x ':)
(and (pair? x)
(eq? (car x) ':))))
Expand All @@ -1527,7 +1515,7 @@

(define (expand-update-operator op op= lhs rhs . declT)
(cond ((and (pair? lhs) (eq? (car lhs) 'ref))
;; expand indexing inside op= first, to remove "begin", "end", and ":"
;; expand indexing inside op= first, to remove "end" and ":"
(let* ((ex (partially-expand-ref lhs))
(stmts (butlast (cdr ex)))
(refex (last (cdr ex)))
Expand Down

0 comments on commit e016f11

Please sign in to comment.