Skip to content

Commit 2fe6b31

Browse files
committed
Make standalone prefix /> work. Improved lowering.
1 parent ed04c29 commit 2fe6b31

File tree

2 files changed

+67
-17
lines changed

2 files changed

+67
-17
lines changed

src/expr.jl

+59-10
Original file line numberDiff line numberDiff line change
@@ -303,25 +303,74 @@ function _to_expr(node::SyntaxNode; iteration_spec=false, need_linenodes=true,
303303
args[1] = Expr(headsym, args[1].args...)
304304
headsym = :const
305305
end
306-
elseif headsym == Symbol("/>")
306+
elseif headsym == Symbol("/>") || headsym == Symbol("\\>")
307307
freearg = gensym()
308-
cargs = [args[1], freearg, args[2:end]...]
309-
reorder_parameters!(cargs, 2)
310-
return Expr(:->, freearg, Expr(:call, cargs...))
311-
elseif headsym == Symbol("\\>")
312-
freearg = gensym()
313-
cargs = [args[1], args[2:end]..., freearg]
314-
reorder_parameters!(cargs, 2)
315-
return Expr(:->, freearg, Expr(:call, cargs...))
308+
callex = only(args)
309+
@assert Meta.isexpr(callex, :call)
310+
args = callex.args
311+
func = headsym == Symbol("/>") ?
312+
:(JuliaSyntax.fixbutfirst) :
313+
:(JuliaSyntax.fixbutlast)
314+
if length(args) >= 2 && Meta.isexpr(args[2], :parameters)
315+
return Expr(:call, func, args[2], args[1], args[3:end]...)
316+
else
317+
return Expr(:call, func, args...)
318+
end
316319
elseif headsym == :chain
317-
return Expr(:call, :(JuliaSyntax.chain), args...)
320+
if kind(node_args[1]) in KSet"/> \>"
321+
return Expr(:call, :(JuliaSyntax.compose_chain), args...)
322+
else
323+
return Expr(:call, :(JuliaSyntax.chain), args...)
324+
end
318325
end
319326
return Expr(headsym, args...)
320327
end
321328

329+
#-------------------------------------------------------------------------------
330+
# Targets for lowering /> and \> syntax
331+
332+
# For use with />
333+
struct FixButFirst{F,Args,Kws}
334+
f::F
335+
args::Args
336+
kwargs::Kws
337+
end
338+
339+
(f::FixButFirst)(x) = f.f(x, f.args...; f.kwargs...)
340+
341+
"""
342+
Fix all arguments except for the first
343+
"""
344+
fixbutfirst(f, args...; kws...) = FixButFirst(f, args, kws)
345+
346+
# For use with \>
347+
struct FixButLast{F,Args,Kws}
348+
f::F
349+
args::Args
350+
kwargs::Kws
351+
end
352+
353+
(f::FixButLast)(x) = f.f(f.args..., x; f.kwargs...)
354+
355+
"""
356+
Fix all arguments except for the last
357+
"""
358+
fixbutlast(f, args...; kws...) = FixButLast(f, args, kws)
359+
322360
chain(x, f, fs...) = chain(f(x), fs...)
323361
chain(x) = x
324362

363+
struct ComposeChain{Funcs}
364+
fs::Funcs
365+
end
366+
367+
(f::ComposeChain)(x) = chain(x, f.fs...)
368+
369+
compose_chain(fs...) = ComposeChain(fs)
370+
371+
372+
#-------------------------------------------------------------------------------
373+
325374
Base.Expr(node::SyntaxNode) = _to_expr(node)
326375

327376
function build_tree(::Type{Expr}, stream::ParseStream; kws...)

src/parser.jl

+8-7
Original file line numberDiff line numberDiff line change
@@ -800,20 +800,21 @@ end
800800
# x /> A.f(y) ==> (chain x (/> (. A (quote f)) y))
801801
function parse_curry_chain(ps::ParseState)
802802
mark = position(ps)
803-
parse_range(ps)
804-
has_chain = false
803+
if (k = peek(ps); k != K"/>" && k != K"\>")
804+
parse_range(ps)
805+
end
806+
chain_len = 0
805807
while (k = peek(ps); k == K"/>" || k == K"\>")
806808
bump(ps, TRIVIA_FLAG)
807809
m = position(ps)
808810
parse_range(ps)
809-
if peek_behind(ps).kind == K"call"
810-
has_chain = true
811-
reset_node!(ps, position(ps), kind=k)
812-
else
811+
if peek_behind(ps).kind != K"call"
813812
emit(ps, m, K"error", error="Expected call to the right of />")
814813
end
814+
emit(ps, m, k)
815+
chain_len += 1
815816
end
816-
if has_chain
817+
if chain_len > 1
817818
emit(ps, mark, K"chain")
818819
end
819820
end

0 commit comments

Comments
 (0)