Annotation Interface GenerateLibrary


@Retention(RUNTIME) @Target(TYPE) public @interface GenerateLibrary
Libraries are specified with public and abstract Java classes that extend the Library class and are annotated by @GenerateLibrary. A library consists of a set of messages, that are specified using public Java methods. The methods may be abstract or use default implementations. The first parameter of every library message is the receiver parameter, which must be a non-primitive type and consistent across all messages of a library. There are no restrictions on the return type or argument types of a message. Every method that specifies a message must have a name that is unique per library. Final or private methods will always be ignored by the generator. Parameter type overloading is currently not supported for messages, therefore every public method must have a unique name per library. Generic type arguments local to messages are generally supported, but generic type arguments on the library type are not yet supported.

Basic Usage

The following example specifies a basic library for arrays:
 @GenerateLibrary
 public abstract class ArrayLibrary extends Library {

     public boolean isArray(Object receiver) {
         return false;
     }

     public abstract int read(Object receiver, int index);
 }
 
Messages that are not implemented and have no default implementation throw an AbstractMethodError. The GenerateLibrary.Abstract annotation can be used, to provide a default implementation for receiver types but at the same time make the message abstract.

A library class may also specify default exports that can be used to dispatch to receiver types that don't export the library. Since the receiver type for default exports can be specified explicitly, it can be used to provide a default implementation for receiver types of third parties or the JDK. For example the Truffle interop library has default exports for most Number types, String and Boolean type.

In order to enable AOT generation for a a library annotate the class with GenerateAOT and enable exports to be used for AOT by setting ExportLibrary.useForAOT() to true.

Deprecating Messages

If a library message gets deprecated using the Deprecated annotation then all exports will get a deprecation warning. This can be useful to evolve libraries over time in a compatible way.

Sometimes it is needed to remove or modify types of parameters as part of evolution. In this case it is possible to declare multiple overloads of the same library message where all but one method are annotated with Deprecated. The non-deprecated method must use more generic or the same parameter types. For example, this allows to evolve message with parameter String to evolve into Object. It is also possible to add or remove parameter types in the non-deprecated method. These restrictions are necessary in order to ensure that exports of that message never export the new overload after recompilation unless the parameter types were updated.

Since:
19.0
See Also:
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static @interface 
    Makes a library message abstract, but allows to keep a default implementation.
    static @interface 
    Specifies library implementations provided by default as a fallback.
  • Optional Element Summary

    Optional Elements
    Modifier and Type
    Optional Element
    Description
    Class<? extends Library>
    Specifies an assertion wrapper class that can be used to verify pre and post conditions of a library.
    boolean
    Allows the library to lookup additional default exports using a service provider interface.
    boolean
    Allows the use of DynamicDispatchLibrary with this library.
    boolean
    Enables push and pop of the encapsulating node when a library transitions from cached to uncached.
    Restricts the receiver type for exports that implement this library.
  • Element Details

    • assertions

      Class<? extends Library> assertions
      Specifies an assertion wrapper class that can be used to verify pre and post conditions of a library. Assertion wrappers are only inserted when assertions (-ea) are enabled. It is required that assertion wrappers don't introduce additional side-effects and call the delegate methods exactly once. If assertions are disabled no library wrapper will be inserted therefore not performing any checks when library messages are invoked.

      Example Usage:

       @GenerateLibrary(assertions = ArrayAssertions.class)
       public abstract class ArrayLibrary extends Library {
      
           public boolean isArray(Object receiver) {
               return false;
           }
      
           public int read(Object receiver, int index) {
               throw new UnsupportedOperationException();
           }
      
           static class ArrayAssertions extends ArrayLibrary {
      
               @Child private ArrayLibrary delegate;
      
               ArrayAssertions(ArrayLibrary delegate) {
                   this.delegate = delegate;
               }
      
               @Override
               public boolean isArray(Object receiver) {
                   return delegate.isArray(receiver);
               }
      
               @Override
               public int read(Object receiver, int index) {
                   int result = super.read(receiver, index);
                   assert delegate.isArray(receiver) : "if a read was successful the receiver must be an array";
                   return result;
               }
      
               @Override
               public boolean accepts(Object receiver) {
                   return delegate.accepts(receiver);
               }
           }
       }
      
       
      Since:
      19.0
      Default:
      com.oracle.truffle.api.library.Library.class
    • receiverType

      Class<?> receiverType
      Restricts the receiver type for exports that implement this library. This allows to have different receiver type in message methods, but require export receiver types to implement or extend a declared class. Default exports are not affected by this restriction and can therefore export the library for any receiver type the message methods first parameter is compatible with.
      Since:
      19.0
      Default:
      java.lang.Object.class
    • defaultExportLookupEnabled

      boolean defaultExportLookupEnabled
      Allows the library to lookup additional default exports using a service provider interface. Exports for this library with explicit receiver type will automatically be interpreted as additional default exports. External default exports may specify with the priority whether they are looked up before or after existing default exports specified for the library. Default exports always have a lower priority than explicit exports on the receiver type or exports that use dynamic dispatch.
      Since:
      20.1
      See Also:
      Default:
      false
    • dynamicDispatchEnabled

      boolean dynamicDispatchEnabled
      Allows the use of DynamicDispatchLibrary with this library. By default dynamic dispatch is enabled. If this flag is set to false then the dispatch method will not be used for this library. Only default exports and exports declared with the receiver type will be used instead for this library.
      Since:
      20.1
      Default:
      true
    • pushEncapsulatingNode

      boolean pushEncapsulatingNode
      Enables push and pop of the encapsulating node when a library transitions from cached to uncached. The current encapsulating node is needed for correct stack trace location when library exports perform guest language calls. If a library is known to never need correct stack trace information, e.g. if all exports are known to not perform guest language calls, then pushing and popping of encapsulating nodes can be disabled. By default pushing and popping of encapsulating nodes is enabled.
      Since:
      20.3
      See Also:
      Default:
      true