Skip to content

Commit 0e3cbcb

Browse files
authored
Merge pull request #11 from JuliaDebug/teh/define_name
Allow `define=true` to be used to define generated/kwarg methods
2 parents 1da3988 + a1b4c2b commit 0e3cbcb

File tree

2 files changed

+63
-27
lines changed

2 files changed

+63
-27
lines changed

src/LoweredCodeUtils.jl

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -131,10 +131,14 @@ In this case, `lastpc == pc`.
131131
If no 3-argument `:method` expression is found, `sigt` will be `nothing`.
132132
"""
133133
function signature(@nospecialize(recurse), frame::Frame, @nospecialize(stmt), pc)
134+
mod = moduleof(frame)
134135
lastpc = frame.pc = pc
135136
while !isexpr(stmt, :method, 3) # wait for the 3-arg version
136137
if isexpr(stmt, :thunk) && isanonymous_typedef(stmt.args[1])
137138
lastpc = pc = define_anonymous(recurse, frame, stmt)
139+
elseif isexpr(stmt, :call) && JuliaInterpreter.is_quotenode(stmt.args[1], Core.Typeof) &&
140+
(sym = stmt.args[2]; isa(sym, Symbol) && !isdefined(mod, sym))
141+
return nothing, pc
138142
else
139143
lastpc = pc
140144
pc = step_expr!(recurse, frame, stmt, true)
@@ -278,37 +282,37 @@ function correct_name!(@nospecialize(recurse), frame, pc, name, parentname)
278282
nameinfo = find_corrected_name(frame, pc, name, parentname)
279283
if nameinfo === nothing
280284
pc = skip_until(stmt->isexpr(stmt, :method, 3), frame, pc)
281-
lastidx = pc
282285
pc = next_or_nothing(frame, pc)
286+
return name, pc
287+
end
288+
pctop, isgen = nameinfo
289+
sigtparent, lastpcparent = signature(recurse, frame, pctop)
290+
sigtparent === nothing && return name, pc
291+
methparent = whichtt(sigtparent)
292+
methparent === nothing && return name, pc # caller isn't defined, no correction is needed
293+
if isgen
294+
cname = nameof(methparent.generator.gen)
283295
else
284-
pctop, isgen = nameinfo
285-
sigtparent, lastpcparent = signature(recurse, frame, pctop)
286-
methparent = whichtt(sigtparent)
287-
methparent === nothing && return name, pc # caller isn't defined, no correction is needed
288-
if isgen
289-
cname = nameof(methparent.generator.gen)
290-
else
291-
bodyparent = Base.uncompressed_ast(methparent)
292-
bodystmt = bodyparent.code[end-1]
293-
@assert isexpr(bodystmt, :call)
294-
ref = getcallee(bodystmt)
295-
isa(ref, GlobalRef) || @show ref typeof(ref)
296-
@assert isa(ref, GlobalRef)
297-
@assert ref.mod == moduleof(frame)
298-
cname = ref.name
299-
end
300-
# Swap in the correct name
301-
if name != cname
302-
replacename!(frame.framecode.src.code, name=>cname)
303-
end
296+
bodyparent = Base.uncompressed_ast(methparent)
297+
bodystmt = bodyparent.code[end-1]
298+
@assert isexpr(bodystmt, :call)
299+
ref = getcallee(bodystmt)
300+
isa(ref, GlobalRef) || @show ref typeof(ref)
301+
@assert isa(ref, GlobalRef)
302+
@assert ref.mod == moduleof(frame)
303+
cname = ref.name
304+
end
305+
# Swap in the correct name
306+
if name != cname
307+
replacename!(frame.framecode.src.code, name=>cname)
308+
end
309+
stmt = pc_expr(frame, lastpcparent)
310+
while !ismethod(stmt)
311+
lastpcparent = next_or_nothing(frame, lastpcparent)
312+
lastpcparent === nothing && return name, lastpcparent
304313
stmt = pc_expr(frame, lastpcparent)
305-
while !ismethod(stmt)
306-
lastpcparent = next_or_nothing(frame, lastpcparent)
307-
lastpcparent === nothing && return name, lastpcparent
308-
stmt = pc_expr(frame, lastpcparent)
309-
end
310-
name = stmt.args[1]
311314
end
315+
name = stmt.args[1]
312316
return name, pc
313317
end
314318

@@ -345,7 +349,15 @@ function methoddef!(@nospecialize(recurse), signatures, frame::Frame, @nospecial
345349
if ismethod3(stmt)
346350
pc3 = pc
347351
sigt, pc = signature(recurse, frame, stmt, pc)
352+
if sigt === nothing && define
353+
step_expr!(recurse, frame, stmt, true)
354+
end
355+
sigt, pc = signature(recurse, frame, stmt, pc)
348356
meth = whichtt(sigt)
357+
if meth === nothing && define
358+
step_expr!(recurse, frame, stmt, true)
359+
meth = whichtt(sigt)
360+
end
349361
if isa(meth, Method)
350362
push!(signatures, meth.sig)
351363
elseif stmt.args[1] == false

test/runtests.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,30 @@ bodymethtest5(x, y=Dict(1=>2)) = 5
180180
methoddefs!(signatures, frame; define=true)
181181
@test Lowering.fdefine(0) == 1
182182

183+
# define with correct_name!
184+
ex = quote
185+
@generated function generated1(A::AbstractArray{T,N}, val) where {T,N}
186+
ex = Expr(:tuple)
187+
for i = 1:N
188+
push!(ex.args, :val)
189+
end
190+
return ex
191+
end
192+
end
193+
frame = JuliaInterpreter.prepare_thunk(Lowering, ex)
194+
empty!(signatures)
195+
methoddefs!(signatures, frame; define=true)
196+
@test length(signatures) == 2
197+
@test Lowering.generated1(rand(2,2), 3.2) == (3.2, 3.2)
198+
ex = quote
199+
another_kwdef(x, y=1; z="hello") = 333
200+
end
201+
frame = JuliaInterpreter.prepare_thunk(Lowering, ex)
202+
empty!(signatures)
203+
methoddefs!(signatures, frame; define=true)
204+
@test length(signatures) == 5
205+
@test Lowering.another_kwdef(0) == 333
206+
183207
# Test for correct exit (example from base/namedtuples.jl)
184208
ex = quote
185209
function merge(a::NamedTuple{an}, b::NamedTuple{bn}) where {an, bn}

0 commit comments

Comments
 (0)