Skip to content

Commit

Permalink
fix slurping into function definition (#40738)
Browse files Browse the repository at this point in the history
Discovered while working on #40737. Currently, this throws an
unintuitive error:
```julia
julia> a, f()... = 1, 2, 3
ERROR: syntax: ssavalue with no def
Stacktrace:
 [1] top-level scope
   @ REPL[1]:1
```

Might as well fix this properly - Why not allow function definitions to
slurp a little from time to time? ;)

(cherry picked from commit 5c49a0d)
  • Loading branch information
simeonschaub authored and KristofferC committed Jul 7, 2021
1 parent 26bfefa commit 8ebbd94
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 4 deletions.
12 changes: 8 additions & 4 deletions src/julia-syntax.scm
Original file line number Diff line number Diff line change
Expand Up @@ -1456,7 +1456,7 @@
(cons R elts)))
((vararg? L)
(if (null? (cdr lhss))
(let ((temp (make-ssavalue)))
(let ((temp (if (eventually-call? (cadr L)) (gensy) (make-ssavalue))))
`(block ,@(reverse stmts)
(= ,temp (tuple ,@rhss))
,@(reverse after)
Expand Down Expand Up @@ -2155,9 +2155,13 @@
((eq? l x) #t)
(else (in-lhs? x (cdr lhss)))))))
;; in-lhs? also checks for invalid syntax, so always call it first
(let* ((xx (if (or (and (not (in-lhs? x lhss)) (symbol? x))
(ssavalue? x))
x (make-ssavalue)))
(let* ((xx (cond ((or (and (not (in-lhs? x lhss)) (symbol? x))
(ssavalue? x))
x)
((and (pair? lhss) (vararg? (last lhss))
(eventually-call? (cadr (last lhss))))
(gensy))
(else (make-ssavalue))))
(ini (if (eq? x xx) '() (list (sink-assignment xx (expand-forms x)))))
(n (length lhss))
;; skip last assignment if it is an all-underscore vararg
Expand Down
12 changes: 12 additions & 0 deletions test/syntax.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2937,3 +2937,15 @@ end
@test eval(Meta.parse("`a\\\r\nb`")) == `ab`
@test eval(Meta.parse("`a\\\rb`")) == `ab`
end

@testset "slurping into function def" begin
x, f()... = [1, 2, 3]
@test x == 1
@test f() == [2, 3]
# test that call to `Base.rest` is outside the definition of `f`
@test f() === f()

x, f()... = 1, 2, 3
@test x == 1
@test f() == (2, 3)
end

0 comments on commit 8ebbd94

Please sign in to comment.