From e0a730695706696380b7f6413bb7b3048c7477ba Mon Sep 17 00:00:00 2001 From: c42f Date: Fri, 17 Feb 2023 10:01:52 +1000 Subject: [PATCH 1/2] Prototype: Underscores and prefix anonymous function syntax As discussed in https://github.com/JuliaLang/julia/issues/38713 --- src/expr.jl | 35 +++++++++++++++++++++++++++++++---- src/parser.jl | 9 ++++++--- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/expr.jl b/src/expr.jl index 61ec2e75..84503134 100644 --- a/src/expr.jl +++ b/src/expr.jl @@ -30,6 +30,27 @@ function reorder_parameters!(args, params_pos) insert!(args, params_pos, pop!(args)) end +function lower_underscores!(anon_args, args, argrange=1:length(args)) + for i in argrange + a = args[i] + if a == :_ + g = gensym() + push!(anon_args, g) + args[i] = g + elseif a isa Expr + if Meta.isexpr(a, :call) && length(a.args) > 2 && + Meta.isexpr(a.args[2], :parameters) + lower_underscores!(anon_args, a.args, 1:1) + lower_underscores!(anon_args, a.args, 3:length(a.args)) + lower_underscores!(anon_args, a.args, 2:2) + else + # FIXME: Other out-of-source-order Exprs + lower_underscores!(anon_args, a.args) + end + end + end +end + function _to_expr(node::SyntaxNode; iteration_spec=false, need_linenodes=true, eq_to_kw=false, map_kw_in_params=false) if !haschildren(node) @@ -250,11 +271,17 @@ function _to_expr(node::SyntaxNode; iteration_spec=false, need_linenodes=true, # Block for conditional's source location args[1] = Expr(:block, loc, args[1]) elseif headsym === :(->) - if Meta.isexpr(args[2], :block) - pushfirst!(args[2].args, loc) + if is_prefix_op_call(node) + anon_args = Symbol[] + lower_underscores!(anon_args, args) + pushfirst!(args, Expr(:tuple, anon_args...)) else - # Add block for source locations - args[2] = Expr(:block, loc, args[2]) + if Meta.isexpr(args[2], :block) + pushfirst!(args[2].args, loc) + else + # Add block for source locations + args[2] = Expr(:block, loc, args[2]) + end end elseif headsym === :function if length(args) > 1 diff --git a/src/parser.jl b/src/parser.jl index 6318054a..6d302455 100644 --- a/src/parser.jl +++ b/src/parser.jl @@ -276,7 +276,7 @@ function is_syntactic_operator(k) end function is_syntactic_unary_op(k) - kind(k) in KSet"$ & ::" + kind(k) in KSet"$ & :: ->" end function is_type_operator(t) @@ -1417,6 +1417,7 @@ end # &a ==> (& a) # ::a ==> (::-pre a) # $a ==> ($ a) +# ->a ==> (-> a) # # flisp: parse-unary-prefix function parse_unary_prefix(ps::ParseState) @@ -1434,14 +1435,16 @@ function parse_unary_prefix(ps::ParseState) if k in KSet"& ::" # &a ==> (& a) parse_where(ps, parse_call) + elseif k == K"->" + # -> binds loosely on the right + parse_eq_star(ps) else # $a ==> ($ a) # $$a ==> ($ ($ a)) # $&a ==> ($ (& a)) parse_unary_prefix(ps) end - # Only need PREFIX_OP_FLAG for :: - f = k == K"::" ? PREFIX_OP_FLAG : EMPTY_FLAGS + f = (k == K"::" || k == K"->") ? PREFIX_OP_FLAG : EMPTY_FLAGS emit(ps, mark, k, f) end else From c4e0ef59b77648fc3387da7d7fc1d3065b53769b Mon Sep 17 00:00:00 2001 From: c42f Date: Sat, 18 Feb 2023 14:03:03 +1000 Subject: [PATCH 2/2] Make _ always refer to the same (single) argument --- src/expr.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/expr.jl b/src/expr.jl index 84503134..30cc3b9c 100644 --- a/src/expr.jl +++ b/src/expr.jl @@ -34,8 +34,12 @@ function lower_underscores!(anon_args, args, argrange=1:length(args)) for i in argrange a = args[i] if a == :_ - g = gensym() - push!(anon_args, g) + if isempty(anon_args) + g = gensym() + push!(anon_args, g) + else + g = anon_args[1] + end args[i] = g elseif a isa Expr if Meta.isexpr(a, :call) && length(a.args) > 2 &&