help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: inline function expansion


From: Lynn Winebarger
Subject: Re: inline function expansion
Date: Sun, 28 May 2023 10:12:15 -0400

On Sat, May 27, 2023 at 10:34 AM Lynn Winebarger <owinebar@gmail.com> wrote:
>
> On Sat, May 20, 2023 at 11:48 AM Stefan Monnier
> <monnier@iro.umontreal.ca> wrote:
> > > For my purposes, an "interface" spec is just a list of method and slot
> > > signatures associated to some object, which will be realized by a set
> > > of bindings specified via special forms and bound to some name.
> > > Then a compile-time generic f is a factoring of a regular generic into
> > > a generic function of interface realizations that produces a concrete
> > > runtime function.  I'm thinking to adopt the "place name" technique of
> > > naming the concrete function by the form that created it, ie. \(f\
> > > arg1-iface-realizer\ arg2-iface-realizer\ ...\).  Note the check is
> > > that the realizer provides all the required signatures (a superset),
> > > which is why I refer to it as a "constraint" on the interface
> > > implementation.
> > >
> > > Then the generic method could dispatch on simple wrappers created by
> > > the iface-realizers.  If constructors are invoked at compile time when
> > > they appear in constant expressions and have constant arguments, then
> > > the generic multi-dispatch method specialized on those realizers can
> > > inline the call to the specialized method in the compiler macro, while
> > > a residual generic method could do the same dispatch at run-time.
> > >
> > > But the point is to separate the expression of the algorithm from the
> > > expression of the bindings that are used by the algorithm, without
> > > resorting to either dynamic dispatch tables or ad hoc macros per
> > > algorithm.
> >
> > I'm still lost.  An example might help.
>
> For my purposes, interfaces and realizations of interfaces are just a
> way to specify bindings of symbols in a more structured and
> encapsulated way than raw macros.
> I'm still spit-balling here, but I'm thinking a generic
> compile-time-dispatched (inlineable) "max" might be defined along
> these lines:
>
My intention below is that define-inline-method is like applying the
generic function to the abstract interfaces, producing a function that
consumes the body as an argument.  So maybe there should be a
(define-inline-generic max (< a b))
that creates the dual-definition of max as a (generic) compiler macro
and generic function, with the method specializing max on
"realized-interface" arguments that successfully unify against the
supplied interface spec:
(max <-iface a-iface b-iface) = (lambda (<-realized a-realized
b-realized) ((lambda (a b) ...) (realized-interface-value a)
(realized-interface-value b)))

where "realized-interface-value" removes the wrapper used for
specialization.  Note that it also only does so for "opaque"
arguments, to allow the "<" argument to be treated as a fixed constant
when the call site provides a constant.  This definition should
specialize both the generic compiler macro and the generic function on
realizations of the specified interfaces for the arguments of max.
Technically, we need the following definitions:

;; these should be predefined constants
(define-interface null-interface)
(define-realized-interface null-realized)

In the code below, not specifying an interface for the a and b
arguments is the same as specifying the null-interface.

> ;; ordering interface has two parameters
> (define-interface ordering (bool-T elt-T)
>   ;; return value of `lt' method satisfies bool-T interface
>   (method (bool-T lt) (elt-T a) (elt-T b)))
>
> (define-realized-interface integer-ordering (ordering boolean integer)
>   ;; bind lt method to built-in `<'
>   (method lt <))
>
> (defgeneric max (< a b)
>   "Determine the larger of a and b according to <")
>
> (define-inline-method max ((ordering <) &opaque a b)
>   "Determine the larger of a and b according to ordering <"
>   ;; < is treated syntactically as a dispatcher
>   (if (< lt a b) a b))
>

And this
> ;; because elisp does not allow applications in the operator position
> (define-inlined-method integer-max (max integer-ordering))

should be
(define-inlined-method integer-max (max integer-ordering null-realized
null-realized))

> ;; Alternatively,
> ;; (integer-ordering lt)  reduces at compile time to something like
> ;;  #s(interface-method
> ;;     #s(interface-realization
> ;;        #s(interface ordering boolean integer)
> ;;        <)
> ;;      lt
> ;;      <)
> ;; which `max' is specialized for by define-inline-method above, so
> (defun integer-max (a b)
>   ;; inlined by compile-time dispatch of the max generic method
>   (max (integer-ordering lt) a b))
>
> ;; These should produce t
> (= (max integer-ordering 5 6) (integer-max 5 6))
> (= (max (integer-ordering lt) 5 6) (integer-max 5 6))
> (macroexp-const-p (macroexpand-all '(max (integer-ordering lt) 5 6)))
>


Lynn



reply via email to

[Prev in Thread] Current Thread [Next in Thread]