Skip to content

Commit 4811d62

Browse files
committed
Order typedescs by dependency
1 parent 4df1528 commit 4811d62

File tree

5 files changed

+73
-7
lines changed

5 files changed

+73
-7
lines changed

Project.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
name = "JuliaLibWrapping"
22
uuid = "d61f35a8-f6af-436f-bc10-cee6b101f7bd"
3-
authors = ["Tim Holy <[email protected]> and contributors"]
43
version = "1.0.0-DEV"
4+
authors = ["Tim Holy <[email protected]> and contributors"]
55

66
[deps]
77
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
8+
OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
89

910
[compat]
1011
Graphs = "1"
12+
OrderedCollections = "1.8.1"
1113
julia = "1.12"
1214

1315
[extras]

src/JuliaLibWrapping.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
module JuliaLibWrapping
22

3+
using OrderedCollections
34
using Graphs
45

56
export parselog

src/parselog.jl

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ Extract the signatures of the entrypoints and nonstandard types from a log file.
5050
"""
5151
function parselog(filename::String)
5252
entrypoints = MethodDesc[]
53-
typedescs = Dict{String, TypeDesc}()
53+
typedescs = OrderedDict{String, TypeDesc}()
5454

5555
open(filename) do f
5656
handling_types = false
@@ -99,6 +99,31 @@ function parselog(filename::String)
9999
end
100100
end
101101

102+
# Sort the types by building a dependency graph
103+
g = SimpleDiGraph(length(typedescs))
104+
name2idx = Dict(name => i for (i, name) in enumerate(keys(typedescs)))
105+
for (i, (_, type)) in enumerate(typedescs)
106+
for field in type.fields
107+
dep = get(name2idx, field.type, nothing)
108+
if dep !== nothing
109+
add_edge!(g, i, dep)
110+
end
111+
end
112+
end
113+
function lt(a, b)
114+
# if neither is a declared type, compare by name
115+
haskey(typedescs, a) || haskey(typedescs, b) || return a < b
116+
# if one is not declared, it comes first
117+
!haskey(typedescs, a) && return true
118+
!haskey(typedescs, b) && return false
119+
# otherwise, a < b if there is a path from b to a
120+
ia, ib = name2idx[a], name2idx[b]
121+
has_path(g, ib, ia) && return true
122+
has_path(g, ia, ib) && return false
123+
return a < b # if no path, compare by name
124+
end
125+
sort!(typedescs; lt)
126+
102127
return entrypoints, typedescs
103128
end
104129
parselog(filename::AbstractString) = parselog(String(filename)::String)

test/bindinginfo_simplelib.log renamed to test/bindinginfo_libsimple.log

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
countsame(list::Ptr{MyTwoVec}, n::Int32)::Int32
12
copyto_and_sum(fromto::CVectorPair{Float32})::Float32
23

4+
MyTwoVec
5+
x::Int32[0]
6+
y::Int32[4]
7+
8 bytes
38
CVectorPair{Float32}
49
from::CVector{Float32}[0]
510
to::CVector{Float32}[16]

test/runtests.jl

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,39 @@
11
using JuliaLibWrapping
22
using Test
33

4+
function onlymatch(f, collection)
5+
matches = filter(f, collection)
6+
if length(matches) != 1
7+
error("Expected exactly one match, found $(length(matches))")
8+
end
9+
return matches[1]
10+
end
11+
412
@testset "JuliaLibWrapping.jl" begin
513
@testset "parselog" begin
6-
entrypoints, typedescs = parselog("bindinginfo_simplelib.log")
7-
methdesc = only(entrypoints)
8-
@test methdesc.name == "copyto_and_sum"
14+
entrypoints, typedescs = parselog("bindinginfo_libsimple.log")
15+
16+
methdesc = onlymatch(md -> md.name == "copyto_and_sum", entrypoints)
917
@test methdesc.return_type == "Float32"
1018
@test length(methdesc.args) == 1
1119
argdesc = only(methdesc.args)
1220
@test argdesc.name == "fromto"
1321
@test argdesc.type == "CVectorPair{Float32}"
1422
@test argdesc.isva == false
15-
@test length(typedescs) == 2
23+
@test sprint(show, methdesc) == "copyto_and_sum(fromto::CVectorPair{Float32})::Float32"
24+
25+
methdesc = onlymatch(md -> md.name == "countsame", entrypoints)
26+
@test methdesc.return_type == "Int32"
27+
@test length(methdesc.args) == 2
28+
argdesc1, argdesc2 = methdesc.args
29+
@test argdesc1.name == "list"
30+
@test argdesc1.type == "Ptr{MyTwoVec}"
31+
@test argdesc1.isva == false
32+
@test argdesc2.name == "n"
33+
@test argdesc2.type == "Int32"
34+
@test argdesc2.isva == false
35+
36+
@test length(typedescs) == 3
1637
tdesc = typedescs["CVectorPair{Float32}"]
1738
@test tdesc.name == "CVectorPair{Float32}"
1839
@test length(tdesc.fields) == 2
@@ -35,7 +56,19 @@ using Test
3556
@test tdesc.size == 16
3657
@test haskey(typedescs, "CVectorPair{Float32}")
3758
@test haskey(typedescs, "CVector{Float32}")
38-
@test sprint(show, only(entrypoints)) == "copyto_and_sum(fromto::CVectorPair{Float32})::Float32"
59+
tdesc = typedescs["MyTwoVec"]
60+
@test tdesc.name == "MyTwoVec"
61+
@test length(tdesc.fields) == 2
62+
@test tdesc.fields[1].name == "x"
63+
@test tdesc.fields[1].type == "Int32"
64+
@test tdesc.fields[1].offset == 0
65+
@test tdesc.fields[2].name == "y"
66+
@test tdesc.fields[2].type == "Int32"
67+
@test tdesc.fields[2].offset == 4
68+
@test tdesc.size == 8
69+
name2idx = Dict(name => i for (i, name) in enumerate(keys(typedescs)))
70+
@test name2idx["CVectorPair{Float32}"] > name2idx["CVector{Float32}"]
71+
3972
str = sprint(show, typedescs)
4073
@test occursin("CVectorPair{Float32}(from::CVector{Float32}[0], to::CVector{Float32}[16]) (32 bytes)", str)
4174
@test occursin("CVector{Float32}(length::Int32[0], data::Ptr{Float32}[8]) (16 bytes)", str)

0 commit comments

Comments
 (0)