-
-
Notifications
You must be signed in to change notification settings - Fork 144
/
gen_class_builder.go
131 lines (121 loc) · 2.93 KB
/
gen_class_builder.go
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
package gen
import (
"fmt"
"strings"
"github.com/progrium/macschema/schema"
)
type classBuilder struct {
Class schema.Class
Imports []PackageContents
consumedImports map[Import]bool
}
func (cb *classBuilder) EachTypeMethod(f func(schema.Method)) {
f(schema.Method{
Name: "alloc",
Return: schema.DataType{Name: "instancetype"},
})
for _, m := range cb.Class.TypeMethods {
f(m)
}
for _, p := range cb.Class.TypeProperties {
for _, m := range propertyMethods(p) {
f(m)
}
}
}
func (cb *classBuilder) EachInstanceMethod(f func(schema.Method)) {
seen := make(map[string]bool)
for _, m := range cb.Class.InstanceMethods {
seen[m.Name] = true
f(m)
}
if !seen["init"] {
f(schema.Method{
Name: "init",
Return: schema.DataType{Name: "instancetype"},
})
}
for _, p := range cb.Class.InstanceProperties {
func() {
defer ignoreIfUnimplemented(fmt.Sprintf("%s.%s", cb.Class.Name, p.Name))
for _, m := range propertyMethods(p) {
// properties sometimes specify a getter or setter method that is also
// in `InstanceMethods`, so skip those if they've already been handled
if !seen[m.Name] {
f(m)
}
}
}()
}
}
func (cb *classBuilder) instanceMethod(method schema.Method) MethodDef {
r := MethodDef{
Name: toExportedName(selectorNameToGoIdent(method.Name)),
WrappedFunc: cb.cgoWrapperFunc(method, false),
}
if isInstanceType(method.Return) {
r.Name += "_as" + cb.Class.Name
}
return r
}
func (cb *classBuilder) msgSend(method schema.Method, isTypeMethod bool) CGoMsgSend {
msg := CGoMsgSend{
Name: msgSendFuncName(cb.Class, method.Name, isTypeMethod),
Class: cb.Class.Name,
Return: cb.toMsgSendReturn(method.Return),
}
for i, key := range strings.SplitAfter(method.Name, ":") {
if key == "" {
continue
}
part := SelectorPart{
Key: key,
}
if i < len(method.Args) {
arg := method.Args[i]
typ := cb.mapType(arg.Type)
part.Arg = &Arg{
Name: arg.Name,
Type: typ.CType,
}
}
msg.Selector = append(msg.Selector, part)
}
return msg
}
func (cb *classBuilder) toMsgSendReturn(dt schema.DataType) string {
if isVoid(dt) {
return "void"
}
typ := cb.mapType(dt)
return typ.CType
}
func (cb *classBuilder) cgoWrapperFunc(method schema.Method, isTypeMethod bool) CGoWrapperFunc {
r := CGoWrapperFunc{
Name: msgSendFuncName(cb.Class, method.Name, isTypeMethod),
Args: []CGoWrapperArg{},
Returns: cb.toCGoWrapperReturn(method.Return),
}
for _, arg := range method.Args {
typ := cb.mapType(arg.Type)
goType := typ.GoSimpleRefType
if goType == "" {
goType = typ.GoType
}
r.Args = append(r.Args, CGoWrapperArg{
Name: arg.Name,
Type: goType,
ToCGoFmt: typ.ToCGoFmt,
})
}
return r
}
func (cb *classBuilder) toCGoWrapperReturn(dt schema.DataType) []CGoWrapperReturn {
if isVoid(dt) {
return nil
}
typ := cb.mapType(dt)
return []CGoWrapperReturn{
{Type: typ.GoType, FromCGoFmt: typ.FromCGoFmt},
}
}