All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.oracle.truffle.api.library.GenerateLibrary Maven / Gradle / Ivy

Go to download

Truffle is a multi-language framework for executing dynamic languages that achieves high performance when combined with Graal.

There is a newer version: 24.1.1
Show newest version
/*
 * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * The Universal Permissive License (UPL), Version 1.0
 *
 * Subject to the condition set forth below, permission is hereby granted to any
 * person obtaining a copy of this software, associated documentation and/or
 * data (collectively the "Software"), free of charge and under any and all
 * copyright rights in the Software, and any and all patent rights owned or
 * freely licensable by each licensor hereunder covering either (i) the
 * unmodified Software as contributed to or provided by such licensor, or (ii)
 * the Larger Works (as defined below), to deal in both
 *
 * (a) the Software, and
 *
 * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
 * one is included with the Software each a "Larger Work" to which the Software
 * is contributed by such licensors),
 *
 * without restriction, including without limitation the rights to copy, create
 * derivative works of, display, perform, and distribute the Software and make,
 * use, sell, offer for sale, import, export, have made, and have sold the
 * Software and the Larger Work(s), and to sublicense the foregoing rights on
 * either these or other terms.
 *
 * This license is subject to the following condition:
 *
 * The above copyright notice and either this complete permission notice or at a
 * minimum a reference to the UPL must be included in all copies or substantial
 * portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.oracle.truffle.api.library;

import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import com.oracle.truffle.api.dsl.GenerateAOT;
import com.oracle.truffle.api.nodes.EncapsulatingNodeReference;

/**
 * Libraries are specified with public and abstract Java classes that
 * extend the {@linkplain 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 * {@link AbstractMethodError}. The {@link 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 {@link DefaultExport 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 {@link Number} types, {@link String} and {@link Boolean} type. *

* In order to enable AOT generation for a a library annotate the class with {@link GenerateAOT} and * enable exports to be used for AOT by setting {@link ExportLibrary#useForAOT()} to * true. * * @see DefaultExport to specify default exports. * @see Abstract to make messages abstract if they have a default implemetnation * @since 19.0 */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) public @interface GenerateLibrary { /** * 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 */ Class assertions() default Library.class; /** * 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 */ Class receiverType() default Object.class; /** * * Specifies {@link GenerateLibrary library} implementations provided by default as a fallback. * May only be used on classes annotated with Library. * * @since 19.0 */ @Retention(RetentionPolicy.CLASS) @Target({ElementType.TYPE}) @Repeatable(DefaultExport.Repeat.class) public @interface DefaultExport { /** * @since 19.0 */ Class value(); /** * @since 19.0 */ @Retention(RetentionPolicy.CLASS) @Target({ElementType.TYPE}) public @interface Repeat { /** * @since 19.0 */ DefaultExport[] value(); } } /** * Makes a library message abstract, but allows to keep a default implementation. By default, * abstract messages throw an {@link AbstractMethodError} if they are not exported for a given * receiver type. To customize this behavior the library message can specify a method body and * annotate it with {@link Abstract} to keep requiring an implementation from exports. *

* For example: * *

     * @GenerateLibrary
     * public abstract class ArrayLibrary extends Library {
     *
     *     @Abstract(ifExported = "read")
     *     public boolean isArray(Object receiver) {
     *         return false;
     *     }
     *
     *     @Abstract(ifExported = "isArray")
     *     public int read(Object receiver, int index) {
     *         throw new UnsupportedOperationException();
     *     }
     * }
     * 
* * In this example a receiver that does not export the ArrayLibrary will return * false for isArray and throw an * {@linkplain UnsupportedOperationException} for read calls. A message may be made * conditionally abstract by specifying the {@link Abstract#ifExported()} attribute. * * @see #ifExported() * @since 19.0 */ @Retention(RetentionPolicy.CLASS) @Target({ElementType.METHOD}) public @interface Abstract { /** * Specifies a message to be abstract only if another message is implemented. Multiple other * messages can be specified. *

* For example: * *

         * @GenerateLibrary
         * public abstract class ArrayLibrary extends Library {
         *
         *     @Abstract(ifExported = "read")
         *     public boolean isArray(Object receiver) {
         *         return false;
         *     }
         *
         *     @Abstract(ifExported = "isArray")
         *     public int read(Object receiver, int index) {
         *         throw new UnsupportedOperationException();
         *     }
         * }
         * 
* * In this example the isArray message only needs to be exported if the read message is * exported and vice-versa. * * @since 19.0 */ String[] ifExported() default {}; } /** * Allows the library to lookup additional default exports using a service provider interface. * {@link ExportLibrary Exports} for this library with explicit receiver type will automatically * be interpreted as additional default exports. External default exports may specify with the * {@link ExportLibrary#priority() 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. * * @see ExportLibrary#priority() * @since 20.1 */ boolean defaultExportLookupEnabled() default false; /** * Allows the use of {@link DynamicDispatchLibrary} with this library. By default dynamic * dispatch is enabled. If this flag is set to false then the * {@link DynamicDispatchLibrary#dispatch(Object) 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 */ boolean dynamicDispatchEnabled() default true; /** * 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. * * @see EncapsulatingNodeReference * @since 20.3 */ boolean pushEncapsulatingNode() default true; }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy