256b74f64c3a0ca847b5afead008787d34147dbf
[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                         {trampoline-result-define}target$.call({java-call});
88                         {trampoline-result-return}
89                 };
90                 return new FunctionPointer<>(
91                         Memory.upcall(
92                                 MethodHandles.lookup(),
93                                 trampoline,
94                                 "call",
95                                 "{java-signature}",
96                                 descriptor(),
97                                 scope$),
98                         target$);
99         }
100         }}
101 }
102
103
104 # structs - normal structs
105 # handle  - anonymous structs
106 # library - library template
107
108 code class {
109         library {{
110 package {package};
111 import jdk.incubator.foreign.*;
112 import java.lang.invoke.*;
113 import au.notzed.nativez.*;
114
115 public class {name} {
116 {defines}
117 {enums}
118 {funcs}
119 }
120         }}
121         library-dynamic
122                 func:template=code:method=invoke-dynamic
123                 init:template=code:method=invoke-dynamic-init {{
124 package {package};
125 import jdk.incubator.foreign.*;
126 import java.lang.invoke.*;
127 import java.util.function.Function;
128 import au.notzed.nativez.*;
129
130 public class {name} {
131         {name}(Function<String,MemoryAddress> resolve, ResourceScope scope) {
132 {init}
133         }
134         public static {name} create(Function<String,MemoryAddress> resolve, ResourceScope scope) {
135                 return new {name}(resolve, scope);
136         }
137 {defines}
138 {enums}
139 {funcs}
140 }
141         }}
142         constants {{
143 package {package};
144
145 public interface {name} {
146 {enums}
147 {defines}
148 }
149         }}
150         struct {{
151 package {package};
152 import jdk.incubator.foreign.*;
153 import jdk.incubator.foreign.MemoryLayout.*;
154 import java.lang.invoke.*;
155 import au.notzed.nativez.*;
156
157 public class {rename} implements Pointer {
158
159         public final MemorySegment segment;
160
161         private {rename}(MemorySegment segment) {
162                 this.segment = segment;
163         }
164
165         public static {rename} create(MemorySegment segment) {
166                 return new {rename}(segment);
167         }
168
169         public static {rename} create(MemoryAddress address, ResourceScope scope) {
170                 return MemoryAddress.NULL != address ? create(MemorySegment.ofAddress(address, LAYOUT.byteSize(), scope)) : null;
171         }
172
173         public static {rename} create(SegmentAllocator frame) {
174                 return create(frame.allocate(LAYOUT));
175         }
176
177         @Override
178         public final MemoryAddress address() {
179                 return segment.address();
180         }
181
182         @Override
183         public final ResourceScope scope() {
184                 return segment.scope();
185         }
186
187         public final MemorySegment segment() {
188                 return segment;
189         }
190
191 {defines}
192 {enums}
193 {accessors}
194 {methods}
195 {layout}
196 {varhandles}
197 }
198 }}
199         struct-array {{
200 package {package};
201 import jdk.incubator.foreign.*;
202 import jdk.incubator.foreign.MemoryLayout.*;
203 import java.lang.invoke.*;
204 import au.notzed.nativez.*;
205
206 public class {rename} implements Pointer, Array<{rename}> {
207
208         public final MemorySegment segment;
209
210         private {rename}(MemorySegment segment) {
211                 this.segment = segment;
212         }
213
214         public static {rename} create(MemorySegment segment) {
215                 return new {rename}(segment);
216         }
217
218         public static {rename} create(MemoryAddress address, ResourceScope scope) {
219                 return MemoryAddress.NULL != address ? create(MemorySegment.ofAddress(address, LAYOUT.byteSize(), scope)) : null;
220         }
221
222         public static {rename} create(SegmentAllocator frame) {
223                 return create(frame.allocate(LAYOUT));
224         }
225
226         public static {rename} createArray(MemoryAddress address, ResourceScope scope) {
227                 return MemoryAddress.NULL != address ? create(MemorySegment.ofAddress(address, Long.MAX_VALUE, scope)) : null;
228         }
229
230         @Override
231         public final MemoryAddress address() {
232                 return segment.address();
233         }
234
235         @Override
236         public final ResourceScope scope() {
237                 return segment.scope();
238         }
239
240         public final MemorySegment segment() {
241                 return segment;
242         }
243
244         @Override
245         public long length() {
246                 return segment.byteSize() / LAYOUT.byteSize();
247         }
248
249         @Override
250         public {rename} getAtIndex(long index) {
251                 try {
252                         return {rename}.create((MemorySegment){name}$SH.invokeExact(segment, index));
253                 } catch (Throwable t) {
254                         throw new RuntimeException(t);
255                 }
256         }
257
258 {defines}
259 {enums}
260 {accessors}
261 {methods}
262 {layout}
263         final static MethodHandle {name}$SH = MemoryLayout.sequenceLayout(LAYOUT).sliceHandle(PathElement.sequenceElement());
264 {varhandles}
265 }
266 }}
267         handle {{
268 package {package};
269 import jdk.incubator.foreign.*;
270 import java.lang.invoke.*;
271 import au.notzed.nativez.*;
272
273 public class {rename} implements Pointer {
274
275         MemoryAddress address;
276         ResourceScope scope;
277
278         private {rename}(MemoryAddress address, ResourceScope scope) {
279                 this.address = address;
280                 this.scope = scope;
281         }
282
283         public static {rename} create(MemoryAddress address, ResourceScope scope) {
284                 return MemoryAddress.NULL != address ? new {rename}(address, scope) : null;
285         }
286
287         @Override
288         public MemoryAddress address() {
289                 return address;
290         }
291
292         @Override
293         public ResourceScope scope() {
294                 return scope;
295         }
296
297 {defines}
298 {enums}
299 {methods}
300 }
301 }}
302         call {{
303 package {package};
304 import jdk.incubator.foreign.*;
305 import java.lang.invoke.*;
306 import au.notzed.nativez.*;
307
308 @FunctionalInterface
309 public interface {rename} {
310         {java-result} call({java-arguments});
311
312         public static FunctionDescriptor descriptor() {
313                 return {function-descriptor};
314         }
315
316 {upcall}
317 {downcall}
318 }
319 }}
320 }
321
322 # do I want this to be perl code as template or just a template?
323 code getset {
324         get set=value={getnative} {{
325         public {type} get{rename}() {
326                 return {tojava};
327         }
328         }}
329         geti set=value={getnative} set=segment=segment {{
330         public {type} get{rename}AtIndex(long index) {
331                 // option a: resolve an offset segment and asme as above with set=segment=segment
332                 // option b: an indexed varhandle
333                 MemorySegment segment = segment().asSlice(index * LAYOUT.byteSize(), LAYOUT.byteSize());
334                 return {tojava};
335         }
336         }}
337         set set=value=value {{
338         public void set{rename}({type} value) {
339                 {setnative};
340         }
341         }}
342         seti set=value=value set=segment=segment {{
343         public void set{rename}AtIndex(long index, {type} value) {
344                 MemorySegment segment = segment().asSlice(index * LAYOUT.byteSize(), LAYOUT.byteSize());
345                 {setnative};
346         }
347         }}
348 }
349
350 code getsetelement {
351         get set=index=i {{
352         public {typei} get{rename}Element(long i) {
353                 return {getnativei};
354         }
355         }}
356         set set=index=i set=value=value {{
357         public void set{rename}Element(long i, {typei} value) {
358                 {setnativei};
359         }
360         }}
361 }
362
363 code getsetelement2d {
364         get set=index0=i set=index1=j {{
365         public {typei} get{rename}Element(long i, long j) {
366                 return {getnativei};
367         }
368         }}
369         set set=index0=i set=index1=j set=value=value {{
370         public void set{rename}Element(long i, long j, {typei} value) {
371                 {setnativei};
372         }
373         }}
374 }
375
376 code getbyvalue {
377         get {{
378         public {type} get{rename}() {
379                 try {
380                         return {getnative};
381                 } catch (Throwable t) {
382                         throw new RuntimeException(t);
383                 }
384         }
385         }}
386 }