Skip to content

Commit 4f65817

Browse files
committed
Add StackedMethodTable
1 parent 02f1270 commit 4f65817

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

src/jlgen.jl

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,57 @@ end # !HAS_INTEGRATED_CACHE
297297

298298
Base.Experimental.@MethodTable(GLOBAL_METHOD_TABLE)
299299

300+
# Implements a priority lookup for method tables, where the first match in the stack get's returned.
301+
# An alternative to this would be to use a "Union" where we would query the parent method table and
302+
# do a most-specific match.
303+
struct StackedMethodTable{MTV<:CC.MethodTableView} <: CC.MethodTableView
304+
world::UInt
305+
mt::Core.MethodTable
306+
parent::MTV
307+
end
308+
StackedMethodTable(world::UInt, mt::Core.MethodTable) = StackedMethodTable(world, mt, CC.InternalMethodTable(world))
309+
StackedMethodTable(world::UInt, mt::Core.MethodTable, parent::Core.MethodTable) = StackedMethodTable(world, mt, StackedMethodTable(world, parent))
310+
311+
function findall(@nospecialize(sig::Type), table::StackedMethodTable; limit::Int=-1)
312+
result = CC._findall(sig, table.mt, table.world, limit)
313+
result === nothing && return nothing # to many matches
314+
nr = CC.length(result)
315+
if nr 1 && CC.getindex(result, nr).fully_covers
316+
# no need to fall back to the parent method view
317+
return CC.MethodMatchResult(result, true)
318+
end
319+
320+
parent_result = CC.findall(sig, table.parent; limit)::Union{Nothing, CC.MethodMatchResult}
321+
parent_result === nothing && return nothing #too many matches
322+
323+
overlayed = parent_result.overlayed | !CC.isempty(result)
324+
parent_result = parent_result.matches::CC.MethodLookupResult
325+
326+
# merge the parent match results with the internal method table
327+
return CC.MethodMatchResult(
328+
CC.MethodLookupResult(
329+
CC.vcat(result.matches, parent_result.matches),
330+
CC.WorldRange(
331+
CC.max(result.valid_worlds.min_world, parent_result.valid_worlds.min_world),
332+
CC.min(result.valid_worlds.max_world, parent_result.valid_worlds.max_world)),
333+
result.ambig | parent_result.ambig),
334+
overlayed)
335+
end
336+
337+
CC.isoverlayed(::StackedMethodTable) = true
338+
339+
function CC.findsup(@nospecialize(sig::Type), table::StackedMethodTable)
340+
match, valid_worlds = CC._findsup(sig, table.mt, table.world)
341+
match !== nothing && return match, valid_worlds, true
342+
# look up in parent
343+
parent_match, parent_valid_worlds, overlayed = CC.findsup(sig, table.parent)
344+
return (
345+
parent_match,
346+
CC.WorldRange(
347+
max(valid_worlds.min_world, parent_valid_worlds.min_world),
348+
min(valid_worlds.max_world, parent_valid_worlds.max_world)),
349+
overlayed)
350+
end
300351

301352
## interpreter
302353

0 commit comments

Comments
 (0)