|
From: Philipp M. <ph...@ma...> - 2024-08-02 12:52:10
|
Review:
I'd like to get a separate set of integers with their own type,
which can be used eg.
- as distinct number type (an integer space for probabilities),
- like a structure or class type (invisibly addressing entries
in a vector, but needing eg. only 24+8 tag bits instead of 64).
Also, subtypes should be possible - I plan for a contrib
that allows to easily define multiple own subclasses by
using a few more tag bits (bits 8 to 15, as 0 to 7 are the widetag).
So, here's what I got so far [1],
with an hour or two thrown in whenever possible.
[[ No worries, that's in _my_ github repo -- it's just that github
uses the original repo as a reference base.
See the first commit in [2], the rest above is trash and debug
stuff. ]]
Please be patient -- I have nearly no idea what I'm doing here.
I mostly add some stuff, fix errors, and loop back until
SBCL compiles again.
The status is that creating, querying, and garbage collecting
such values works as expected, and they're not confused with fixnums:
(assert (not (typep 4 'sb-kernel::udef-inttype)))
; NIL
(assert (not (sb-int:udef-inttype-p 4)))
; NIL
(defvar *x* (make-array 20000
:initial-element (sb-int:make-udef-inttype 541)))
; *X*
(sb-ext:gc)
; NIL
(print (sb-int:udef-inttype-value (aref *x* 0)))
; 541
(print (type-of (aref *x* 0)))
; SB-INT:UDEF-INTTYPE
(print (aref *x* 0))
; #<SB-INT:UDEF-INTTYPE #x21D>
(print (sb-int:udef-inttype-p (aref *x* 0)))
; T
(sb-int:udef-inttype-p
(sb-int:make-udef-inttype 51))
; T
Strangely, ASSERT of the last form thinks otherwise:
(assert
(sb-int:udef-inttype-p
(sb-int:make-udef-inttype 51)))
; The assertion
; (SB-INT:UDEF-INTTYPE-P #1=(SB-INT:MAKE-UDEF-INTTYPE 51)) failed
; with #1# = #<SB-INT:UDEF-INTTYPE #x33>.
; [Condition of type SIMPLE-ERROR]
I guess that's some difference between compiler and interpreter,
but never mind that for now.
The problem I'm facing now, and for which I'd be glad for any help,
is the following dichotomy.
I can use the type in defmethod:
(defmethod my-dispatch ((y t))
:anything)
(defmethod my-dispatch ((x sb-int:udef-inttype))
:udef)
But calling that fails:
(my-dispatch (sb-int:make-udef-inttype 1))))
; The value #<SB-INT:UDEF-INTTYPE #x1> is
; not of type SB-KERNEL:INSTANCE when binding X
; [Condition of type TYPE-ERROR]
The reasons for this error is the generated
(DECLARE (TYPE SB-INT:UDEF-INTTYPE X))
for the defmethod which gets translated to a check for INSTANCE, as per
(sb-int:info :type :builtin 'sb-int:udef-inttype)
; #<SB-KERNEL:NAMED-TYPE SB-KERNEL:INSTANCE>
; T
which, I guess, comes from my src/code/primordial-type.lisp changes:
(frob instance *instance-type*)
(frob funcallable-instance *funcallable-instance-type*)
+ ;; New after sbcl-2.4.7: User-defined integers, to be used in
DEFMETHOD etc.
+ (frob udef-inttype *instance-type*)
;; new in sbcl-1.0.3.3: necessary to act as a join point for the
;; extended sequence hierarchy. (Might be removed later if we use
;; a dedicated FUNDAMENTAL-SEQUENCE class for this.)
(frob extended-sequence *extended-sequence-type*))
Now I don't know whether I should keep *INSTANCE-TYPE* for subclassing
and defmethod matching, or whether switching to a numeric type like
(sb-int:info :type :builtin 'fixnum)
; #<SB-KERNEL:NUMERIC-TYPE FIXNUM>
; T
would be more promising -- a totally separate type might hamper
subclassing unless a lot more special cases are handled, I guess.
Or is that FROBbing the wrong thing to do?
After all, getting the type udef-inttype checked would make more sense.
Any insights would be welcome.
Ad 1:
https://github.com/sbcl/sbcl/commit/b7d20348d3fa8dc56f707012229b39bc6e1a83fe
Ad 2: https://github.com/phmarek/sbcl/tree/udef-crush
|