@@ -306,6 +306,22 @@ function is_valid_identifier(k)
306
306
! (is_syntactic_operator (k) || k in KSet " ? .'" )
307
307
end
308
308
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
+
309
325
# -------------------------------------------------------------------------------
310
326
# Parser
311
327
#
@@ -1786,7 +1802,26 @@ function parse_resword(ps::ParseState)
1786
1802
emit (ps, mark, K " error" , error= " expected assignment after `const`" )
1787
1803
end
1788
1804
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
1790
1825
elseif word == K " abstract"
1791
1826
# Abstract type definitions
1792
1827
# abstract type A end ==> (abstract A)
@@ -1968,23 +2003,17 @@ function parse_global_local_const_vars(ps)
1968
2003
end
1969
2004
1970
2005
# 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 )
1976
2007
is_anon_func = false
1977
- bump (ps, TRIVIA_FLAG)
1978
- bump_trivia (ps)
1979
2008
1980
- def_mark = position (ps)
2009
+ mark = position (ps)
1981
2010
if ! is_function
1982
2011
# Parse macro name
1983
2012
parse_identifier_or_interpolate (ps)
1984
2013
kb = peek_behind (ps). orig_kind
1985
2014
if is_initial_reserved_word (ps, kb)
1986
2015
# 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" )
1988
2017
else
1989
2018
# macro f() end ==> (macro (call f) (block))
1990
2019
# macro (:)(ex) end ==> (macro (call : ex) (block))
@@ -1997,6 +2026,7 @@ function parse_function(ps::ParseState)
1997
2026
# When an initial parenthesis is present, we might either have
1998
2027
# * the function name in parens, followed by (args...)
1999
2028
# * an anonymous function argument list in parens
2029
+ # * the whole function declaration in parens
2000
2030
#
2001
2031
# This should somewhat parse as in parse_paren() (this is what
2002
2032
# the flisp parser does), but that results in weird parsing of
@@ -2005,22 +2035,36 @@ function parse_function(ps::ParseState)
2005
2035
bump (ps, TRIVIA_FLAG)
2006
2036
is_empty_tuple = peek (ps, skip_newlines= true ) == K " )"
2007
2037
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
2009
2040
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)
2011
2043
end
2012
2044
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
2013
2056
if is_anon_func
2014
2057
# function (x) body end ==> (function (tuple x) (block body))
2058
+ # function (x::f()) end ==> (function (tuple (:: x (call f))) (block))
2015
2059
# function (x,y) end ==> (function (tuple x y) (block))
2016
2060
# function (x=1) end ==> (function (tuple (= x 1)) (block))
2017
2061
# function (;x=1) end ==> (function (tuple (parameters (= x 1))) (block))
2018
- emit (ps, def_mark , K " tuple" )
2062
+ emit (ps, mark , K " tuple" )
2019
2063
elseif is_empty_tuple
2020
2064
# Weird case which is consistent with parse_paren but will be
2021
2065
# rejected in lowering
2022
2066
# function ()(x) end ==> (function (call (tuple) x) (block))
2023
- emit (ps, def_mark , K " tuple" )
2067
+ emit (ps, mark , K " tuple" )
2024
2068
else
2025
2069
# function (:)() end ==> (function (call :) (block))
2026
2070
# function (x::T)() end ==> (function (call (:: x T)) (block))
@@ -2033,7 +2077,7 @@ function parse_function(ps::ParseState)
2033
2077
kb = peek_behind (ps). orig_kind
2034
2078
if is_reserved_word (kb)
2035
2079
# 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" )
2037
2081
else
2038
2082
# function f() end ==> (function (call f) (block))
2039
2083
# function type() end ==> (function (call type) (block))
@@ -2045,26 +2089,18 @@ function parse_function(ps::ParseState)
2045
2089
end
2046
2090
end
2047
2091
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
2057
2093
end
2058
2094
if ! is_anon_func
2059
2095
# Parse function argument list
2060
2096
# function f(x,y) end ==> (function (call f x y) (block))
2061
2097
# function f{T}() end ==> (function (call (curly f T)) (block))
2062
2098
# function A.f() end ==> (function (call (. A (quote f))) (block))
2063
- parse_call_chain (ps, def_mark )
2099
+ parse_call_chain (ps, mark )
2064
2100
if peek_behind (ps). kind != K " call"
2065
2101
# 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" )
2068
2104
end
2069
2105
end
2070
2106
if is_function && peek (ps) == K " ::"
@@ -2073,21 +2109,16 @@ function parse_function(ps::ParseState)
2073
2109
# function f()::g(T) end ==> (function (:: (call f) (call g T)) (block))
2074
2110
bump (ps, TRIVIA_FLAG)
2075
2111
parse_call (ps)
2076
- emit (ps, def_mark , K " ::" )
2112
+ emit (ps, mark , K " ::" )
2077
2113
end
2078
2114
if peek (ps) == K " where"
2079
2115
# Function signature where syntax
2080
2116
# function f() where {T} end ==> (function (where (call f) T) (block))
2081
2117
# function f() where T end ==> (function (where (call f) T) (block))
2082
- parse_where_chain (ps, def_mark )
2118
+ parse_where_chain (ps, mark )
2083
2119
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
2091
2122
end
2092
2123
2093
2124
# Parse a try block
0 commit comments