Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

type templates

4.0.0

A library for defining and expanding templated functions

About Type-Templates

This library allows you to define types and "template functions" that can be expanded into various type-specialised versions to eliminate runtime dispatch overhead. It was specifically designed to implement low-level numerical data types and functionality.

How To

First, let's define a meta-type that can instantiate structure types. For an example, let's implement 3-dimensional vectors, which can hold different element types.

(define-template-type vec (element-type)
    (compose-name NIL element-type 'vec)
  (field (compose-name NIL element-type 'vec '-x)
         :type element-type :alias (:x))
  (field (compose-name NIL element-type 'vec '-y)
         :type element-type :alias (:y))
  (field (compose-name NIL element-type 'vec '-z)
         :type element-type :alias (:z)))

This creates a vec-type meta-type that describes how a vec type is created. Now let's instantiate it:

(define-vec single-float)
(define-vec double-float)
(define-vec fixnum)

We should now have the structure types single-float-vec, double-float-vec, and fixnum-vec, each with their own field accessors and direct constructors. To present an easier way for users to access the x, y and z slots of the vectors, let's create a dispatch function that'll call the specific slot accessor depending on the argument type.

(define-type-dispatch x (vec)
  ((single-float-vec) single-float (single-float-vec-x vec))
  ((double-float-vec) double-float (double-float-vec-x vec))
  ((fixnum-vec) fixnum (fixnum-vec-x vec)))

This will create a function x as well as internal compiler structures to eliminate the runtime dispatch if the types are known ahead. However, you may notice that manually listing the cases like this is rather tedious. Let's create a macro to emit the type dispatcher cases for us.

(defmacro define-slot-reader (slot)
  `(define-type-dispatch ,slot (vec)
     ,@(loop for type in (instances 'vec-type)
             collect `((,(lisp-type type)) ,(place-type type slot)
                       ,(place-form type slot 'vec)))))

This macro goes through all type instances of our meta-type and emits a dispatch matching that type, with the slot's value type as the return type, and the reader form for the vec variable to read out the actual value. If you expand (define-slot-reader x) you should get the same as we manually wrote above.

Because defining a slot dispatcher is such a common problem, you can also just use define-slot-accessor, which will also take care of defining the corresponding writer function.

(define-slot-accessor vec-type x x)

You can see now how this library allows you to reason about structure types and automatically compute a lot more information. To illustrate this even better, let's define a template function that'll implement the dot product.

(define-template dot element-type (a b)
  (let ((type (type-instance 'vec-type element-type)))
    `((declare (type ,(lisp-type type) a b)
               (return-type ,element-type)
               inline)
      (+ ,@(loop for slot in (slots type)
                 collect `(* ,(place-form type slot a) ,(place-form type slot b)))))))

Here we make use of the slot iteration, so conceivably the number of slots could also be made variable between vec-type instances, and this template would still operate correctly.

Also notable are that the additional declarations: return-type lets you specify the return type of the resulting function the template generates, and inline lets you specify that the function should be declared inline.

To now instantiate the template into actual function definitions, we could simply repeat define-dot for every element type we have, or we could do it like this:

(do-type-combinations vec-type define-dot)

This will expand into a call to define-dot for all template arguments that were used to instantiate a vec-type. The names of the functions will follow the scheme of dot/single-float, dot/double-float, etc.

We'll now again want to define a dispatcher function as an easy entry point for the user. For template-defined functions however we can make use of another shorthand:

(define-templated-dispatch dot (a b)
  ((vec-type 0) dot))

The templated dispatch macro will notice the meta-type, and automatically expand it into all concrete type instances, appending the template arguments to the template name to reach the correct specific version of the template. The 0 here means that the second argument type should be the same as the first, meaning only (single-float-vec single-float-vec), etc. will get a branch, but not (single-float-vec fixnum-vec).

With this you should have a broad overview of how to use the template system. Please refer to the individual functions used in the tutorial for further information on their capabilities.

System Information

4.0.0
Yukari Hafner
zlib

Definition Index

  • ORG.SHIRAKUMO.TYPE-TEMPLATES

      No documentation provided.
      • EXTERNAL CONDITION

        NO-SUCH-SLOT

            Source
            Error signalled when trying to fetch a slot that does not exist.
            
            See SLOT
          • EXTERNAL CONDITION

            TEMPLATE-UNFULFILLABLE

                Source
                Error signalled to notify that the template cannot be expanded for the given arguments.
                
                This is also available as a local function of the same name within
                DEFINE-TEMPLATE, to allow you to easily signal the condition.
                
                See DEFINE-TEMPLATE
              • EXTERNAL FUNCTION

                COMPOSE-NAME

                  • SEPARATOR
                  • &REST
                  • PARTS
                  Source
                  Compose a symbol out of parts.
                  
                  The symbol will be interned in the current package.
                  Separator should be a string designator that will be injected between
                  each part. Each part otherwise is added to the symbol name via
                  PRINC-TO-STRING.
                  
                  See CL:*PACKAGE*
                  See FORMAT-NAME
                • EXTERNAL FUNCTION

                  ENUMERATE-COMBINATIONS

                    • &REST
                    • COMBINATIONS
                    Source
                    Returns a list of all possible permutations of the given sets of items.
                    
                    Eg: (enumerate-combinations '(a b) '(1 2))
                      => ((a 1) (a 2) (b 1) (b 2))
                  • EXTERNAL FUNCTION

                    FORMAT-NAME

                      • FORMAT
                      • &REST
                      • ARGS
                      Source
                      Format a new symbol.
                      
                      The symbol will be interned in the current package.
                      The name is case-shuffled to the current readtable case after
                      formatting.
                      
                      See CL:*PACKAGE*
                      See CL:FORMAT
                      See COMPOSE-NAME
                    • EXTERNAL GENERIC-FUNCTION

                      ACCESSOR

                        • OBJECT
                        Returns the name of the accessor function for the slot.
                        
                        See SLOT (type)
                      • EXTERNAL GENERIC-FUNCTION

                        COMPUTE-TYPE-INSTANCE-DEFINITION

                          • TEMPLATE-TYPE
                          Source
                          Computes the form used to define a type instance of the template type.
                          
                          Users may add methods to this that include the results of
                          CALL-NEXT-METHOD in their return value, in order to append extra
                          definitions, such as for PRINT-OBJECT.
                          
                          See TEMPLATE-TYPE (type)
                        • EXTERNAL GENERIC-FUNCTION

                          (SETF INSTANCES)

                            • NEW-VALUE
                            • OBJECT
                            No documentation provided.
                          • EXTERNAL GENERIC-FUNCTION

                            NAMES

                              • OBJECT
                              Returns the list of alternate names for the slot.
                              
                              See SLOT (type)
                            • EXTERNAL GENERIC-FUNCTION

                              PLACE

                                • TEMPLATE-TYPE
                                • QUALIFIER
                                Source
                                Returns the name of the place for the given slot.
                                
                                QUALIFIER can either be a SLOT instance or the name of a slot on the
                                TEMPLATE-TYPE.
                                
                                See SLOT
                                See PLACE-FORM
                                See TEMPLATE-TYPE (type)
                              • EXTERNAL GENERIC-FUNCTION

                                PLACE-FORM

                                  • TEMPLATE-TYPE
                                  • QUALIFIER
                                  • VAR
                                  Source
                                  Returns an accessor form of the place for the given slot.
                                  
                                  This form can be used to read or SETF the value off the slot on the
                                  instance bound to the symbol passed in VAR.
                                  
                                  See SLOT
                                  See PLACE
                                  See TEMPLATE-TYPE (type)
                                • EXTERNAL GENERIC-FUNCTION

                                  READ-ONLY

                                    • OBJECT
                                    Returns true if the slot can only be read, but not set.
                                    
                                    See SLOT (type)
                                  • EXTERNAL GENERIC-FUNCTION

                                    TYPE-INSTANCE

                                      • BASE-TYPE
                                      • &REST
                                      • TEMPLATE-ARGS
                                      Source
                                      Returns an instance of the given template type that fulfils the given template arguments.
                                      
                                      If no such instance exists, an error of type NO-SUCH-INSTANCE is
                                      signalled.
                                      
                                      See NO-SUCH-INSTANCE
                                      See TEMPLATE-TYPE (type)
                                    • EXTERNAL GENERIC-FUNCTION

                                      VALUE

                                        • OBJECT
                                        Returns the constant value form for the slot.
                                        
                                        If the slot is realised and does not have a constant value, an error
                                        is signalled.
                                        
                                        See SLOT (type)
                                        See REALIZED-SLOT-P
                                      • EXTERNAL MACRO

                                        DEFINE-ALIAS

                                          • FUN
                                          • ARGS
                                          • &BODY
                                          • EXPANSION
                                          Source
                                          Define a simple alias function.
                                          
                                          EXPANSION should evaluate to a form that is used in the function
                                          body. This is similar to defining a compiler-macro, except that it
                                          tries to automatically define both a compiler macro and a regular
                                          function definition at once.
                                        • EXTERNAL MACRO

                                          DEFINE-DEPENDENT-DISPATCH-TYPE

                                            • NAME
                                              • TYPE-LIST
                                              • I
                                              • &REST
                                              • ARGS
                                            • &BODY
                                            • BODY
                                            Source
                                            Defines a function that can be used to compute more complex dependent types in templated dispatch function definitions.
                                            
                                            TYPE-LIST is bound to the list of ARGTYPEs in the expansion. I is
                                            bound to the index of the current dependent dispatch type to
                                            expand. ARGS are bound to the respective arguments of the call.
                                            
                                            BODY should return a concrete type to use in place of the dependent
                                            type expression, or NIL if there is no dependent type and the
                                            expansion should be eliminated.
                                            
                                            See DEFINE-TEMPLATED-DISPATCH
                                          • EXTERNAL MACRO

                                            DEFINE-TEMPLATE

                                              • NAME
                                              • &REST
                                              • ARGS
                                              Source
                                              Define a new template function.
                                              
                                              NAME will be used as the prefix for all emitted template instances.
                                              NAME will be concatenated together with DEFINE- to name the macro that
                                              is used to emit template instances.
                                              
                                              The structure of a DEFINE-TEMPLATE use should be as follows:
                                              
                                                (define-template NAME TEMPLATE-ARGUMENT+ INSTANCE-LAMBDA-LIST BODY*)
                                              
                                              TEMPLATE-ARGUMENTS should be symbols naming the variables bound to the
                                              template arguments during BODY. INSTANCE-LAMBDA-LIST should be the
                                              lambda-list of an emitted function instance. BODY should be any number
                                              of forms which return a list of body forms to emit into the resulting
                                              function instance.
                                              
                                              The first of those forms may be a DECLARE expression, with the
                                              following special declarations:
                                              
                                                TYPE         --- Used to declare types of the function instance's
                                                  arguments. Together with the RETURN-TYPE these will be used to
                                                  create an FTYPE declaration for the function instance.
                                                RETURN-TYPE  --- The function instance will declare this as the type
                                                  of the return value.
                                                INLINE       --- The function instance will be declared inline
                                              
                                              The resulting definition macro will take the template arguments as
                                              arguments as well as an optional name for the resulting function
                                              instance. If no name is given, the name is automatically composed out
                                              off the template name and the template arguments, separated by a
                                              slash.
                                              
                                              A local function is bound during evaluation of BODY named
                                              TEMPLATE-UNFULFILLABLE. When called, a TEMPLATE-UNFULFILLABLE error is
                                              signalled to signify that the given template arguments are not a valid
                                              combination.
                                              
                                              See COMPOSE-NAME
                                              See DEFINE-TEMPLATED-DISPATCH
                                            • EXTERNAL MACRO

                                              DEFINE-TEMPLATE-TYPE

                                                • NAME
                                                • TEMPLATE-ARGS
                                                • NAME-CONSTRUCTOR
                                                • &BODY
                                                • BODY
                                                Source
                                                Define a new template type.
                                                
                                                NAME will be concatenated together with -TYPE and interned into the
                                                local package to produce the name of the template type.
                                                NAME will also be concatenated together with DEFINE- to name a macro
                                                used to define instances of the template type.
                                                
                                                TEMPLATE-ARGS should be a list of arguments the template accepts.
                                                NAME-CONSTRUCTOR should be a form that, when evaluated, returns a
                                                symbol naming the type instance for the given template arguments.
                                                
                                                BODY may accept the following keyword arguments:
                                                :INCLUDE  --- Specify another template-type to use as the supertype.
                                                   This is done via a list that should be composed out of the
                                                   template-type name and the template arguments to supply for that
                                                   supertype. You may use the name of local template arguments.
                                                
                                                The rest of the BODY should be a number of forms. The forms are
                                                evaluated in an environment where the FIELD function is bound and
                                                should use it to emit information about the slots on the resulting
                                                type instance.
                                                
                                                See FIELD
                                                See TEMPLATE-TYPE (type)
                                                See DEFINE-TYPE-INSTANCE
                                              • EXTERNAL MACRO

                                                DEFINE-TEMPLATED-DISPATCH

                                                  • NAME
                                                  • ARGS
                                                  • &BODY
                                                  • BODY
                                                  Source
                                                  Define a dispatcher function using type template information.
                                                  
                                                  BODY accepts the following keyword arguments:
                                                  :IGNORE-TEMPLATE-TYPES --- A list of template type names that should
                                                    be ignored for the resulting template invocation's template
                                                    arguments.
                                                  
                                                  The rest of the body should have the following structure:
                                                  
                                                    EXPANSIONS   ::= EXPANSION*
                                                    EXPANSION    ::= ((ARGTYPE*) TEMPLATE TEMPLATE-ARG*)
                                                                   | ((ARGTYPE*) (TEMPLATE TEMPLATE-ARG*) ARG*)
                                                    ARGTYPE      ::= TEMPLATE-TYPE
                                                                   | REFERENCE
                                                                   | DEPENDENT
                                                                   | REF-ARGUMENT
                                                    TEMPLATE-TYPE --- The name of a template-type, for each of the
                                                      instances of which this expansion will be instantiated.
                                                    REFERENCE     --- A number duplicating the concrete type at that
                                                      position of the ARGTYPE list.
                                                    DEPENDENT     ::= #'(DEPENDENT-NAME ARG*)
                                                    ALIAS-NAME    --- The name of a dependent dispatch type function.
                                                    REF-ARGUMENT  --- A vector of two elements, the first being the
                                                      position of the template type instance to reference in the ARGTYPE
                                                      list, and the second being the number of the template argument of
                                                      that template type instance to use.
                                                    TEMPLATE      --- The name of the template to call.
                                                    TEMPLATE-ARG  --- Additional template arguments that will be
                                                      prepended before the combined template arguments of the
                                                      TEMPLATE-TYPE instance expanded for this EXPANSION. Note that this
                                                      includes *all* template arguments of all template-type instances
                                                      in the ARGTYPES list that aren't excluded via the
                                                      IGNORE-TEMPLATE-TYPES option above.
                                                    ARG           --- An argument to pass to the function call.
                                                  
                                                  The effective function call will be computed based on the template
                                                  name and the template arguments, inserting a slash between each as per
                                                  the standard naming convention.
                                                  
                                                  See DEFINE-TEMPLATE
                                                  See DEFINE-TYPE-DISPATCH
                                                  See DEFINE-DEPENDENT-DISPATCH-TYPE
                                                  See TEMPLATE-TYPE (type)
                                                • EXTERNAL MACRO

                                                  DEFINE-TYPE-ALIAS

                                                    • NAME
                                                    • &REST
                                                    • TYPES
                                                    Source
                                                    Define an alias for a number of template type instances.
                                                    
                                                    NAME will name a lisp-type of NAME.
                                                    NAME will also be concatenated together with -TYPE to name a
                                                    TEMPLATE-TYPE that holds the type instances.
                                                    
                                                    See TYPE-ALIAS
                                                  • EXTERNAL MACRO

                                                    DEFINE-TYPE-DISPATCH

                                                      • NAME
                                                      • ARGS
                                                      • &BODY
                                                      • EXPANSIONS
                                                      Source
                                                      Define a dispatcher function.
                                                      
                                                      EXPANSIONS should have the following structure:
                                                      
                                                        EXPANSIONS ::= EXPANSION*
                                                        EXPANSION  ::= ((ARGTYPE*) RETTYPE EXPANSION)
                                                        ARGTYPE    --- A lisp-type for the corresponding lambda-list
                                                          variable. If the number of argtypes is shorter than the number of
                                                          variables in the lambda-list, the remainder are automatically
                                                          bound to NULL.
                                                        RETTYPE    --- A lisp-type for the type of the value returned in
                                                          this expansion.
                                                        EXPANSION  --- A form that the type dispatcher will expand into
                                                          should this branch of argument types match.
                                                      
                                                      See DEFINE-TEMPLATED-DISPATCH
                                                    • EXTERNAL MACRO

                                                      DEFINE-TYPE-WITH-CONVERTER

                                                        • NAME
                                                        • BASE-TYPE
                                                          • VALUE
                                                        • &BODY
                                                        • CONVERSION
                                                        Source
                                                        Define an alias for a longer lisp type with a conversion function to coerce values to fit within that type.
                                                        
                                                        BASE-TYPE should be the type this is an alias for, and CONVERSION the
                                                        body of the function used to coerce any value to the requested type.
                                                      • EXTERNAL MACRO

                                                        DO-TYPE-COMBINATIONS

                                                          • TYPE
                                                          • TEMPLATE
                                                          • &REST
                                                          • OTHER-TEMPLATE-ARGS
                                                          Source
                                                          Expand all possible type arguments for instances of the given template-type.
                                                          
                                                          OTHER-TEMPLATE-ARGS can be further permutation lists that precede the
                                                          arguments of the template type instances.
                                                          
                                                          This is useful if the template accepts the same template arguments as
                                                          the template type.
                                                          
                                                          See TEMPLATE-TYPE (type)
                                                          See DO-COMBINATIONS