Class ScalarFunctionDescriptor


  • public class ScalarFunctionDescriptor
    extends Object
    Describes an implementation of a function. Instead of directly implementing ScalarValuedFunction, a function can be defined using a ScalarFunctionDescriptor. A definition can be created by using one of the static factory methods provided by this class.

    A ScalarValuedFunction abstractly consists of four pieces:

    • A label identifying the function. This is used in error messages produced by the function.
    • A list of arguments to the function. These include both parameters which remain constant for all evaluations, as well as subexpressions (in the form of functions) which may vary per evaluation.
    • Logic for validating the arguments and determining the result type.
    • Logic for creating an evaluator in the context of a record value.
    Implementations only differ in these particular details. Therefore, a description consisting of this information is sufficient to implement a function.

    This class provides a number of static methods for defining functions by providing a description of the implementation. An evaluator class must be implemented. Any special logic is handled by providing additional classes, though default implementations covering a number of common cases are provided. Some basic type checking logic is provided as well, so that functions which only require simple assignability checks do not require any additional classes beyond the evaluator.

    Typical practice is to wrap the definition of a function with a static method (or methods). The static method(s) can restrict arguments to appropriate types. While the method(s) do not need to validate subexpression arguments (as they lack sufficient context until bound to a record value), they should validate other arguments. When defining a function, simple type bounds checks can be declared on subexpressions. These will be automatically validated by the descriptor at appropriate times. Lists and arrays of subexpressions can only be used in the final argument position. These will be flattened into the argument list for purposes of validation and evaluator construction.

    See Also:
    FunctionEvaluator, FunctionTyper, EvaluatorFactory
    • Method Detail

      • define

        public static ScalarValuedFunction define​(String name,
                                                  ScalarTokenType resultType,
                                                  Class<? extends FunctionEvaluator> evaluator,
                                                  Object... args)
        Defines an instance of a function returning a result of the specified type and using an evaluator of the given class.

        Use this when a function always returns the same type, requires no argument checking beyond the bounds check, and uses the same evaluator regardless of arguments. This describes a large majority of functions; for example, string length always returns an integer, expects its argument is a string, and only needs a single implementation.

        Parameters:
        name - an identifier to associate with the function. This will be used in errors generated during validation of the function.
        resultType - the output type of the function.
        evaluator - the class of the function evaluator to use. This will be invoked reflectively. Refer to ReflectiveFactory for more details on constructor requirements for using this.
        args - the arguments to pass to the evaluator and other associated classes. Subexpressions which have type bounds should be tagged using a ScalarFunctionDescriptor.SubexpressionBound.
        Returns:
        a descriptor object for invoking the defined function
      • define

        public static ScalarValuedFunction define​(String name,
                                                  FunctionTyper typer,
                                                  Class<? extends FunctionEvaluator> evaluator,
                                                  Object... args)
        Defines an instance of a function returning a result using an evaluator of the given class, but with complex type restrictions and/or variable output type.

        Use this when a function always uses the same evaluator, but has special logic for determining the output type or requires checks on subexpressions beyond a simple type bound. This describes the second largest group of functions; for example, value comparisons always return a boolean, but must check that the arguments are of comparable types (with no addition restriction), and can be implemented using a single class.

        Parameters:
        name - an identifier to associate with the function. This will be used in errors generated during validation of the function.
        typer - the typer used to determine the output type of the function based on the provided arguments.
        evaluator - the class of the function evaluator to use. This will be invoked reflectively. Refer to ReflectiveFactory for more details on constructor requirements for using this.
        args - the arguments to pass to the evaluator and other associated classes. Subexpressions which have type bounds should be tagged using a ScalarFunctionDescriptor.SubexpressionBound.
        Returns:
        a descriptor object for invoking the defined function
      • define

        public static ScalarValuedFunction define​(String name,
                                                  ScalarTokenType resultType,
                                                  EvaluatorFactory factory,
                                                  Object... args)
        Defines an instance of a function returning a result of the specified type but needing to choose between possible evaluator implementations.

        Use this when a function always returns the same type and requires no argument checking beyond the bounds check, but requires special logic for determining the evaluator to use.

        Parameters:
        name - an identifier to associate with the function. This will be used in errors generated during validation of the function.
        resultType - the output type of the function
        factory - the factory for constructing the evaluator to use for a function
        args - the arguments to pass to the evaluator and other associated classes. Subexpressions which have type bounds should be tagged using a ScalarFunctionDescriptor.SubexpressionBound.
        Returns:
        a descriptor object for invoking the defined function
      • define

        public static ScalarValuedFunction define​(String name,
                                                  FunctionTyper typer,
                                                  EvaluatorFactory factory,
                                                  Object... args)
        Defines an instance of a function requiring complex logic for determining result type and/or checking function arguments, as well as needing to choose between possible evaluator implementations.

        This provides the maximum flexibility, at the cost of requiring the implementation of two additional classes beyond the function evaluator. An example of such a case is polymorphic addition, which determines its value based on the argument types (automatically widening) and chooses an appropriate evaluator based on the result type.

        Parameters:
        name - an identifier to associate with the function. This will be used in errors generated during validation of the function.
        typer - the typer used to determine the output type of the function based on the provided arguments.
        factory - the factory for constructing the evaluator to use for a function
        args - the arguments to pass to the evaluator and other associated classes. Subexpressions which have type bounds should be tagged using a ScalarFunctionDescriptor.SubexpressionBound.
        Returns:
        a descriptor object for invoking the defined function
      • arg

        public static ScalarFunctionDescriptor.SubexpressionBound arg​(ScalarValuedFunction subexpr,
                                                                      ScalarTokenType type)
        Declares the given subexpression has the specified type bound. If the subexpression fails to be assignable to the specified bound during evaluation of the containing function, an error will be raised.
        Parameters:
        subexpr - the subexpression being bounded
        type - the bound on the subexpression result type
        Returns:
        a type bound to use as a function argument
      • varargs

        public static ScalarFunctionDescriptor.SubexpressionBound varargs​(List<? extends ScalarValuedFunction> subexprs,
                                                                          ScalarTokenType type)
        Declares a variable number of arguments, all having the specified type bound. If any subexpression fails to be assignable to the specified bound during evaluation of the containing function, an error will be raised.

        The list will be flattened into the argument array passed to the evaluator.

        Parameters:
        subexprs - the subexpressions being bounded
        type - the bound on the subexpression result type
        Returns:
        a type bound to use as a function argument
      • getName

        public String getName()
        Gets the label associated with the function. This is the same value which was passed to the define function.
        Returns:
        the name assigned to the function instance