forked from nsf/gogobject
-
Notifications
You must be signed in to change notification settings - Fork 0
/
function_builder.go
117 lines (96 loc) · 2.5 KB
/
function_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
package main
import (
"gobject/gi"
)
type function_builder struct {
function *gi.FunctionInfo
args []function_builder_arg
rets []function_builder_arg
orig_args []*gi.ArgInfo
}
type function_builder_arg struct {
index int
arg_info *gi.ArgInfo
type_info *gi.TypeInfo
}
func int_slice_contains(haystack []int, needle int) bool {
for _, val := range haystack {
if val == needle {
return true
}
}
return false
}
func new_function_builder(fi *gi.FunctionInfo) *function_builder {
fb := new(function_builder)
fb.function = fi
// prepare an array of ArgInfos
for i, n := 0, fi.NumArg(); i < n; i++ {
arg := fi.Arg(i)
fb.orig_args = append(fb.orig_args, arg)
}
// build skip list
var skiplist []int
for _, arg := range fb.orig_args {
ti := arg.Type()
len := ti.ArrayLength()
if len != -1 {
skiplist = append(skiplist, len)
}
clo := arg.Closure()
if clo != -1 {
skiplist = append(skiplist, clo)
}
des := arg.Destroy()
if des != -1 {
skiplist = append(skiplist, des)
}
}
// then walk over arguments
for i, ai := range fb.orig_args {
if int_slice_contains(skiplist, i) {
continue
}
ti := ai.Type()
switch ai.Direction() {
case gi.DIRECTION_IN:
fb.args = append(fb.args, function_builder_arg{i, ai, ti})
case gi.DIRECTION_INOUT:
fb.args = append(fb.args, function_builder_arg{i, ai, ti})
fb.rets = append(fb.rets, function_builder_arg{i, ai, ti})
case gi.DIRECTION_OUT:
fb.rets = append(fb.rets, function_builder_arg{i, ai, ti})
}
}
// add return value if it exists to 'rets'
if ret := fi.ReturnType(); ret != nil && ret.Tag() != gi.TYPE_TAG_VOID {
fb.rets = append(fb.rets, function_builder_arg{-1, nil, ret})
}
// add GError special argument (if any)
if fi.Flags()&gi.FUNCTION_THROWS != 0 {
fb.rets = append(fb.rets, function_builder_arg{-2, nil, nil})
}
return fb
}
func (fb *function_builder) has_return_value() bool {
return (len(fb.rets) > 0 && fb.rets[len(fb.rets)-1].index == -1) ||
(len(fb.rets) > 1 && fb.rets[len(fb.rets)-2].index == -1)
}
func (fb *function_builder) has_closure_argument() (int, int, gi.ScopeType) {
for _, arg := range fb.args {
userdata := arg.arg_info.Closure()
if userdata == -1 {
continue
}
if arg.type_info.Tag() != gi.TYPE_TAG_INTERFACE {
continue
}
if arg.type_info.Interface().Type() != gi.INFO_TYPE_CALLBACK {
continue
}
destroy := arg.arg_info.Destroy()
scope := arg.arg_info.Scope()
return userdata, destroy, scope
}
return -1, -1, gi.SCOPE_TYPE_INVALID
}