Re: Unportable ways to add non-trivial type constraints.

Vasily Postnicov <[email protected]> Mon, 3 Feb 2025 12:49:15 +0000
Newsgroups gmane.lisp.steel-bank.general
Message-ID <CADnZ6BmgXyRTdwOm_qsNQ-DyHKAX4c32usi7KVi=XmTPMVuATw@mail.gmail.com>
Thanks! No luck, I guess.

пн, 3 февр. 2025 г. в 12:43, Stas Boukarev <[email protected]>:

> Constraint propagation is changing all the time, it's going to be not
> just non-portable but non-portable between different versions. And
> possibly in subtle ways where you can't catch it.
> So, don't do this.
>
> On Mon, Feb 3, 2025 at 3:40 PM Vasily Postnicov <[email protected]>
> wrote:
> >
> > Hi! Suppose I want to write a specialized eql comparison function which
> has a type a -> a -> BOOLEAN (i.e. types of its arguments must be equal).
> >
> > There is no portable way to specify such a type in Common Lisp. But, in
> src/compiler/fun-info.lisp I found this:
> >
> >   ;; If true, the function can add flow-sensitive type information
> >   ;; about the state of the world after its execution. The COMBINATION
> >   ;; node is passed as an argument, along with the current set of
> >   ;; active constraints for the block.  The function returns a
> >   ;; sequence of constraints; a constraint is a triplet of a
> >   ;; constraint kind (a symbol, see (defstruct (constraint ...)) in
> >   ;; constraint.lisp) and arguments, either LVARs, LAMBDA-VARs, or
> >   ;; CTYPEs.  If any of these arguments is NIL, the constraint is
> >   ;; skipped. This simplifies integration with OK-LVAR-LAMBDA-VAR,
> >   ;; which maps LVARs to LAMBDA-VARs.  An optional fourth value in
> >   ;; each constraint flips the meaning of the constraint if it is
> >   ;; non-NIL.
> >   (constraint-propagate nil :type (or function null))
> >
> > So I thought this is what I need and tried the following:
> > (defpackage foo
> >   (:use #:cl)
> >   (:export #:foo #:bar #:baz))
> > (in-package :foo)
> >
> > (sb-c:defknown (foo) (t t) boolean
> >     (sb-c:movable sb-c:flushable sb-c:foldable))
> >
> > (defun foo (x y)
> >   (eql x y))
> >
> > (sb-c:defoptimizer (foo sb-c::constraint-propagate) ((x y) node gen)
> >   (let ((type-x (sb-c::lvar-type x))
> >         (type-y (sb-c::lvar-type y))
> >         (var-x  (sb-c::ok-lvar-lambda-var x gen))
> >         (var-y  (sb-c::ok-lvar-lambda-var y gen)))
> >     (when (and var-x var-y)
> >       (print
> >        (list
> >         (list 'typep var-x type-y)
> >         (list 'typep var-y type-x))))))
> >
> > (declaim (ftype (function (integer string) (values boolean &optional))
> bar))
> > (defun bar (x y)
> >   (foo x y))
> >
> > When compiling bar I have this printed:
> > ((TYPEP
> >   #<SB-C::LAMBDA-VAR
> >     :%SOURCE-NAME X
> >     :TYPE #<SB-KERNEL:NUMERIC-TYPE INTEGER>
> >     :WHERE-FROM :DECLARED {1111651493}>
> >   #<SB-KERNEL:UNION-TYPE STRING> T)
> >  (TYPEP
> >   #<SB-C::LAMBDA-VAR
> >     :%SOURCE-NAME Y
> >     :TYPE #<SB-KERNEL:UNION-TYPE STRING>
> >     :WHERE-FROM :DECLARED {1111651553}>
> >   #<SB-KERNEL:NUMERIC-TYPE INTEGER> T))
> > but no compile-time or run-time when I use bar:
> >
> > CL-USER> (foo:baz 543 "dsd")
> > NIL
> >
> > Can you please give me a hint how type information about arguments can
> be added to a function? My goal is to learn how I can write a bit
> type-safer code and non-portability does not bother me.
> >
> > Also, if there are any publications about how SBCL handles types, please
> tell me.
> > _______________________________________________
> > Sbcl-help mailing list
> > [email protected]
> > https://lists.sourceforge.net/lists/listinfo/sbcl-help
>

_______________________________________________
Sbcl-help mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/sbcl-help