Flesh out vkheader implementation, uses registry and custom callbacks to fill out...
[panamaz] / src / notzed.nativez / lib / code.api
1 # -*- Mode:text; tab-width:4; electric-indent-mode: nil; indent-line-function:insert-tab; -*-
2
3 # method template
4 # 'invoke' is a simple string template
5 # variables are defined by method.pm
6 code method {
7         # normal function invocation
8         invoke {{
9         static final MethodHandle {name}$FH = Memory.downcall("{name}", {function-descriptor});
10         public {static}{java-result} {rename}({java-arguments}) {
11                 {native-output-define}
12                 {native-result-define}
13                 try {create-frame}{
14                         {native-output-init}
15                         {native-result-assign}{name}$FH.invokeExact({native-call});
16                         {native-output-copy}
17                         {result-test}{
18                                 {java-result-assign}
19                                 {on-success}
20                                 {java-result-return}
21                         }
22                 } catch (Throwable t) {
23                         throw new RuntimeException(t);
24                 }
25                 {result-throw}
26         }
27         }}
28
29         invoke-dynamic-init {{
30                 {name}$FH = Memory.downcall("{name}", {function-descriptor}, resolve, scope);
31         }}
32
33         invoke-dynamic {{
34         final MethodHandle {name}$FH;
35         public {java-result} {rename}({java-arguments}) {
36                 {native-output-define}
37                 {native-result-define}
38                 try {create-frame}{
39                         {native-output-init}
40                         {native-result-assign}{name}$FH.invokeExact({native-call});
41                         {native-output-copy}
42                         {result-test}{
43                                 {java-result-assign}
44                                 {on-success}
45                                 {java-result-return}
46                         }
47                 } catch (Throwable t) {
48                         throw new RuntimeException(t);
49                 }
50                 {result-throw}
51         }
52         }}
53
54         # callback function/types
55         downcall {{
56         public static FunctionPointer<{rename}> downcall(MemoryAddress addr$, ResourceScope scope$) {
57                 NativeSymbol symbol$ = NativeSymbol.ofAddress("{rename}", addr$, scope$);
58                 MethodHandle {rename}$FH = Memory.downcall(symbol$, descriptor());
59                 return new FunctionPointer<{rename}>(
60                         symbol$,
61                         ({java-arguments}) -> {
62                                 {native-output-define}
63                                 {native-result-define}
64                                 try {create-frame}{
65                                         {native-output-init}
66                                         {native-result-assign}{rename}$FH.invokeExact({native-call});
67                                         {native-output-copy}
68                                         {result-test}{
69                                                 {java-result-assign}
70                                                 {on-success}
71                                                 {java-result-return}
72                                         }
73                                 } catch (Throwable t) {
74                                         throw new RuntimeException(t);
75                                 }
76                         });
77         }
78         }}
79
80         upcall {{
81         public static FunctionPointer<{rename}> upcall({rename} target$, ResourceScope scope$) {
82                 interface Trampoline {
83                         {java-result} call({native-arguments});
84                 }
85                 Trampoline trampoline = ({native-arguments}) -> {
86                         // frame?  scope?
87                         try (ResourceScope upcallScope$ = ResourceScope.newConfinedScope()) {
88                                 {trampoline-result-define}target$.call({java-call});
89                                 {trampoline-result-return}
90                         }
91                 };
92                 return new FunctionPointer<>(
93                         Memory.upcall(
94                                 MethodHandles.lookup(),
95                                 trampoline,
96                                 "call",
97                                 "{java-signature}",
98                                 descriptor(),
99                                 scope$),
100                         target$);
101         }
102         }}
103 }
104
105
106 # structs - normal structs
107 # handle  - anonymous structs
108 # library - library template
109
110 code class {
111         library {{
112 package {package};
113 import jdk.incubator.foreign.*;
114 import java.lang.invoke.*;
115 import au.notzed.nativez.*;
116
117 public class {name} {
118 {defines}
119 {enums}
120 {funcs}
121 }
122         }}
123         library-dynamic
124                 func:template=code:method=invoke-dynamic
125                 init:template=code:method=invoke-dynamic-init {{
126 package {package};
127 import jdk.incubator.foreign.*;
128 import java.lang.invoke.*;
129 import java.util.function.Function;
130 import au.notzed.nativez.*;
131
132 public class {name} {
133         {name}(Function<String,MemoryAddress> resolve, ResourceScope scope) {
134 {init}
135         }
136         public static {name} create(Function<String,MemoryAddress> resolve, ResourceScope scope) {
137                 return new {name}(resolve, scope);
138         }
139 {defines}
140 {enums}
141 {funcs}
142 }
143         }}
144         constants {{
145 package {package};
146
147 public interface {name} {
148 {enums}
149 {defines}
150 }
151         }}
152         struct {{
153 package {package};
154 import jdk.incubator.foreign.*;
155 import jdk.incubator.foreign.MemoryLayout.*;
156 import java.lang.invoke.*;
157 import au.notzed.nativez.*;
158
159 public class {rename} implements Pointer {
160
161         public final MemorySegment segment;
162
163         private {rename}(MemorySegment segment) {
164                 this.segment = segment;
165 {init}
166         }
167
168         public static {rename} create(MemorySegment segment) {
169                 return new {rename}(segment);
170         }
171
172         public static {rename} create(MemoryAddress address, ResourceScope scope) {
173                 return MemoryAddress.NULL != address ? create(MemorySegment.ofAddress(address, LAYOUT.byteSize(), scope)) : null;
174         }
175
176         public static {rename} create(SegmentAllocator frame) {
177                 return create(frame.allocate(LAYOUT));
178         }
179
180         @Override
181         public final MemoryAddress address() {
182                 return segment.address();
183         }
184
185         @Override
186         public final ResourceScope scope() {
187                 return segment.scope();
188         }
189
190         public final MemorySegment segment() {
191                 return segment;
192         }
193
194 {defines}
195 {enums}
196 {accessors}
197 {methods}
198 {layout}
199 {varhandles}
200 }
201 }}
202         struct-array {{
203 package {package};
204 import jdk.incubator.foreign.*;
205 import jdk.incubator.foreign.MemoryLayout.*;
206 import java.lang.invoke.*;
207 import au.notzed.nativez.*;
208
209 public class {rename} implements Pointer, Array<{rename}> {
210
211         public final MemorySegment segment;
212
213         private {rename}(MemorySegment segment) {
214                 this.segment = segment;
215 {init}
216         }
217
218         public static {rename} create(MemorySegment segment) {
219                 return new {rename}(segment);
220         }
221
222         public static {rename} create(MemoryAddress address, ResourceScope scope) {
223                 return MemoryAddress.NULL != address ? create(MemorySegment.ofAddress(address, LAYOUT.byteSize(), scope)) : null;
224         }
225
226         public static {rename} create(SegmentAllocator frame) {
227                 return create(frame.allocate(LAYOUT));
228         }
229
230         public static {rename} createArray(MemoryAddress address, ResourceScope scope) {
231                 return MemoryAddress.NULL != address ? create(MemorySegment.ofAddress(address, Long.MAX_VALUE, scope)) : null;
232         }
233
234         public static {rename} createArray(MemoryAddress address, long length, ResourceScope scope) {
235                 return MemoryAddress.NULL != address ? create(MemorySegment.ofAddress(address, LAYOUT.byteSize() * length, scope)) : null;
236         }
237
238         public static {rename} createArray(long length, SegmentAllocator alloc) {
239                 return create(alloc.allocateArray(LAYOUT, length));
240         }
241
242         @Override
243         public final MemoryAddress address() {
244                 return segment.address();
245         }
246
247         @Override
248         public final ResourceScope scope() {
249                 return segment.scope();
250         }
251
252         public final MemorySegment segment() {
253                 return segment;
254         }
255
256         @Override
257         public long length() {
258                 return segment.byteSize() / LAYOUT.byteSize();
259         }
260
261         @Override
262         public {rename} getAtIndex(long index) {
263                 try {
264                         return {rename}.create((MemorySegment){name}$SH.invokeExact(segment, index));
265                 } catch (Throwable t) {
266                         throw new RuntimeException(t);
267                 }
268         }
269
270 {defines}
271 {enums}
272 {accessors}
273 {methods}
274 {layout}
275         final static MethodHandle {name}$SH = MemoryLayout.sequenceLayout(LAYOUT).sliceHandle(PathElement.sequenceElement());
276 {varhandles}
277 }
278 }}
279         handle {{
280 package {package};
281 import jdk.incubator.foreign.*;
282 import java.lang.invoke.*;
283 import au.notzed.nativez.*;
284
285 public class {rename} implements Pointer {
286
287         MemoryAddress address;
288         ResourceScope scope;
289
290         private {rename}(MemoryAddress address, ResourceScope scope) {
291                 this.address = address;
292                 this.scope = scope;
293 {init}
294         }
295
296         public static {rename} create(MemoryAddress address, ResourceScope scope) {
297                 return MemoryAddress.NULL != address ? new {rename}(address, scope) : null;
298         }
299
300         public static HandleArray<{rename}> createArray(long count, SegmentAllocator alloc) {
301                 return HandleArray.createArray(count, alloc, {rename}::create);
302         }
303
304         @Override
305         public MemoryAddress address() {
306                 return address;
307         }
308
309         @Override
310         public ResourceScope scope() {
311                 return scope;
312         }
313
314 {defines}
315 {enums}
316 {methods}
317 }
318 }}
319         call {{
320 package {package};
321 import jdk.incubator.foreign.*;
322 import java.lang.invoke.*;
323 import au.notzed.nativez.*;
324
325 @FunctionalInterface
326 public interface {rename} {
327         {java-result} call({java-arguments});
328
329         public static FunctionDescriptor descriptor() {
330                 return {function-descriptor};
331         }
332
333 {upcall}
334 {downcall}
335 }
336 }}
337 }
338
339 # do I want this to be perl code as template or just a template?
340 code getset {
341         get set=value={getnative} {{
342         public {type} get{rename}() {
343                 return {tojava};
344         }
345         }}
346         geti set=value={getnative} set=segment=segment {{
347         # TODO: final static VarHandle {name}$VI = MemoryLayout.sequenceLayout(LAYOUT).varHandle(PathElement.sequenceElement(), PathElement.groupElement("{name}"));
348         public {type} get{rename}AtIndex(long index) {
349                 // option a: resolve an offset segment and asme as above with set=segment=segment
350                 // option b: an indexed varhandle
351                 MemorySegment segment = segment().asSlice(index * LAYOUT.byteSize(), LAYOUT.byteSize());
352                 return {tojava};
353         }
354         }}
355         set set=value=value {{
356         public void set{rename}({type} value) {
357                 {setnative};
358         }
359         }}
360         seti set=value=value set=segment=segment {{
361         public void set{rename}AtIndex(long index, {type} value) {
362                 MemorySegment segment = segment().asSlice(index * LAYOUT.byteSize(), LAYOUT.byteSize());
363                 {setnative};
364         }
365         }}
366 }
367
368 # set requires allocations, not sure if it should be Frame or Scope?
369 code getset-frame {
370         get set=value={getnative} {{
371         public {type} get{rename}() {
372                 return {tojava};
373         }
374         }}
375         geti set=value={getnative} set=segment=segment {{
376         public {type} get{rename}AtIndex(long index) {
377                 // option a: resolve an offset segment and asme as above with set=segment=segment
378                 // option b: an indexed varhandle
379                 MemorySegment segment = segment().asSlice(index * LAYOUT.byteSize(), LAYOUT.byteSize());
380                 return {tojava};
381         }
382         }}
383         set set=value=value {{
384         public void set{rename}(Frame frame$, {type} value) {
385                 {setnative};
386         }
387         }}
388         seti set=value=value set=segment=segment {{
389         public void set{rename}AtIndex(Frame frame$, long index, {type} value) {
390                 MemorySegment segment = segment().asSlice(index * LAYOUT.byteSize(), LAYOUT.byteSize());
391                 {setnative};
392         }
393         }}
394 }
395
396 code getsetelement {
397         get set=index=i {{
398         public {typei} get{rename}Element(long i) {
399                 return {getnativei};
400         }
401         }}
402         set set=index=i set=value=value {{
403         public void set{rename}Element(long i, {typei} value) {
404                 {setnativei};
405         }
406         }}
407 }
408
409 code getsetelement2d {
410         get set=index0=i set=index1=j {{
411         public {typei} get{rename}Element(long i, long j) {
412                 return {getnativei};
413         }
414         }}
415         set set=index0=i set=index1=j set=value=value {{
416         public void set{rename}Element(long i, long j, {typei} value) {
417                 {setnativei};
418         }
419         }}
420 }
421
422 code getbyvalue {
423         get {{
424         public {type} get{rename}() {
425                 try {
426                         return {getnative};
427                 } catch (Throwable t) {
428                         throw new RuntimeException(t);
429                 }
430         }
431         }}
432 }