@@ -306,6 +306,22 @@ function is_valid_identifier(k)
306306 ! (is_syntactic_operator (k) || k in KSet " ? .'" )
307307end
308308
309+ # The expression is a call after stripping `where` and `::`
310+ function was_eventually_call (ps:: ParseState )
311+ stream = ps. stream
312+ p = position (ps)
313+ while true
314+ kb = peek_behind (stream, p). kind
315+ if kb == K " call"
316+ return true
317+ elseif kb == K " where" || kb == K " ::"
318+ p = first_child_position (ps. stream, p)
319+ else
320+ return false
321+ end
322+ end
323+ end
324+
309325# -------------------------------------------------------------------------------
310326# Parser
311327#
@@ -1786,7 +1802,26 @@ function parse_resword(ps::ParseState)
17861802 emit (ps, mark, K " error" , error= " expected assignment after `const`" )
17871803 end
17881804 elseif word in KSet " function macro"
1789- parse_function (ps)
1805+ bump (ps, TRIVIA_FLAG)
1806+ bump_trivia (ps)
1807+ has_body = parse_function_signature (ps, word == K " function" )
1808+ if has_body
1809+ # The function body
1810+ # function f() \n a \n b end ==> (function (call f) (block a b))
1811+ # function f() end ==> (function (call f) (block))
1812+ parse_block (ps)
1813+ bump_closing_token (ps, K " end" )
1814+ emit (ps, mark, word)
1815+ else
1816+ # Function/macro definition with no methods
1817+ # function f end ==> (function f)
1818+ # (function f \n end) ==> (function f)
1819+ # function f \n\n end ==> (function f)
1820+ # function $f end ==> (function ($ f))
1821+ # macro f end ==> (macro f)
1822+ bump (ps, TRIVIA_FLAG, skip_newlines= true )
1823+ emit (ps, mark, word)
1824+ end
17901825 elseif word == K " abstract"
17911826 # Abstract type definitions
17921827 # abstract type A end ==> (abstract A)
@@ -1968,23 +2003,17 @@ function parse_global_local_const_vars(ps)
19682003end
19692004
19702005# Parse function and macro definitions
1971- function parse_function (ps:: ParseState )
1972- mark = position (ps)
1973- word = peek (ps)
1974- @check word in KSet " macro function"
1975- is_function = word == K " function"
2006+ function parse_function_signature (ps:: ParseState , is_function:: Bool )
19762007 is_anon_func = false
1977- bump (ps, TRIVIA_FLAG)
1978- bump_trivia (ps)
19792008
1980- def_mark = position (ps)
2009+ mark = position (ps)
19812010 if ! is_function
19822011 # Parse macro name
19832012 parse_identifier_or_interpolate (ps)
19842013 kb = peek_behind (ps). orig_kind
19852014 if is_initial_reserved_word (ps, kb)
19862015 # macro while(ex) end ==> (macro (call (error while) ex) (block))
1987- emit (ps, def_mark , K " error" , error= " Invalid macro name" )
2016+ emit (ps, mark , K " error" , error= " Invalid macro name" )
19882017 else
19892018 # macro f() end ==> (macro (call f) (block))
19902019 # macro (:)(ex) end ==> (macro (call : ex) (block))
@@ -1997,6 +2026,7 @@ function parse_function(ps::ParseState)
19972026 # When an initial parenthesis is present, we might either have
19982027 # * the function name in parens, followed by (args...)
19992028 # * an anonymous function argument list in parens
2029+ # * the whole function declaration in parens
20002030 #
20012031 # This should somewhat parse as in parse_paren() (this is what
20022032 # the flisp parser does), but that results in weird parsing of
@@ -2005,22 +2035,36 @@ function parse_function(ps::ParseState)
20052035 bump (ps, TRIVIA_FLAG)
20062036 is_empty_tuple = peek (ps, skip_newlines= true ) == K " )"
20072037 opts = parse_brackets (ps, K " )" ) do _, _, _, _
2008- _is_anon_func = peek (ps, 2 ) != K " ("
2038+ _parsed_call = was_eventually_call (ps)
2039+ _is_anon_func = peek (ps, 2 ) != K " (" && ! _parsed_call
20092040 return (needs_parameters = _is_anon_func,
2010- is_anon_func = _is_anon_func)
2041+ is_anon_func = _is_anon_func,
2042+ parsed_call = _parsed_call)
20112043 end
20122044 is_anon_func = opts. is_anon_func
2045+ if opts. parsed_call
2046+ # Compat: Ugly case where extra parentheses existed and we've
2047+ # already parsed the whole signature.
2048+ # function (f() where T) end ==> (function (where (call f) T) (block))
2049+ # function (f()::S) end ==> (function (:: (call f) S) (block))
2050+ #
2051+ # TODO : Warn for use of parens? The precedence of `::` and
2052+ # `where` don't work inside parens so this is a bit of a syntax
2053+ # oddity/aberration.
2054+ return true
2055+ end
20132056 if is_anon_func
20142057 # function (x) body end ==> (function (tuple x) (block body))
2058+ # function (x::f()) end ==> (function (tuple (:: x (call f))) (block))
20152059 # function (x,y) end ==> (function (tuple x y) (block))
20162060 # function (x=1) end ==> (function (tuple (= x 1)) (block))
20172061 # function (;x=1) end ==> (function (tuple (parameters (= x 1))) (block))
2018- emit (ps, def_mark , K " tuple" )
2062+ emit (ps, mark , K " tuple" )
20192063 elseif is_empty_tuple
20202064 # Weird case which is consistent with parse_paren but will be
20212065 # rejected in lowering
20222066 # function ()(x) end ==> (function (call (tuple) x) (block))
2023- emit (ps, def_mark , K " tuple" )
2067+ emit (ps, mark , K " tuple" )
20242068 else
20252069 # function (:)() end ==> (function (call :) (block))
20262070 # function (x::T)() end ==> (function (call (:: x T)) (block))
@@ -2033,7 +2077,7 @@ function parse_function(ps::ParseState)
20332077 kb = peek_behind (ps). orig_kind
20342078 if is_reserved_word (kb)
20352079 # function begin() end ==> (function (call (error begin)) (block))
2036- emit (ps, def_mark , K " error" , error= " Invalid function name" )
2080+ emit (ps, mark , K " error" , error= " Invalid function name" )
20372081 else
20382082 # function f() end ==> (function (call f) (block))
20392083 # function type() end ==> (function (call type) (block))
@@ -2045,26 +2089,18 @@ function parse_function(ps::ParseState)
20452089 end
20462090 end
20472091 if peek (ps, skip_newlines= true ) == K " end" && ! is_anon_func
2048- # Function/macro definition with no methods
2049- # function f end ==> (function f)
2050- # (function f \n end) ==> (function f)
2051- # function f \n\n end ==> (function f)
2052- # function $f end ==> (function ($ f))
2053- # macro f end ==> (macro f)
2054- bump (ps, TRIVIA_FLAG, skip_newlines= true )
2055- emit (ps, mark, word)
2056- return
2092+ return false
20572093 end
20582094 if ! is_anon_func
20592095 # Parse function argument list
20602096 # function f(x,y) end ==> (function (call f x y) (block))
20612097 # function f{T}() end ==> (function (call (curly f T)) (block))
20622098 # function A.f() end ==> (function (call (. A (quote f))) (block))
2063- parse_call_chain (ps, def_mark )
2099+ parse_call_chain (ps, mark )
20642100 if peek_behind (ps). kind != K " call"
20652101 # function f body end ==> (function (error f) (block body))
2066- emit (ps, def_mark , K " error" ,
2067- error= " Invalid signature in $(untokenize (word) ) definition" )
2102+ emit (ps, mark , K " error" ,
2103+ error= " Invalid signature in $(is_function ? " function " : " macro " ) definition" )
20682104 end
20692105 end
20702106 if is_function && peek (ps) == K " ::"
@@ -2073,21 +2109,16 @@ function parse_function(ps::ParseState)
20732109 # function f()::g(T) end ==> (function (:: (call f) (call g T)) (block))
20742110 bump (ps, TRIVIA_FLAG)
20752111 parse_call (ps)
2076- emit (ps, def_mark , K " ::" )
2112+ emit (ps, mark , K " ::" )
20772113 end
20782114 if peek (ps) == K " where"
20792115 # Function signature where syntax
20802116 # function f() where {T} end ==> (function (where (call f) T) (block))
20812117 # function f() where T end ==> (function (where (call f) T) (block))
2082- parse_where_chain (ps, def_mark )
2118+ parse_where_chain (ps, mark )
20832119 end
2084-
2085- # The function body
2086- # function f() \n a \n b end ==> (function (call f) (block a b))
2087- # function f() end ==> (function (call f) (block))
2088- parse_block (ps)
2089- bump_closing_token (ps, K " end" )
2090- emit (ps, mark, word)
2120+ # function f()::S where T end ==> (function (where (:: (call f) S) T) (block))
2121+ return true
20912122end
20922123
20932124# Parse a try block
0 commit comments