Skip to content

Commit

Permalink
Merge pull request #21576 from JuliaLang/jb/anonfnwhere
Browse files Browse the repository at this point in the history
fix parsing and lowering of multi-line anon functions with `where`
  • Loading branch information
JeffBezanson authored Apr 27, 2017
2 parents 2d803f3 + 9b1aeb1 commit f2f3959
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 13 deletions.
35 changes: 23 additions & 12 deletions src/julia-parser.scm
Original file line number Diff line number Diff line change
Expand Up @@ -1137,6 +1137,16 @@
(and (eq? (car sig) 'where)
(valid-func-sig? paren (cadr sig))))))

(define (unwrap-where x)
(if (and (pair? x) (eq? (car x) 'where))
(unwrap-where (cadr x))
x))

(define (rewrap-where x w)
(if (and (pair? w) (eq? (car w) 'where))
(list 'where (rewrap-where x (cadr w)) (caddr w))
x))

(define (parse-struct-def s mut? word)
(if (reserved-word? (peek-token s))
(error (string "invalid type name \"" (take-token s) "\"")))
Expand Down Expand Up @@ -1258,18 +1268,19 @@
(error (string "expected \"end\" in definition of function \"" sig "\"")))
(take-token s)
`(function ,sig))
(let* ((def (if (or (symbol? sig)
(and (pair? sig) (eq? (car sig) '|::|)
(symbol? (cadr sig))))
(if paren
;; in "function (x)" the (x) is a tuple
`(tuple ,sig)
;; function foo => syntax error
(error (string "expected \"(\" in " word " definition")))
(if (not (valid-func-sig? paren sig))
(error (string "expected \"(\" in " word " definition"))
sig)))
(body (parse-block s)))
(let* ((usig (unwrap-where sig))
(def (if (or (symbol? usig)
(and (pair? usig) (eq? (car usig) '|::|)
(symbol? (cadr usig))))
(if paren
;; in "function (x)" the (x) is a tuple
(rewrap-where `(tuple ,usig) sig)
;; function foo => syntax error
(error (string "expected \"(\" in " word " definition")))
(if (not (valid-func-sig? paren sig))
(error (string "expected \"(\" in " word " definition"))
sig)))
(body (parse-block s)))
(expect-end s word)
(list word def body)))))

Expand Down
7 changes: 6 additions & 1 deletion src/julia-syntax.scm
Original file line number Diff line number Diff line change
Expand Up @@ -969,8 +969,13 @@
(list* g (if isamp `(& ,ca) ca) C))))))))

(define (expand-function-def e) ;; handle function or stagedfunction
(define (just-arglist? ex)
(and (pair? ex)
(or (memq (car ex) '(tuple block))
(and (eq? (car ex) 'where)
(just-arglist? (cadr ex))))))
(let ((name (cadr e)))
(if (and (pair? name) (memq (car name) '(tuple block)))
(if (just-arglist? name)
(expand-forms (cons '-> (cdr e)))
(expand-function-def- e))))

Expand Down
13 changes: 13 additions & 0 deletions test/parse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1018,6 +1018,19 @@ end
short_where_call = :(f(x::T) where T = T)
@test short_where_call.args[2].head == :block

# `where` with multi-line anonymous functions
let f = function (x::T) where T
T
end
@test f(:x) === Symbol
end

let f = function (x::T, y::S) where T<:S where S
(T,S)
end
@test f(0,1) === (Int,Int)
end

# issue #20541
@test parse("[a .!b]") == Expr(:hcat, :a, Expr(:call, :(.!), :b))

Expand Down

0 comments on commit f2f3959

Please sign in to comment.