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