-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdecl.go
More file actions
159 lines (137 loc) · 4.29 KB
/
Copy pathdecl.go
File metadata and controls
159 lines (137 loc) · 4.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package main
import (
"cmp"
"fmt"
"maps"
"slices"
"strings"
)
// ordered is a declaration that knows its position in the header.
type ordered interface {
ordinal() int
}
// symbol is a declaration with a C name and a So name.
type symbol interface {
names() (cname, name string)
}
// sorted returns the declarations in header order.
func sorted[T ordered](decls map[string]T) []T {
s := slices.Collect(maps.Values(decls))
slices.SortFunc(s, func(a, b T) int { return cmp.Compare(a.ordinal(), b.ordinal()) })
return s
}
// symbols returns the declarations as symbols, in header order.
func symbols[T interface {
ordered
symbol
}](decls map[string]T) []symbol {
s := sorted(decls)
out := make([]symbol, len(s))
for i, d := range s {
out[i] = d
}
return out
}
// funcTypeDecl is a C function pointer typedef. An empty sig means the
// signature could not be expressed in So, and notes say why.
type funcTypeDecl struct {
name string
cname string
sig string // Go function type, "func(c.Int) c.Int"
notes []note
order int
}
func (d funcTypeDecl) ordinal() int { return d.order }
func (d funcTypeDecl) names() (string, string) { return d.cname, d.name }
// structDecl is a C struct or union. Both map to a Go struct: an extern type
// only names the C layout, it does not define it.
type structDecl struct {
name string
cname string // C name, "struct Foo" for a type with no typedef
fields []fieldDecl // nil means opaque
notes []note
order int
}
func (d structDecl) ordinal() int { return d.order }
func (d structDecl) names() (string, string) { return d.cname, d.name }
type fieldDecl struct {
name string
cname string // C name, differs from name when the C name is a Go keyword
typ string
}
// constDecl is an enum member or an object-like macro. An empty value means
// the constant could not be expressed in So, and notes say why.
type constDecl struct {
name string
cname string
value string
notes []note
order int
}
func (d constDecl) ordinal() int { return d.order }
func (d constDecl) names() (string, string) { return d.cname, d.name }
type funcDecl struct {
name string
cname string
params []paramDecl
result string
variadic bool
notes []note
order int
}
func (d funcDecl) ordinal() int { return d.order }
func (d funcDecl) names() (string, string) { return d.cname, d.name }
type paramDecl struct {
name string
typ string
}
// varDecl is a C global variable, or an object-like macro that expands to a
// string literal. A macro has no So type to be a constant of, so it becomes a
// variable of the C string type the literal really has. An empty type means the
// variable could not be expressed in So, and notes say why.
type varDecl struct {
name string
cname string
typ string
comment string // the C text of a string macro
notes []note
order int
}
func (d varDecl) ordinal() int { return d.order }
func (d varDecl) names() (string, string) { return d.cname, d.name }
// noteVerb says what sobind did with a C declaration it could not map.
type noteVerb string
const (
noteOpaque noteVerb = "opaque" // the type is emitted without its fields
noteSkipped noteVerb = "skipped" // nothing is emitted for the C symbol
noteGuessed noteVerb = "guessed" // the declaration is emitted, but not as C declares it
noteInlined noteVerb = "inlined" // the header defines the function, so it may have no symbol
)
// note explains a C declaration sobind could not map. A declaration has zero
// or more notes, each emitted as a single line with a "sobind:" prefix.
type note struct {
verb noteVerb
target string // C name
reason string
}
func (n note) String() string {
return fmt.Sprintf("// sobind: %s %s, %s", n.verb, n.target, n.reason)
}
// noteSummary is the line under the file header that counts the declarations
// which may need manual work. It is empty when there are no notes.
func noteSummary(notes []note) string {
if len(notes) == 0 {
return ""
}
count := map[noteVerb]int{}
for _, n := range notes {
count[n.verb]++
}
var parts []string
for _, verb := range []noteVerb{noteOpaque, noteSkipped, noteGuessed, noteInlined} {
if count[verb] > 0 {
parts = append(parts, fmt.Sprintf("%d %s", count[verb], verb))
}
}
return fmt.Sprintf("// sobind: %s", strings.Join(parts, ", "))
}