Skip to content

Commit b3a400f

Browse files
committedMar 11, 2025·
@Dissect: use "local" declaration to indicate a binding
1 parent 058012e commit b3a400f

File tree

6 files changed

+111
-106
lines changed

6 files changed

+111
-106
lines changed
 

‎src/dissect.jl

+18-13
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,24 @@ function dissect(@nospecialize(val), @nospecialize(pat))
1212
end
1313

1414
function dissect(scr::Symbol, @nospecialize(pat))
15-
if pat isa Symbol
16-
if pat === :_
17-
:(true)
18-
elseif pat === :nothing || pat === :missing
19-
:($scr === $pat)
20-
else
21-
:(local $pat = $scr; true)
22-
end
15+
if pat === :_
16+
:(true)
17+
elseif pat === :nothing || pat === :missing
18+
:($scr === $pat)
2319
elseif pat isa Bool
2420
:($scr === $pat)
2521
elseif pat isa QuoteNode && pat.value isa Symbol
2622
:($scr === $pat)
2723
elseif pat isa Expr
2824
nargs = length(pat.args)
29-
if pat.head === :(:=) && nargs == 2
30-
ex1 = dissect(scr, pat.args[1])
31-
ex2 = dissect(scr, pat.args[2])
25+
if pat.head === :local && nargs == 1 &&
26+
(local var = pat.args[1]) isa Symbol
27+
:(local $var = $scr; true)
28+
elseif pat.head === :local && nargs === 1 &&
29+
(local pat′ = pat.args[1]) isa Expr && pat′.head === :(=) &&
30+
length(pat′.args) == 2 && (local var = pat′.args[1]) isa Symbol
31+
ex1 = :(local $var = $scr; true)
32+
ex2 = dissect(scr, pat′.args[2])
3233
:($ex2 && $ex1)
3334
elseif pat.head === :(::) && nargs == 1
3435
:($scr isa $(pat.args[1]))
@@ -41,8 +42,10 @@ function dissect(scr::Symbol, @nospecialize(pat))
4142
elseif pat.head === :kw && nargs == 2
4243
dissect(:($scr.$(pat.args[1])), pat.args[2])
4344
elseif pat.head === :call && nargs >= 1 &&
44-
(local f = pat.args[1]; f isa Symbol)
45+
(local f = pat.args[1]) isa Symbol
4546
dissect(scr, getfield(FunSQL, f), pat.args[2:end])
47+
elseif pat.head === :($) && nargs == 1
48+
:(isequal($scr, $(pat.args[1])))
4649
else
4750
error("invalid pattern: $(repr(pat))")
4851
end
@@ -114,7 +117,9 @@ end
114117

115118
function dissect(scr::Symbol, ::Type{GlobalRef}, pats::Vector{Any})
116119
if length(pats) == 2
117-
return :($scr isa GlobalRef && $scr.mod == $(pats[1]) && $scr.name === $(pats[2]))
120+
ex1 = dissect(:($scr.mod), pats[1])
121+
ex2 = dissect(:($scr.name), pats[2])
122+
return :($scr isa GlobalRef && $ex1 && $ex2)
118123
end
119124
error("invalid pattern: $(repr(pats))")
120125
end

‎src/link.jl

+11-11
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ struct LinkContext
2323
end
2424

2525
function link(n::SQLNode)
26-
@dissect(n, WithContext(over = over, catalog = catalog)) || throw(ILLFormedError())
26+
@dissect(n, WithContext(over = (local over), catalog = (local catalog))) || throw(ILLFormedError())
2727
ctx = LinkContext(catalog)
2828
t = row_type(over)
2929
refs = SQLNode[]
@@ -221,7 +221,7 @@ end
221221
function link(n::AsNode, ctx)
222222
refs = SQLNode[]
223223
for ref in ctx.refs
224-
if @dissect(ref, over |> Nested(name = name))
224+
if @dissect(ref, (local over) |> Nested(name = (local name)))
225225
@assert name == n.name
226226
push!(refs, over)
227227
else
@@ -241,7 +241,7 @@ function link(n::DefineNode, ctx)
241241
refs = SQLNode[]
242242
seen = Set{Symbol}()
243243
for ref in ctx.refs
244-
if @dissect(ref, nothing |> Get(name = name)) && name in keys(n.label_map)
244+
if @dissect(ref, nothing |> Get(name = (local name))) && name in keys(n.label_map)
245245
push!(seen, name)
246246
else
247247
push!(refs, ref)
@@ -300,13 +300,13 @@ function link(n::GroupNode, ctx)
300300
if has_aggregates
301301
ctx′ = LinkContext(ctx, refs = refs)
302302
for ref in ctx.refs
303-
if (@dissect(ref, nothing |> Agg(args = args, filter = filter) |> Nested(name = name)) && name === n.name) ||
304-
(@dissect(ref, nothing |> Agg(args = args, filter = filter)) && n.name === nothing)
303+
if (@dissect(ref, nothing |> Agg(args = (local args), filter = (local filter)) |> Nested(name = (local name))) && name === n.name) ||
304+
(@dissect(ref, nothing |> Agg(args = (local args), filter = (local filter))) && n.name === nothing)
305305
gather!(args, ctx′)
306306
if filter !== nothing
307307
gather!(filter, ctx′)
308308
end
309-
elseif @dissect(ref, nothing |> Get(name = name)) && name in keys(n.label_map)
309+
elseif @dissect(ref, nothing |> Get(name = (local name))) && name in keys(n.label_map)
310310
# Force evaluation in a nested subquery.
311311
push!(refs, n.by[n.label_map[name]])
312312
end
@@ -352,13 +352,13 @@ function link(n::IterateNode, ctx)
352352
end
353353

354354
function route(r::JoinRouter, ref::SQLNode)
355-
if @dissect(ref, over |> Nested(name = name)) && name in r.label_set
355+
if @dissect(ref, (local over) |> Nested(name = (local name))) && name in r.label_set
356356
return 1
357357
end
358-
if @dissect(ref, Get(name = name)) && name in r.label_set
358+
if @dissect(ref, Get(name = (local name))) && name in r.label_set
359359
return 1
360360
end
361-
if @dissect(ref, over |> Agg()) && r.group
361+
if @dissect(ref, (local over) |> Agg()) && r.group
362362
return 1
363363
end
364364
return -1
@@ -424,8 +424,8 @@ function link(n::PartitionNode, ctx)
424424
ctx′ = LinkContext(ctx, refs = imm_refs)
425425
has_aggregates = false
426426
for ref in ctx.refs
427-
if (@dissect(ref, nothing |> Agg(args = args, filter = filter) |> Nested(name = name)) && name === n.name) ||
428-
(@dissect(ref, nothing |> Agg(args = args, filter = filter)) && n.name === nothing)
427+
if (@dissect(ref, nothing |> Agg(args = (local args), filter = (local filter)) |> Nested(name = (local name))) && name === n.name) ||
428+
(@dissect(ref, nothing |> Agg(args = (local args), filter = (local filter))) && n.name === nothing)
429429
gather!(args, ctx′)
430430
if filter !== nothing
431431
gather!(filter, ctx′)

‎src/nodes.jl

+34-34
Original file line numberDiff line numberDiff line change
@@ -506,133 +506,133 @@ function transliterate(@nospecialize(ex), ctx::TransliterateContext)
506506
else
507507
return QuoteNode(ex)
508508
end
509-
elseif @dissect(ex, QuoteNode(name::Symbol))
509+
elseif @dissect(ex, QuoteNode((local name)::Symbol))
510510
# :name
511511
return :(Var($ex))
512512
elseif ex isa Expr
513-
if @dissect(ex, Expr(:($), arg))
513+
if @dissect(ex, Expr(:($), (local arg)))
514514
# $(...)
515515
return esc(arg)
516-
elseif @dissect(ex, Expr(:macrocall, ref := GlobalRef(Core, Symbol("@doc")), ln::LineNumberNode, doc, arg))
516+
elseif @dissect(ex, Expr(:macrocall, (local ref = GlobalRef($Core, $(Symbol("@doc")))), (local ln)::LineNumberNode, (local doc), (local arg)))
517517
# "..." ...
518-
if @dissect(arg, name::Symbol || Expr(:macrocall, GlobalRef(Core, Symbol("@cmd")), ::LineNumberNode, name::String))
518+
if @dissect(arg, (local name)::Symbol || Expr(:macrocall, GlobalRef($Core, $(Symbol("@cmd"))), ::LineNumberNode, (local name)::String))
519519
arg = Symbol("funsql_$name")
520520
else
521521
ctx = TransliterateContext(ctx, src = ln)
522522
arg = transliterate(arg, ctx)
523523
end
524524
return Expr(:macrocall, ref, ln, doc, arg)
525-
elseif @dissect(ex, Expr(:(=), Expr(:call, name::Symbol || Expr(:macrocall, GlobalRef(Core, Symbol("@cmd")), ::LineNumberNode, name::String), args...), body))
525+
elseif @dissect(ex, Expr(:(=), Expr(:call, (local name)::Symbol || Expr(:macrocall, GlobalRef($Core, $(Symbol("@cmd"))), ::LineNumberNode, (local name)::String), (local args)...), (local body)))
526526
# name(args...) = body
527527
ctx = TransliterateContext(ctx, decl = true)
528528
trs = Any[transliterate(arg, ctx) for arg in args]
529529
ctx = TransliterateContext(ctx, decl = false)
530530
return Expr(:(=),
531531
:($(esc(Symbol("funsql_$name")))($(trs...))),
532532
transliterate(body, ctx))
533-
elseif @dissect(ex, Expr(:(=), name::Symbol, arg))
533+
elseif @dissect(ex, Expr(:(=), (local name)::Symbol, (local arg)))
534534
# name = arg
535535
return Expr(:(=), esc(name), transliterate(arg, ctx))
536536
elseif ctx.decl && @dissect(ex, Expr(:(::), _::Symbol, _))
537537
# name::t
538538
return esc(ex)
539-
elseif @dissect(ex, Expr(:kw, key, arg))
539+
elseif @dissect(ex, Expr(:kw, (local key), (local arg)))
540540
# key = arg
541541
ctx = TransliterateContext(ctx, decl = true)
542542
ctx′ = TransliterateContext(ctx, decl = false)
543543
return Expr(:kw, transliterate(key, ctx), transliterate(arg, ctx′))
544-
elseif @dissect(ex, Expr(:(...), arg))
544+
elseif @dissect(ex, Expr(:(...), (local arg)))
545545
# arg...
546546
return Expr(:(...), transliterate(arg, ctx))
547-
elseif @dissect(ex, Expr(:parameters, args...))
547+
elseif @dissect(ex, Expr(:parameters, (local args)...))
548548
# ; args...
549549
return Expr(:parameters, Any[transliterate(arg, ctx) for arg in args]...)
550-
elseif @dissect(ex, Expr(:macrocall, GlobalRef(Core, Symbol("@cmd")), ::LineNumberNode, name::String))
550+
elseif @dissect(ex, Expr(:macrocall, GlobalRef($Core, $(Symbol("@cmd"))), ::LineNumberNode, (local name)::String))
551551
# `name`
552552
return QuoteNode(Symbol(name))
553-
elseif @dissect(ex, Expr(:call, Expr(:., over, QuoteNode(name)), args...))
553+
elseif @dissect(ex, Expr(:call, Expr(:., (local over), QuoteNode(local name)), (local args)...))
554554
# over.name(args...)
555555
tr1 = transliterate(over, ctx)
556556
tr2 = transliterate(Expr(:call, name, args...), ctx)
557557
return :(Chain($tr1, $tr2))
558-
elseif @dissect(ex, Expr(:macrocall, Expr(:., over, Expr(:quote, ex′)), args...))
558+
elseif @dissect(ex, Expr(:macrocall, Expr(:., (local over), Expr(:quote, (local ex′))), (local args)...))
559559
# over.`name`
560560
tr1 = transliterate(over, ctx)
561561
tr2 = transliterate(Expr(:macrocall, ex′, args...), ctx)
562562
return :(Chain($tr1, $tr2))
563-
elseif @dissect(ex, Expr(:., over, Expr(:quote, arg)))
563+
elseif @dissect(ex, Expr(:., (local over), Expr(:quote, (local arg))))
564564
# over.`name` (Julia ≥ 1.10)
565565
tr1 = transliterate(over, ctx)
566566
tr2 = transliterate(arg, ctx)
567567
return :(Chain($tr1, $tr2))
568-
elseif @dissect(ex, Expr(:call, Expr(:macrocall, Expr(:., over, Expr(:quote, ex′)), args...), args′...))
568+
elseif @dissect(ex, Expr(:call, Expr(:macrocall, Expr(:., (local over), Expr(:quote, (local ex′))), (local args)...), (local args′)...))
569569
# over.`name`(args...)
570570
tr1 = transliterate(over, ctx)
571571
tr2 = transliterate(Expr(:call, Expr(:macrocall, ex′, args...), args′...), ctx)
572572
return :(Chain($tr1, $tr2))
573-
elseif @dissect(ex, Expr(:call, Expr(:., over, Expr(:quote, arg)), args...))
573+
elseif @dissect(ex, Expr(:call, Expr(:., (local over), Expr(:quote, (local arg))), (local args)...))
574574
# over.`name`(args...) (Julia ≥ 1.10)
575575
tr1 = transliterate(over, ctx)
576576
tr2 = transliterate(Expr(:call, arg, args...), ctx)
577577
return :(Chain($tr1, $tr2))
578-
elseif @dissect(ex, Expr(:., over, QuoteNode(name)))
578+
elseif @dissect(ex, Expr(:., (local over), QuoteNode((local name))))
579579
# over.name
580580
tr1 = transliterate(over, ctx)
581581
tr2 = transliterate(name, ctx)
582582
return :(Chain($tr1, $tr2))
583-
elseif @dissect(ex, Expr(:call, :(=>), name := QuoteNode(_::Symbol), arg))
583+
elseif @dissect(ex, Expr(:call, :(=>), (local name = QuoteNode(_::Symbol)), (local arg)))
584584
# :name => arg
585585
tr = transliterate(arg, ctx)
586586
return :($name => $tr)
587-
elseif @dissect(ex, Expr(:call, :(=>), name, arg))
587+
elseif @dissect(ex, Expr(:call, :(=>), (local name), (local arg)))
588588
# name => arg
589589
tr1 = transliterate(name, ctx)
590590
tr2 = transliterate(arg, ctx)
591591
return :($tr1 => $tr2)
592-
elseif @dissect(ex, Expr(:call, :(:), arg1, arg2))
592+
elseif @dissect(ex, Expr(:call, :(:), (local arg1), (local arg2)))
593593
tr1 = transliterate(arg1, ctx)
594594
tr2 = transliterate(arg2, ctx)
595595
return :($tr1:$tr2)
596-
elseif @dissect(ex, Expr(:vect, args...))
596+
elseif @dissect(ex, Expr(:vect, (local args)...))
597597
# [args...]
598598
return Expr(:vect, Any[transliterate(arg, ctx) for arg in args]...)
599-
elseif @dissect(ex, Expr(:tuple, args...))
599+
elseif @dissect(ex, Expr(:tuple, (local args)...))
600600
# (args...)
601601
return Expr(:tuple, Any[transliterate(arg, ctx) for arg in args]...)
602-
elseif @dissect(ex, Expr(:comparison, arg1, arg2::Symbol, arg3))
602+
elseif @dissect(ex, Expr(:comparison, (local arg1), (local arg2)::Symbol, (local arg3)))
603603
# Chained comparison.
604604
tr1 = transliterate(arg1, ctx)
605605
tr2 = transliterate(arg3, ctx)
606606
return :($(esc(Symbol("funsql_$arg2")))($tr1, $tr2))
607-
elseif @dissect(ex, Expr(:comparison, arg1, arg2::Symbol, arg3, args...))
607+
elseif @dissect(ex, Expr(:comparison, (local arg1), (local arg2)::Symbol, (local arg3), (local args)...))
608608
# Chained comparison.
609609
tr1 = transliterate(arg1, ctx)
610610
tr2 = transliterate(arg3, ctx)
611611
tr3 = transliterate(Expr(:comparison, arg3, args...), ctx)
612612
return :(Fun(:and, $(esc(Symbol("funsql_$arg2")))($tr1, $tr2), $tr3))
613-
elseif @dissect(ex, Expr(:(&&), args...))
613+
elseif @dissect(ex, Expr(:(&&), (local args)...))
614614
# &&(args...)
615615
trs = Any[transliterate(arg, ctx) for arg in args]
616616
return :(Fun(:and, args = [$(trs...)]))
617-
elseif @dissect(ex, Expr(:(||), args...))
617+
elseif @dissect(ex, Expr(:(||), (local args)...))
618618
# ||(args...)
619619
trs = Any[transliterate(arg, ctx) for arg in args]
620620
return :(Fun(:or, args = [$(trs...)]))
621-
elseif @dissect(ex, Expr(:call, op := :+ || :-, arg := :Inf))
621+
elseif @dissect(ex, Expr(:call, (local op = :+ || :-), (local arg = :Inf)))
622622
# ±Inf
623623
tr = transliterate(arg, ctx)
624624
return Expr(:call, op, tr)
625-
elseif @dissect(ex, Expr(:call, name::Symbol, args...))
625+
elseif @dissect(ex, Expr(:call, (local name)::Symbol, (local args)...))
626626
# name(args...)
627627
trs = Any[transliterate(arg, ctx) for arg in args]
628628
return :($(esc(Symbol("funsql_$name")))($(trs...)))
629-
elseif @dissect(ex, Expr(:call, Expr(:macrocall, GlobalRef(Core, Symbol("@cmd")), ::LineNumberNode, name::String), args...))
629+
elseif @dissect(ex, Expr(:call, Expr(:macrocall, GlobalRef($Core, $(Symbol("@cmd"))), ::LineNumberNode, (local name)::String), (local args)...))
630630
# `name`(args...)
631631
trs = Any[transliterate(arg, ctx) for arg in args]
632632
return :($(esc(Symbol("funsql_$name")))($(trs...)))
633-
elseif @dissect(ex, Expr(:block, args...))
633+
elseif @dissect(ex, Expr(:block, (local args)...))
634634
# begin; args...; end
635-
if all(@dissect(arg, ::LineNumberNode || Expr(:(=), _...) || Expr(:macrocall, GlobalRef(Core, Symbol("@doc")), _...))
635+
if all(@dissect(arg, ::LineNumberNode || Expr(:(=), _...) || Expr(:macrocall, GlobalRef($Core, $(Symbol("@doc"))), _...))
636636
for arg in args)
637637
trs = Any[]
638638
for arg in args
@@ -656,20 +656,20 @@ function transliterate(@nospecialize(ex), ctx::TransliterateContext)
656656
end
657657
return tr
658658
end
659-
elseif @dissect(ex, Expr(:if, arg1, arg2))
659+
elseif @dissect(ex, Expr(:if, (local arg1), (local arg2)))
660660
tr1 = transliterate(arg1, ctx)
661661
tr2 = transliterate(arg2, ctx)
662662
return :(Fun(:case, $tr1, $tr2))
663-
elseif @dissect(ex, Expr(:if, arg1, arg2, arg3))
663+
elseif @dissect(ex, Expr(:if, (local arg1), (local arg2), (local arg3)))
664664
trs = Any[transliterate(arg1, ctx),
665665
transliterate(arg2, ctx)]
666-
while @dissect(arg3, Expr(:if || :elseif, arg1′, arg2′, arg3′))
666+
while @dissect(arg3, Expr(:if || :elseif, (local arg1′), (local arg2′), (local arg3′)))
667667
push!(trs,
668668
transliterate(arg1′, ctx),
669669
transliterate(arg2′, ctx))
670670
arg3 = arg3′
671671
end
672-
if @dissect(arg3, Expr(:if || :elseif, arg1′, arg2′))
672+
if @dissect(arg3, Expr(:if || :elseif, (local arg1′), (local arg2′)))
673673
push!(trs,
674674
transliterate(arg1′, ctx),
675675
transliterate(arg2′, ctx))

‎src/resolve.jl

+5-5
Original file line numberDiff line numberDiff line change
@@ -38,22 +38,22 @@ get_path(ctx::ResolveContext) =
3838
copy(ctx.path)
3939

4040
function row_type(n::SQLNode)
41-
@dissect(n, Resolved(type = type::RowType)) || throw(IllFormedError())
41+
@dissect(n, Resolved(type = (local type)::RowType)) || throw(IllFormedError())
4242
type
4343
end
4444

4545
function scalar_type(n::SQLNode)
46-
@dissect(n, Resolved(type = type::ScalarType)) || throw(IllFormedError())
46+
@dissect(n, Resolved(type = (local type)::ScalarType)) || throw(IllFormedError())
4747
type
4848
end
4949

5050
function type(n::SQLNode)
51-
@dissect(n, Resolved(type = t)) || throw(IllFormedError())
51+
@dissect(n, Resolved(type = (local t))) || throw(IllFormedError())
5252
t
5353
end
5454

5555
function resolve(n::SQLNode)
56-
@dissect(n, WithContext(over = n′, catalog = catalog)) || throw(IllFormedError())
56+
@dissect(n, WithContext(over = (local n′), catalog = (local catalog))) || throw(IllFormedError())
5757
ctx = ResolveContext(catalog)
5858
WithContext(over = resolve(n′, ctx), catalog = catalog)
5959
end
@@ -107,7 +107,7 @@ function resolve_scalar(n::TabularNode, ctx)
107107
end
108108

109109
function unnest(node, base, ctx)
110-
while @dissect(node, over |> Get(name = name))
110+
while @dissect(node, (local over) |> Get(name = (local name)))
111111
base = Nested(over = base, name = name)
112112
node = over
113113
end

0 commit comments

Comments
 (0)
Please sign in to comment.