Skip to content

Commit 54a8b0f

Browse files
committed
refactor: moved more gdext stuff to gdext
1 parent 152ecb4 commit 54a8b0f

File tree

8 files changed

+520
-479
lines changed

8 files changed

+520
-479
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@ main
2323
data/
2424

2525
# generated
26-
src/_*.v
26+
_*.v

bin/gen.vsh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import generator { Generator }
77

88
fn main() {
99
println('Generating V bindings...')
10-
execute('rm src/_*.v')
10+
execute('rm */_*.v')
1111

1212
mut api_dump_file := 'data/extension_api.json'
1313

src/class.v renamed to gdext/register.v

Lines changed: 159 additions & 166 deletions
Large diffs are not rendered by default.

generator/convert.v

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ const keywords = [
5454
'union',
5555
'unsafe',
5656
'volatile',
57+
'voidptr',
5758
]
5859

5960
const genwords = [
@@ -76,8 +77,13 @@ fn convert_name(_name string) string {
7677
return name
7778
}
7879

80+
@[params]
81+
struct ConvertCfg {
82+
ns string // namespace module
83+
}
84+
7985
// convert type from C++ to V
80-
fn convert_type(_type string) string {
86+
fn convert_type(_type string, cfg ConvertCfg) string {
8187
mut type := _type
8288

8389
type = type.replace('enum::', '')
@@ -123,7 +129,7 @@ fn convert_type(_type string) string {
123129
type = type.replace('::', '')
124130

125131
for type.ends_with('*') {
126-
type = '&${type[..type.len - 1]}'
132+
type = '&${type[..type.len - 1]}'.trim_space_right()
127133
}
128134

129135
if type.replace('&', '') == 'int' {
@@ -134,6 +140,15 @@ fn convert_type(_type string) string {
134140
type = type.replace('float', 'f64')
135141
}
136142

143+
// inject namespace if needed
144+
type_stripped := type.replace('&', '')
145+
if cfg.ns != '' && type_stripped !in numbers && type_stripped !in keywords {
146+
type = '${cfg.ns}.${type_stripped}'
147+
if indirections := type.last_index('&') {
148+
type = '${type[..indirections]}${type}'
149+
}
150+
}
151+
137152
return type
138153
}
139154

generator/generator.v

Lines changed: 135 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub fn Generator.new(api_dump string) Generator {
2626
pub fn (mut g Generator) run() ! {
2727
g.setup()
2828

29+
g.gen_gdext()!
2930
g.gen_functions()!
3031
g.gen_enums()!
3132
g.gen_builtin_classes()!
@@ -68,27 +69,111 @@ fn (mut g Generator) setup() {
6869
}
6970
}
7071

71-
fn (g &Generator) gen_enums() ! {
72+
fn (g &Generator) gen_gdext() ! {
7273
mut buf := strings.new_builder(1024)
73-
buf.writeln('module gd')
74+
buf.writeln('
75+
|module gdext
76+
|
77+
|import gd
78+
'.strip_margin().trim('\n'))
7479

75-
for enm in g.api.global_enums {
76-
name := convert_type(enm.name)
77-
buf.writeln('')
78-
buf.writeln('pub enum ${name} as i64 {')
79-
mut bits := []i64{cap: enm.values.len}
80+
// call_func
81+
buf.writeln('
82+
|// TODO: see if we can leverage the passed-in FunctionData
83+
|fn call_func[T](user_data voidptr, instance gd.GDExtensionClassInstancePtr, args &&gd.Variant, arg_count gd.GDExtensionInt, ret &gd.Variant, err &gd.GDExtensionCallError) {
84+
| mut inst := unsafe { &T(instance) }
85+
| method_data := unsafe { &FunctionData(user_data) }
86+
| // HACK: there is no way this nested `\$for` is actually necessary...
87+
| \$for method in T.methods {
88+
| if method.name == method_data.name {
89+
| mut params := []voidptr{}
90+
| // handle params
91+
| // TODO: leverage `gd.ToVariant` and `gd.FromVariant` interfaces
92+
| mut p := 0
93+
| \$for param in method.params {
94+
| prm := unsafe { &args[p] }
95+
| \$if param.typ is &bool {
96+
| value := prm.to_bool()
97+
| params << &value
98+
| } \$else \$if param.typ is &string {
99+
| value := prm.to_string()
100+
| params << &value
101+
| } \$else \$if param.typ is &int {
102+
| value := prm.to_int()
103+
| params << &value
104+
| } \$else \$if param.typ is &i64 {
105+
| value := gd.i64_from_variant(prm)
106+
| params << &value
107+
| } \$else \$if param.typ is &f64 {
108+
| value := gd.f64_from_variant(prm)
109+
| params << &value
110+
'.strip_margin().trim_right('\n'))
80111

81-
for val in enm.values {
82-
if val.value !in bits {
83-
bits << val.value
84-
buf.writeln('\t${val.name.to_lower()} = ${val.value}')
85-
}
112+
for class in g.api.builtin_classes {
113+
if class.name.is_lower() {
114+
continue
86115
}
116+
class_name := convert_type(class.name, ns: 'gd')
117+
buf.writeln('
118+
| } \$else \$if param.typ is ${class_name} || param.typ is &${class_name} {
119+
| mut value := ${class_name}{}
120+
| value.from_variant(prm)
121+
| params << &value
122+
'.strip_margin().trim('\n'))
123+
}
87124

88-
buf.writeln('}')
125+
for class in g.api.classes {
126+
class_name := convert_type(class.name, ns: 'gd')
127+
buf.writeln('
128+
| } \$else \$if param.typ is ${class_name} || param.typ is &${class_name} {
129+
| mut value := ${class_name}{}
130+
| value.from_variant(prm)
131+
| params << &value
132+
'.strip_margin().trim('\n'))
89133
}
90134

91-
mut f := os.create('src/__enums.v')!
135+
buf.writeln("
136+
| } \$else {
137+
| params << &prm
138+
| }
139+
| p += 1
140+
| }
141+
| if p != arg_count {
142+
| panic('call_func: argument count mismatch')
143+
| }
144+
| // handle return value
145+
| \$if method.return_type is bool {
146+
| result := inst.\$method(...params)
147+
| ret.from_bool(result)
148+
| } \$else \$if method.return_type is string {
149+
| result := inst.\$method(...params)
150+
| str := String.new(result)
151+
| variant := str.to_variant()
152+
| ret.from_variant(variant)
153+
| } \$else \$if method.return_type is int {
154+
| result := inst.\$method(...params)
155+
| ret.from_int(result)
156+
| } \$else \$if method.return_type is i64 {
157+
| result := inst.\$method(...params)
158+
| ret.from_variant(gd.i64_to_variant(result))
159+
| } \$else \$if method.return_type is f64 {
160+
| result := inst.\$method(...params)
161+
| ret.from_variant(gd.f64_to_variant(result))
162+
| } \$else \$if method.return_type is gd.ToVariant {
163+
| result := inst.\$method(...params)
164+
| variant := result.to_variant()
165+
| ret.from_variant(variant)
166+
| } \$else {
167+
| // TODO: \$if method.return_type == 1
168+
| // void
169+
| inst.\$method(...params)
170+
| }
171+
| }
172+
| }
173+
|}
174+
".strip_margin().trim('\n'))
175+
176+
mut f := os.create('gdext/__functions.v')!
92177
defer { f.close() }
93178
f.write(buf)!
94179
}
@@ -192,101 +277,32 @@ fn (g &Generator) gen_functions() ! {
192277
buf.writeln('}')
193278
}
194279

195-
// call_func
196-
buf.writeln('
197-
|// TODO: see if we can leverage the passed-in FunctionData
198-
|fn call_func[T](user_data voidptr, instance GDExtensionClassInstancePtr, args &&Variant, arg_count GDExtensionInt, ret &Variant, err &GDExtensionCallError) {
199-
| mut inst := unsafe { &T(instance) }
200-
| method_data := unsafe { &FunctionData(user_data) }
201-
| // HACK: there is no way this nested `\$for` is actually necessary...
202-
| \$for method in T.methods {
203-
| if method.name == method_data.name {
204-
| mut params := []voidptr{}
205-
| // handle params
206-
| // TODO: leverage `ToVariant` and `FromVariant` interfaces
207-
| mut p := 0
208-
| \$for param in method.params {
209-
| prm := unsafe { &args[p] }
210-
| \$if param.typ is &bool {
211-
| value := prm.to_bool()
212-
| params << &value
213-
| } \$else \$if param.typ is &string {
214-
| value := prm.to_string()
215-
| params << &value
216-
| } \$else \$if param.typ is &int {
217-
| value := prm.to_int()
218-
| params << &value
219-
| } \$else \$if param.typ is &i64 {
220-
| value := i64_from_variant(prm)
221-
| params << &value
222-
| } \$else \$if param.typ is &f64 {
223-
| value := f64_from_variant(prm)
224-
| params << &value
225-
'.strip_margin().trim_right('\n'))
280+
mut f := os.create('src/__functions.v')!
281+
defer { f.close() }
282+
f.write(buf)!
283+
}
226284

227-
for class in g.api.builtin_classes {
228-
if class.name.is_lower() {
229-
continue
285+
fn (g &Generator) gen_enums() ! {
286+
mut buf := strings.new_builder(1024)
287+
buf.writeln('module gd')
288+
289+
for enm in g.api.global_enums {
290+
name := convert_type(enm.name)
291+
buf.writeln('')
292+
buf.writeln('pub enum ${name} as i64 {')
293+
mut bits := []i64{cap: enm.values.len}
294+
295+
for val in enm.values {
296+
if val.value !in bits {
297+
bits << val.value
298+
buf.writeln('\t${val.name.to_lower()} = ${val.value}')
299+
}
230300
}
231-
buf.writeln('
232-
| } \$else \$if param.typ is ${class.name} || param.typ is &${class.name} {
233-
| mut value := ${class.name}{}
234-
| value.from_variant(prm)
235-
| params << &value
236-
'.strip_margin().trim('\n'))
237-
}
238301

239-
for class in g.api.classes {
240-
buf.writeln('
241-
| } \$else \$if param.typ is ${class.name} || param.typ is &${class.name} {
242-
| mut value := ${class.name}{}
243-
| value.from_variant(prm)
244-
| params << &value
245-
'.strip_margin().trim('\n'))
302+
buf.writeln('}')
246303
}
247304

248-
buf.writeln("
249-
| } \$else {
250-
| params << &prm
251-
| }
252-
| p += 1
253-
| }
254-
| if p != arg_count {
255-
| panic('call_func: argument count mismatch')
256-
| }
257-
| // handle return value
258-
| \$if method.return_type is bool {
259-
| result := inst.\$method(...params)
260-
| ret.from_bool(result)
261-
| } \$else \$if method.return_type is string {
262-
| result := inst.\$method(...params)
263-
| str := String.new(result)
264-
| variant := str.to_variant()
265-
| ret.from_variant(variant)
266-
| } \$else \$if method.return_type is int {
267-
| result := inst.\$method(...params)
268-
| ret.from_int(result)
269-
| } \$else \$if method.return_type is i64 {
270-
| result := inst.\$method(...params)
271-
| ret.from_variant(i64_to_variant(result))
272-
| } \$else \$if method.return_type is f64 {
273-
| result := inst.\$method(...params)
274-
| ret.from_variant(f64_to_variant(result))
275-
| } \$else \$if method.return_type is ToVariant {
276-
| result := inst.\$method(...params)
277-
| variant := result.to_variant()
278-
| ret.from_variant(variant)
279-
| } \$else {
280-
| // TODO: \$if method.return_type == 1
281-
| // void
282-
| inst.\$method(...params)
283-
| }
284-
| }
285-
| }
286-
|}
287-
".strip_margin().trim('\n'))
288-
289-
mut f := os.create('src/__functions.v')!
305+
mut f := os.create('src/__enums.v')!
290306
defer { f.close() }
291307
f.write(buf)!
292308
}
@@ -705,7 +721,7 @@ fn (g &Generator) gen_classes() ! {
705721

706722
// struct
707723
buf.writeln('')
708-
buf.writeln('@[noinit]')
724+
// buf.writeln('@[noinit]')
709725
buf.writeln('pub struct ${class.name} {')
710726
if class.inherits == '' {
711727
buf.writeln('pub mut:')
@@ -1062,7 +1078,11 @@ fn (g &Generator) class_to_variant_type(class_name string) string {
10621078

10631079
fn (g &Generator) gen_virtual_methods() ! {
10641080
mut buf := strings.new_builder(1024)
1065-
buf.writeln('module gd')
1081+
buf.writeln('
1082+
|module gdext
1083+
|
1084+
|import gd
1085+
'.strip_margin().trim('\n'))
10661086

10671087
// methods
10681088
for class in g.api.classes {
@@ -1075,11 +1095,13 @@ fn (g &Generator) gen_virtual_methods() ! {
10751095
virt_name := '${convert_name(method.name[1..])}_'
10761096

10771097
buf.writeln('')
1078-
buf.writeln('fn ${convert_type(class.name).to_lower()}_${convert_name(method.name)}[T] (inst GDExtensionClassInstancePtr, args &GDExtensionConstTypePtr, ret GDExtensionTypePtr) {')
1079-
buf.writeln('\tmut v_inst := &${name}(unsafe{&T(inst)})')
1098+
buf.writeln('fn ${convert_type(class.name).to_lower()}_${convert_name(method.name)}[T] (inst gd.GDExtensionClassInstancePtr, args &gd.GDExtensionConstTypePtr, ret gd.GDExtensionTypePtr) {')
1099+
buf.writeln('\tmut v_inst := &gd.${name}(unsafe{&T(inst)})')
10801100

10811101
for i, arg in method.arguments {
1082-
buf.writeln('\t${convert_name(arg.name)} := unsafe{&${convert_type(arg.type)}(args[${i}])}')
1102+
buf.writeln('\t${convert_name(arg.name)} := unsafe{&${convert_type(arg.type,
1103+
ns: 'gd'
1104+
)}(args[${i}])}')
10831105
}
10841106

10851107
buf.write_string('\t')
@@ -1113,13 +1135,13 @@ fn (g &Generator) gen_virtual_methods() ! {
11131135

11141136
// HACK: force function generation
11151137
buf.writeln('
1116-
| \$if T is ${name} {
1138+
| \$if T is gd.${name} {
11171139
| // HACK: force function generation
11181140
| if false { unsafe { ${full_name}[T](nil, nil, nil) } }
11191141
| func := ${full_name}[T]
11201142
| ivar := i64(func)
1121-
| var := i64_to_variant(ivar)
1122-
| sn := StringName.new("${method.name}")
1143+
| var := gd.i64_to_variant(ivar)
1144+
| sn := gd.StringName.new("${method.name}")
11231145
| defer { sn.deinit() }
11241146
| ci.virtual_methods.index_set_named(sn, var) or {panic(err)}
11251147
| }
@@ -1128,7 +1150,7 @@ fn (g &Generator) gen_virtual_methods() ! {
11281150
}
11291151
buf.writeln('}')
11301152

1131-
mut f := os.create('src/__virtual.v')!
1153+
mut f := os.create('gdext/__virtual.v')!
11321154
defer { f.close() }
11331155
f.write(buf)!
11341156
}

0 commit comments

Comments
 (0)