0
# Cross-Language Interoperability
1
2
Truffle's interoperability system enables seamless integration between different languages through a standardized message-based protocol. It provides polyglot object access, cross-language method calls, and unified data type handling across the Truffle ecosystem.
3
4
## Capabilities
5
6
### Interop Library System
7
8
Core library providing standardized messages for cross-language object interaction.
9
10
```java { .api }
11
/**
12
* Main library for polyglot interoperability operations
13
*/
14
public abstract class InteropLibrary extends Library {
15
16
/**
17
* Get uncached interop library instance
18
* @return Uncached InteropLibrary
19
*/
20
public static InteropLibrary getUncached();
21
22
/**
23
* Get interop library for specific receiver
24
* @param receiver Object to get library for
25
* @return InteropLibrary instance
26
*/
27
public static InteropLibrary getUncached(Object receiver);
28
29
// ===== Array Operations =====
30
31
/**
32
* Check if object has array elements
33
* @param receiver Object to check
34
* @return true if has array elements
35
*/
36
public abstract boolean hasArrayElements(Object receiver);
37
38
/**
39
* Get array size
40
* @param receiver Array object
41
* @return Array size
42
* @throws UnsupportedMessageException if not an array
43
*/
44
public abstract long getArraySize(Object receiver) throws UnsupportedMessageException;
45
46
/**
47
* Check if array index is readable
48
* @param receiver Array object
49
* @param index Array index
50
* @return true if readable
51
*/
52
public abstract boolean isArrayElementReadable(Object receiver, long index);
53
54
/**
55
* Check if array index is writable
56
* @param receiver Array object
57
* @param index Array index
58
* @return true if writable
59
*/
60
public abstract boolean isArrayElementWritable(Object receiver, long index);
61
62
/**
63
* Check if array index is insertable
64
* @param receiver Array object
65
* @param index Array index
66
* @return true if insertable
67
*/
68
public abstract boolean isArrayElementInsertable(Object receiver, long index);
69
70
/**
71
* Check if array index is removable
72
* @param receiver Array object
73
* @param index Array index
74
* @return true if removable
75
*/
76
public abstract boolean isArrayElementRemovable(Object receiver, long index);
77
78
/**
79
* Read array element
80
* @param receiver Array object
81
* @param index Array index
82
* @return Element value
83
* @throws UnsupportedMessageException if not supported
84
* @throws InvalidArrayIndexException if invalid index
85
*/
86
public abstract Object readArrayElement(Object receiver, long index)
87
throws UnsupportedMessageException, InvalidArrayIndexException;
88
89
/**
90
* Write array element
91
* @param receiver Array object
92
* @param index Array index
93
* @param value New value
94
* @throws UnsupportedMessageException if not supported
95
* @throws UnsupportedTypeException if incompatible type
96
* @throws InvalidArrayIndexException if invalid index
97
*/
98
public abstract void writeArrayElement(Object receiver, long index, Object value)
99
throws UnsupportedMessageException, UnsupportedTypeException, InvalidArrayIndexException;
100
101
/**
102
* Remove array element
103
* @param receiver Array object
104
* @param index Array index
105
* @throws UnsupportedMessageException if not supported
106
* @throws InvalidArrayIndexException if invalid index
107
*/
108
public abstract void removeArrayElement(Object receiver, long index)
109
throws UnsupportedMessageException, InvalidArrayIndexException;
110
111
// ===== Object Member Operations =====
112
113
/**
114
* Check if object has members
115
* @param receiver Object to check
116
* @return true if has members
117
*/
118
public abstract boolean hasMembers(Object receiver);
119
120
/**
121
* Get object members
122
* @param receiver Object to inspect
123
* @param includeInternal Whether to include internal members
124
* @return Object with member names
125
* @throws UnsupportedMessageException if not supported
126
*/
127
public abstract Object getMembers(Object receiver, boolean includeInternal)
128
throws UnsupportedMessageException;
129
130
/**
131
* Check if member is readable
132
* @param receiver Object to check
133
* @param member Member name
134
* @return true if readable
135
*/
136
public abstract boolean isMemberReadable(Object receiver, String member);
137
138
/**
139
* Check if member is writable
140
* @param receiver Object to check
141
* @param member Member name
142
* @return true if writable
143
*/
144
public abstract boolean isMemberWritable(Object receiver, String member);
145
146
/**
147
* Check if member is insertable
148
* @param receiver Object to check
149
* @param member Member name
150
* @return true if insertable
151
*/
152
public abstract boolean isMemberInsertable(Object receiver, String member);
153
154
/**
155
* Check if member is removable
156
* @param receiver Object to check
157
* @param member Member name
158
* @return true if removable
159
*/
160
public abstract boolean isMemberRemovable(Object receiver, String member);
161
162
/**
163
* Check if member is invocable
164
* @param receiver Object to check
165
* @param member Member name
166
* @return true if invocable
167
*/
168
public abstract boolean isMemberInvocable(Object receiver, String member);
169
170
/**
171
* Read object member
172
* @param receiver Object to read from
173
* @param member Member name
174
* @return Member value
175
* @throws UnsupportedMessageException if not supported
176
* @throws UnknownIdentifierException if member not found
177
*/
178
public abstract Object readMember(Object receiver, String member)
179
throws UnsupportedMessageException, UnknownIdentifierException;
180
181
/**
182
* Write object member
183
* @param receiver Object to write to
184
* @param member Member name
185
* @param value New value
186
* @throws UnsupportedMessageException if not supported
187
* @throws UnknownIdentifierException if member not found
188
* @throws UnsupportedTypeException if incompatible type
189
*/
190
public abstract void writeMember(Object receiver, String member, Object value)
191
throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException;
192
193
/**
194
* Remove object member
195
* @param receiver Object to modify
196
* @param member Member name
197
* @throws UnsupportedMessageException if not supported
198
* @throws UnknownIdentifierException if member not found
199
*/
200
public abstract void removeMember(Object receiver, String member)
201
throws UnsupportedMessageException, UnknownIdentifierException;
202
203
/**
204
* Invoke object member
205
* @param receiver Object containing member
206
* @param member Member name
207
* @param arguments Invocation arguments
208
* @return Invocation result
209
* @throws UnsupportedMessageException if not supported
210
* @throws UnknownIdentifierException if member not found
211
* @throws ArityException if wrong number of arguments
212
* @throws UnsupportedTypeException if incompatible argument types
213
*/
214
public abstract Object invokeMember(Object receiver, String member, Object... arguments)
215
throws UnsupportedMessageException, UnknownIdentifierException, ArityException, UnsupportedTypeException;
216
217
// ===== Executable Operations =====
218
219
/**
220
* Check if object is executable
221
* @param receiver Object to check
222
* @return true if executable
223
*/
224
public abstract boolean isExecutable(Object receiver);
225
226
/**
227
* Execute object
228
* @param receiver Executable object
229
* @param arguments Execution arguments
230
* @return Execution result
231
* @throws UnsupportedMessageException if not executable
232
* @throws ArityException if wrong number of arguments
233
* @throws UnsupportedTypeException if incompatible argument types
234
*/
235
public abstract Object execute(Object receiver, Object... arguments)
236
throws UnsupportedMessageException, ArityException, UnsupportedTypeException;
237
238
// ===== Instantiation Operations =====
239
240
/**
241
* Check if object is instantiable
242
* @param receiver Object to check
243
* @return true if instantiable
244
*/
245
public abstract boolean isInstantiable(Object receiver);
246
247
/**
248
* Instantiate object
249
* @param receiver Constructor object
250
* @param arguments Constructor arguments
251
* @return New instance
252
* @throws UnsupportedMessageException if not instantiable
253
* @throws ArityException if wrong number of arguments
254
* @throws UnsupportedTypeException if incompatible argument types
255
*/
256
public abstract Object instantiate(Object receiver, Object... arguments)
257
throws UnsupportedMessageException, ArityException, UnsupportedTypeException;
258
259
// ===== Pointer Operations =====
260
261
/**
262
* Check if object is a pointer
263
* @param receiver Object to check
264
* @return true if pointer
265
*/
266
public abstract boolean isPointer(Object receiver);
267
268
/**
269
* Get pointer address
270
* @param receiver Pointer object
271
* @return Pointer address
272
* @throws UnsupportedMessageException if not a pointer
273
*/
274
public abstract long asPointer(Object receiver)
275
throws UnsupportedMessageException;
276
277
/**
278
* Convert to native pointer
279
* @param receiver Object to convert
280
* @return Native pointer
281
* @throws UnsupportedMessageException if not convertible
282
*/
283
public abstract void toNative(Object receiver)
284
throws UnsupportedMessageException;
285
286
// ===== Type Checking Operations =====
287
288
/**
289
* Check if object is null
290
* @param receiver Object to check
291
* @return true if null
292
*/
293
public abstract boolean isNull(Object receiver);
294
295
/**
296
* Check if object is boolean
297
* @param receiver Object to check
298
* @return true if boolean
299
*/
300
public abstract boolean isBoolean(Object receiver);
301
302
/**
303
* Convert to boolean
304
* @param receiver Object to convert
305
* @return boolean value
306
* @throws UnsupportedMessageException if not convertible
307
*/
308
public abstract boolean asBoolean(Object receiver)
309
throws UnsupportedMessageException;
310
311
/**
312
* Check if object is string
313
* @param receiver Object to check
314
* @return true if string
315
*/
316
public abstract boolean isString(Object receiver);
317
318
/**
319
* Convert to string
320
* @param receiver Object to convert
321
* @return String value
322
* @throws UnsupportedMessageException if not convertible
323
*/
324
public abstract String asString(Object receiver)
325
throws UnsupportedMessageException;
326
327
/**
328
* Check if object is number
329
* @param receiver Object to check
330
* @return true if number
331
*/
332
public abstract boolean isNumber(Object receiver);
333
334
/**
335
* Check if number fits in int
336
* @param receiver Number object
337
* @return true if fits in int
338
*/
339
public abstract boolean fitsInInt(Object receiver);
340
341
/**
342
* Convert to int
343
* @param receiver Number object
344
* @return int value
345
* @throws UnsupportedMessageException if not convertible
346
*/
347
public abstract int asInt(Object receiver)
348
throws UnsupportedMessageException;
349
350
/**
351
* Check if number fits in long
352
* @param receiver Number object
353
* @return true if fits in long
354
*/
355
public abstract boolean fitsInLong(Object receiver);
356
357
/**
358
* Convert to long
359
* @param receiver Number object
360
* @return long value
361
* @throws UnsupportedMessageException if not convertible
362
*/
363
public abstract long asLong(Object receiver)
364
throws UnsupportedMessageException;
365
366
/**
367
* Check if number fits in double
368
* @param receiver Number object
369
* @return true if fits in double
370
*/
371
public abstract boolean fitsInDouble(Object receiver);
372
373
/**
374
* Convert to double
375
* @param receiver Number object
376
* @return double value
377
* @throws UnsupportedMessageException if not convertible
378
*/
379
public abstract double asDouble(Object receiver)
380
throws UnsupportedMessageException;
381
}
382
```
383
384
### Interoperable Object Interface
385
386
Base interface for objects that participate in cross-language interoperability.
387
388
```java { .api }
389
/**
390
* Marker interface for objects that can be used across language boundaries
391
*/
392
public interface TruffleObject {
393
// Marker interface - no methods
394
}
395
```
396
397
### Library Export System
398
399
Annotations for exporting interop capabilities to other languages.
400
401
```java { .api }
402
/**
403
* Exports library implementation for a class
404
*/
405
@Retention(RetentionPolicy.CLASS)
406
@Target(ElementType.TYPE)
407
@Repeatable(ExportLibrary.List.class)
408
public @interface ExportLibrary {
409
410
/**
411
* Library class to export
412
* @return Library class
413
*/
414
Class<? extends Library> value();
415
416
/**
417
* Receiver type for library
418
* @return Receiver class
419
*/
420
Class<?> receiverType() default Object.class;
421
422
/**
423
* Priority for library resolution
424
* @return Priority value
425
*/
426
int priority() default 0;
427
428
/**
429
* Container for multiple ExportLibrary annotations
430
*/
431
@Retention(RetentionPolicy.CLASS)
432
@Target(ElementType.TYPE)
433
@interface List {
434
ExportLibrary[] value();
435
}
436
}
437
438
/**
439
* Exports message implementation
440
*/
441
@Retention(RetentionPolicy.CLASS)
442
@Target(ElementType.METHOD)
443
public @interface ExportMessage {
444
445
/**
446
* Message name (defaults to method name)
447
* @return Message name
448
*/
449
String name() default "";
450
451
/**
452
* Library class containing message
453
* @return Library class
454
*/
455
Class<? extends Library> library() default Library.class;
456
}
457
```
458
459
**Usage Example:**
460
461
```java
462
@ExportLibrary(InteropLibrary.class)
463
public class MyInteropObject implements TruffleObject {
464
465
private final Map<String, Object> members = new HashMap<>();
466
467
@ExportMessage
468
boolean hasMembers() {
469
return true;
470
}
471
472
@ExportMessage
473
Object getMembers(boolean includeInternal) {
474
return new MemberKeys(members.keySet());
475
}
476
477
@ExportMessage
478
boolean isMemberReadable(String member) {
479
return members.containsKey(member);
480
}
481
482
@ExportMessage
483
Object readMember(String member) throws UnknownIdentifierException {
484
Object value = members.get(member);
485
if (value == null) {
486
throw UnknownIdentifierException.create(member);
487
}
488
return value;
489
}
490
491
@ExportMessage
492
boolean isMemberWritable(String member) {
493
return true;
494
}
495
496
@ExportMessage
497
void writeMember(String member, Object value) {
498
members.put(member, value);
499
}
500
}
501
```
502
503
### Node Library System
504
505
Library for operations on AST nodes in interop contexts.
506
507
```java { .api }
508
/**
509
* Library for interop operations on nodes
510
*/
511
public abstract class NodeLibrary extends Library {
512
513
/**
514
* Get uncached node library
515
* @return Uncached NodeLibrary
516
*/
517
public static NodeLibrary getUncached();
518
519
/**
520
* Check if receiver accepts language and frame
521
* @param receiver Node to check
522
* @param frame Execution frame
523
* @param language Target language
524
* @return true if accepts
525
*/
526
public boolean accepts(Object receiver, VirtualFrame frame, Class<? extends TruffleLanguage<?>> language) {
527
return false;
528
}
529
530
/**
531
* Get view of node for specific language
532
* @param receiver Node to get view for
533
* @param frame Execution frame
534
* @param language Target language
535
* @return Language-specific view
536
* @throws UnsupportedMessageException if not supported
537
*/
538
public Object getView(Object receiver, VirtualFrame frame, Class<? extends TruffleLanguage<?>> language)
539
throws UnsupportedMessageException {
540
throw UnsupportedMessageException.create();
541
}
542
}
543
```
544
545
### Exception Types
546
547
Comprehensive exception hierarchy for interop error handling.
548
549
```java { .api }
550
/**
551
* Base class for all interop exceptions
552
*/
553
public abstract class InteropException extends AbstractTruffleException {
554
555
/**
556
* Protected constructor
557
* @param message Exception message
558
*/
559
protected InteropException(String message) {
560
super(message);
561
}
562
563
/**
564
* Protected constructor
565
* @param message Exception message
566
* @param cause Exception cause
567
*/
568
protected InteropException(String message, Throwable cause) {
569
super(message, cause);
570
}
571
}
572
573
/**
574
* Exception for unsupported interop messages
575
*/
576
public final class UnsupportedMessageException extends InteropException {
577
578
/**
579
* Create exception
580
* @return New exception instance
581
*/
582
public static UnsupportedMessageException create() {
583
return new UnsupportedMessageException();
584
}
585
586
private UnsupportedMessageException() {
587
super("Message not supported");
588
}
589
}
590
591
/**
592
* Exception for incorrect number of arguments
593
*/
594
public final class ArityException extends InteropException {
595
596
/**
597
* Create exception
598
* @param expectedArity Expected number of arguments
599
* @param actualArity Actual number of arguments
600
* @return New exception instance
601
*/
602
public static ArityException create(int expectedArity, int actualArity) {
603
return new ArityException(expectedArity, actualArity);
604
}
605
606
private final int expectedArity;
607
private final int actualArity;
608
609
private ArityException(int expectedArity, int actualArity) {
610
super("Expected " + expectedArity + " arguments but got " + actualArity);
611
this.expectedArity = expectedArity;
612
this.actualArity = actualArity;
613
}
614
615
/**
616
* Get expected arity
617
* @return Expected number of arguments
618
*/
619
public int getExpectedArity() {
620
return expectedArity;
621
}
622
623
/**
624
* Get actual arity
625
* @return Actual number of arguments
626
*/
627
public int getActualArity() {
628
return actualArity;
629
}
630
}
631
632
/**
633
* Exception for unsupported type conversions
634
*/
635
public final class UnsupportedTypeException extends InteropException {
636
637
/**
638
* Create exception
639
* @param suppliedValues Values that caused the error
640
* @return New exception instance
641
*/
642
public static UnsupportedTypeException create(Object[] suppliedValues) {
643
return new UnsupportedTypeException(suppliedValues);
644
}
645
646
/**
647
* Create exception with message
648
* @param suppliedValues Values that caused the error
649
* @param message Error message
650
* @return New exception instance
651
*/
652
public static UnsupportedTypeException create(Object[] suppliedValues, String message) {
653
return new UnsupportedTypeException(suppliedValues, message);
654
}
655
656
private final Object[] suppliedValues;
657
658
private UnsupportedTypeException(Object[] suppliedValues) {
659
super("Unsupported type");
660
this.suppliedValues = suppliedValues;
661
}
662
663
private UnsupportedTypeException(Object[] suppliedValues, String message) {
664
super(message);
665
this.suppliedValues = suppliedValues;
666
}
667
668
/**
669
* Get supplied values
670
* @return Array of supplied values
671
*/
672
public Object[] getSuppliedValues() {
673
return suppliedValues;
674
}
675
}
676
677
/**
678
* Exception for unknown identifiers/members
679
*/
680
public final class UnknownIdentifierException extends InteropException {
681
682
/**
683
* Create exception
684
* @param unknownIdentifier Unknown identifier
685
* @return New exception instance
686
*/
687
public static UnknownIdentifierException create(String unknownIdentifier) {
688
return new UnknownIdentifierException(unknownIdentifier);
689
}
690
691
private final String unknownIdentifier;
692
693
private UnknownIdentifierException(String unknownIdentifier) {
694
super("Unknown identifier: " + unknownIdentifier);
695
this.unknownIdentifier = unknownIdentifier;
696
}
697
698
/**
699
* Get unknown identifier
700
* @return Unknown identifier string
701
*/
702
public String getUnknownIdentifier() {
703
return unknownIdentifier;
704
}
705
}
706
707
/**
708
* Exception for invalid array indices
709
*/
710
public final class InvalidArrayIndexException extends InteropException {
711
712
/**
713
* Create exception
714
* @param invalidIndex Invalid index value
715
* @return New exception instance
716
*/
717
public static InvalidArrayIndexException create(long invalidIndex) {
718
return new InvalidArrayIndexException(invalidIndex);
719
}
720
721
private final long invalidIndex;
722
723
private InvalidArrayIndexException(long invalidIndex) {
724
super("Invalid array index: " + invalidIndex);
725
this.invalidIndex = invalidIndex;
726
}
727
728
/**
729
* Get invalid index
730
* @return Invalid index value
731
*/
732
public long getInvalidIndex() {
733
return invalidIndex;
734
}
735
}
736
737
/**
738
* Exception for iterator exhaustion
739
*/
740
public final class StopIterationException extends InteropException {
741
742
/**
743
* Create exception
744
* @return New exception instance
745
*/
746
public static StopIterationException create() {
747
return new StopIterationException();
748
}
749
750
private StopIterationException() {
751
super("Iterator exhausted");
752
}
753
}
754
```
755
756
### Exception Type Classification
757
758
Enumeration for categorizing interop exceptions.
759
760
```java { .api }
761
/**
762
* Categories of interop exceptions
763
*/
764
public enum ExceptionType {
765
766
/**
767
* Runtime error in guest language
768
*/
769
RUNTIME_ERROR,
770
771
/**
772
* Parsing error in guest language
773
*/
774
PARSE_ERROR,
775
776
/**
777
* Exit request from guest language
778
*/
779
EXIT,
780
781
/**
782
* Interrupt signal
783
*/
784
INTERRUPT
785
}
786
```
787
788
### Iterator Support
789
790
Classes for cross-language iteration support.
791
792
```java { .api }
793
/**
794
* Iterator for arrays in interop contexts
795
*/
796
public final class ArrayIterator implements TruffleObject {
797
798
/**
799
* Create array iterator
800
* @param array Array to iterate
801
* @return ArrayIterator instance
802
*/
803
public static ArrayIterator create(Object array) {
804
return new ArrayIterator(array);
805
}
806
807
private ArrayIterator(Object array) {
808
// Implementation details
809
}
810
}
811
812
/**
813
* Iterator for hash-like objects in interop contexts
814
*/
815
public final class HashIterator implements TruffleObject {
816
817
/**
818
* Create hash iterator
819
* @param hash Hash object to iterate
820
* @return HashIterator instance
821
*/
822
public static HashIterator create(Object hash) {
823
return new HashIterator(hash);
824
}
825
826
private HashIterator(Object hash) {
827
// Implementation details
828
}
829
}
830
```
831
832
## Types
833
834
### Library System Types
835
836
```java { .api }
837
/**
838
* Base class for all Truffle libraries
839
*/
840
public abstract class Library extends Node {
841
842
/**
843
* Check if library accepts receiver
844
* @param receiver Object to check
845
* @return true if accepts
846
*/
847
public boolean accepts(Object receiver) {
848
return true;
849
}
850
}
851
852
/**
853
* Factory for library instances
854
*/
855
public abstract class LibraryFactory<T extends Library> {
856
857
/**
858
* Get uncached library instance
859
* @return Uncached library
860
*/
861
public abstract T getUncached();
862
863
/**
864
* Get uncached library for specific receiver
865
* @param receiver Target receiver
866
* @return Uncached library
867
*/
868
public abstract T getUncached(Object receiver);
869
870
/**
871
* Create cached library
872
* @param receiver Target receiver
873
* @return Cached library
874
*/
875
public abstract T create(Object receiver);
876
}
877
878
/**
879
* Message representation for library operations
880
*/
881
public abstract class Message {
882
883
/**
884
* Get message name
885
* @return Message name
886
*/
887
public abstract String getSimpleName();
888
889
/**
890
* Get qualified message name
891
* @return Qualified name
892
*/
893
public abstract String getQualifiedName();
894
}
895
```