diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 4bd9723fce02f..a51ff05b2cb16 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -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) "\""))) @@ -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))))) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index a0b2ced82bbdb..3828112cf4b60 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -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)))) diff --git a/test/parse.jl b/test/parse.jl index 7528507ed7b6a..6d5716dbedb4f 100644 --- a/test/parse.jl +++ b/test/parse.jl @@ -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))