2011-11-12 17:48:00 -05:00
|
|
|
! Copyright (C) 2005, 2011 Slava Pestov.
|
2007-09-20 18:09:08 -04:00
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
2011-11-22 21:49:18 -05:00
|
|
|
USING: accessors alien arrays assocs byte-arrays classes
|
|
|
|
classes.algebra classes.algebra.private classes.maybe
|
|
|
|
combinators generic generic.standard hashtables kernel
|
|
|
|
kernel.private make math quotations sequences sequences.private
|
|
|
|
slots.private strings words ;
|
2007-09-20 18:09:08 -04:00
|
|
|
IN: slots
|
|
|
|
|
2015-06-25 21:02:03 -04:00
|
|
|
<PRIVATE
|
|
|
|
PRIMITIVE: set-slot ( value obj n -- )
|
|
|
|
PRIMITIVE: slot ( obj m -- value )
|
|
|
|
PRIVATE>
|
|
|
|
|
2008-09-03 19:47:52 -04:00
|
|
|
TUPLE: slot-spec name offset class initial read-only ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2008-07-25 03:07:45 -04:00
|
|
|
PREDICATE: reader < word "reader" word-prop ;
|
|
|
|
|
2012-08-14 21:09:50 -04:00
|
|
|
PREDICATE: reader-method < method "reading" word-prop >boolean ;
|
2009-03-07 00:33:03 -05:00
|
|
|
|
2008-07-25 03:07:45 -04:00
|
|
|
PREDICATE: writer < word "writer" word-prop ;
|
|
|
|
|
2012-08-14 21:09:50 -04:00
|
|
|
PREDICATE: writer-method < method "writing" word-prop >boolean ;
|
2009-03-07 00:33:03 -05:00
|
|
|
|
2008-06-28 03:36:20 -04:00
|
|
|
: <slot-spec> ( -- slot-spec )
|
|
|
|
slot-spec new
|
|
|
|
object bootstrap-word >>class ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2008-06-29 22:37:57 -04:00
|
|
|
: define-typecheck ( class generic quot props -- )
|
2009-03-22 19:00:26 -04:00
|
|
|
[ create-method ] 2dip
|
2010-02-03 08:55:00 -05:00
|
|
|
[ [ props>> ] [ drop ] [ ] tri* assoc-union! drop ]
|
2008-06-29 22:37:57 -04:00
|
|
|
[ drop define ]
|
2009-08-17 23:32:21 -04:00
|
|
|
[ 2drop make-inline ]
|
|
|
|
3tri ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2017-06-01 14:58:58 -04:00
|
|
|
GENERIC#: reader-quot 1 ( class slot-spec -- quot )
|
2009-07-31 22:48:17 -04:00
|
|
|
|
2014-10-31 04:14:31 -04:00
|
|
|
M: object reader-quot
|
2009-07-31 22:48:17 -04:00
|
|
|
nip [
|
2008-06-29 22:37:57 -04:00
|
|
|
dup offset>> ,
|
2007-09-20 18:09:08 -04:00
|
|
|
\ slot ,
|
2008-06-29 22:37:57 -04:00
|
|
|
dup class>> object bootstrap-word eq?
|
|
|
|
[ drop ] [ class>> 1array , \ declare , ] if
|
2007-09-20 18:09:08 -04:00
|
|
|
] [ ] make ;
|
|
|
|
|
2008-03-20 16:30:59 -04:00
|
|
|
: reader-word ( name -- word )
|
2015-06-08 15:38:38 -04:00
|
|
|
">>" append "accessors" create-word
|
2008-07-25 03:07:45 -04:00
|
|
|
dup t "reader" set-word-prop ;
|
2008-03-20 16:30:59 -04:00
|
|
|
|
2008-07-25 03:07:45 -04:00
|
|
|
: reader-props ( slot-spec -- assoc )
|
2009-08-17 23:32:21 -04:00
|
|
|
"reading" associate ;
|
2008-06-29 22:37:57 -04:00
|
|
|
|
2009-03-22 19:00:26 -04:00
|
|
|
: define-reader-generic ( name -- )
|
2011-10-18 16:18:42 -04:00
|
|
|
reader-word ( object -- value ) define-simple-generic ;
|
2009-03-22 19:00:26 -04:00
|
|
|
|
2008-06-28 03:36:20 -04:00
|
|
|
: define-reader ( class slot-spec -- )
|
2009-03-22 19:00:26 -04:00
|
|
|
[ nip name>> define-reader-generic ]
|
|
|
|
[
|
2009-07-31 22:48:17 -04:00
|
|
|
{
|
|
|
|
[ drop ]
|
|
|
|
[ nip name>> reader-word ]
|
|
|
|
[ reader-quot ]
|
|
|
|
[ nip reader-props ]
|
|
|
|
} 2cleave define-typecheck
|
2009-03-22 19:00:26 -04:00
|
|
|
] 2bi ;
|
2008-03-20 16:30:59 -04:00
|
|
|
|
|
|
|
: writer-word ( name -- word )
|
2015-06-08 15:38:38 -04:00
|
|
|
"<<" append "accessors" create-word
|
2008-07-25 03:07:45 -04:00
|
|
|
dup t "writer" set-word-prop ;
|
2008-03-20 16:30:59 -04:00
|
|
|
|
2008-06-30 02:44:58 -04:00
|
|
|
ERROR: bad-slot-value value class ;
|
2008-06-28 00:10:19 -04:00
|
|
|
|
2011-11-22 02:00:52 -05:00
|
|
|
GENERIC: instance-check-quot ( obj -- quot )
|
2008-06-29 03:12:44 -04:00
|
|
|
|
2020-09-09 14:12:50 -04:00
|
|
|
M: class instance-check-quot
|
2010-01-16 01:29:19 -05:00
|
|
|
{
|
|
|
|
{ [ dup object bootstrap-word eq? ] [ drop [ ] ] }
|
|
|
|
{ [ dup "coercer" word-prop ] [ "coercer" word-prop ] }
|
2011-11-22 02:00:52 -05:00
|
|
|
[ call-next-method ]
|
2010-01-16 01:29:19 -05:00
|
|
|
} cond ;
|
2008-06-29 03:12:44 -04:00
|
|
|
|
2011-11-22 02:00:52 -05:00
|
|
|
M: object instance-check-quot
|
|
|
|
[
|
|
|
|
\ dup ,
|
|
|
|
[ predicate-def % ]
|
2015-08-13 19:13:05 -04:00
|
|
|
[ [ bad-slot-value ] curry , ] bi
|
2011-11-22 02:00:52 -05:00
|
|
|
\ unless ,
|
|
|
|
] [ ] make ;
|
|
|
|
|
2017-06-01 14:58:58 -04:00
|
|
|
GENERIC#: writer-quot 1 ( class slot-spec -- quot )
|
2009-07-31 22:48:17 -04:00
|
|
|
|
|
|
|
M: object writer-quot
|
2010-01-16 01:29:19 -05:00
|
|
|
nip
|
|
|
|
[ class>> instance-check-quot dup empty? [ [ dip ] curry ] unless ]
|
|
|
|
[ offset>> [ set-slot ] curry ]
|
|
|
|
bi append ;
|
2008-06-28 00:10:19 -04:00
|
|
|
|
2008-07-25 03:07:45 -04:00
|
|
|
: writer-props ( slot-spec -- assoc )
|
2009-01-21 20:55:47 -05:00
|
|
|
"writing" associate ;
|
2008-07-25 03:07:45 -04:00
|
|
|
|
2009-03-22 19:00:26 -04:00
|
|
|
: define-writer-generic ( name -- )
|
2011-10-18 16:18:42 -04:00
|
|
|
writer-word ( value object -- ) define-simple-generic ;
|
2009-03-22 19:00:26 -04:00
|
|
|
|
2008-06-28 03:36:20 -04:00
|
|
|
: define-writer ( class slot-spec -- )
|
2009-03-22 19:00:26 -04:00
|
|
|
[ nip name>> define-writer-generic ] [
|
2009-07-31 22:48:17 -04:00
|
|
|
{
|
|
|
|
[ drop ]
|
|
|
|
[ nip name>> writer-word ]
|
|
|
|
[ writer-quot ]
|
|
|
|
[ nip writer-props ]
|
|
|
|
} 2cleave define-typecheck
|
2009-03-22 19:00:26 -04:00
|
|
|
] 2bi ;
|
2008-03-20 16:30:59 -04:00
|
|
|
|
|
|
|
: setter-word ( name -- word )
|
2015-06-08 15:38:38 -04:00
|
|
|
">>" prepend "accessors" create-word ;
|
2008-03-20 16:30:59 -04:00
|
|
|
|
2008-11-14 01:39:28 -05:00
|
|
|
: define-setter ( name -- )
|
|
|
|
dup setter-word dup deferred? [
|
2008-12-15 20:44:56 -05:00
|
|
|
[ \ over , swap writer-word , ] [ ] make
|
2011-10-18 16:18:42 -04:00
|
|
|
( object value -- object ) define-inline
|
2008-03-20 16:30:59 -04:00
|
|
|
] [ 2drop ] if ;
|
|
|
|
|
|
|
|
: changer-word ( name -- word )
|
2015-06-08 15:38:38 -04:00
|
|
|
"change-" prepend "accessors" create-word ;
|
2008-03-20 16:30:59 -04:00
|
|
|
|
2008-11-14 01:39:28 -05:00
|
|
|
: define-changer ( name -- )
|
|
|
|
dup changer-word dup deferred? [
|
2008-03-20 16:30:59 -04:00
|
|
|
[
|
2008-11-23 03:44:56 -05:00
|
|
|
\ over ,
|
|
|
|
over reader-word 1quotation
|
2009-05-04 06:15:48 -04:00
|
|
|
[ dip call ] curry [ ] like [ dip swap ] curry %
|
2008-03-20 16:30:59 -04:00
|
|
|
swap setter-word ,
|
2011-10-18 16:18:42 -04:00
|
|
|
] [ ] make ( object quot -- object ) define-inline
|
2008-03-20 16:30:59 -04:00
|
|
|
] [ 2drop ] if ;
|
|
|
|
|
2008-06-28 00:10:19 -04:00
|
|
|
: define-slot-methods ( class slot-spec -- )
|
2008-06-28 03:36:20 -04:00
|
|
|
[ define-reader ]
|
|
|
|
[
|
|
|
|
dup read-only>> [ 2drop ] [
|
2008-11-14 01:39:28 -05:00
|
|
|
[ name>> define-setter drop ]
|
|
|
|
[ name>> define-changer drop ]
|
2008-06-28 03:36:20 -04:00
|
|
|
[ define-writer ]
|
|
|
|
2tri
|
|
|
|
] if
|
|
|
|
] 2bi ;
|
2008-03-20 16:30:59 -04:00
|
|
|
|
|
|
|
: define-accessors ( class specs -- )
|
2008-06-28 00:10:19 -04:00
|
|
|
[ define-slot-methods ] with each ;
|
2008-03-31 02:19:34 -04:00
|
|
|
|
2008-06-28 03:36:20 -04:00
|
|
|
: define-protocol-slot ( name -- )
|
|
|
|
{
|
2009-03-22 19:00:26 -04:00
|
|
|
[ define-reader-generic ]
|
|
|
|
[ define-writer-generic ]
|
2008-11-14 01:39:28 -05:00
|
|
|
[ define-setter ]
|
|
|
|
[ define-changer ]
|
2008-06-28 03:36:20 -04:00
|
|
|
} cleave ;
|
|
|
|
|
2011-11-22 21:49:18 -05:00
|
|
|
DEFER: initial-value
|
|
|
|
|
2011-11-12 17:48:00 -05:00
|
|
|
GENERIC: initial-value* ( class -- object ? )
|
2008-06-29 03:12:44 -04:00
|
|
|
|
2011-11-12 17:48:00 -05:00
|
|
|
M: class initial-value* drop f f ;
|
2008-07-12 02:08:30 -04:00
|
|
|
|
2013-03-28 23:04:19 -04:00
|
|
|
M: maybe initial-value* drop f t ;
|
2011-11-22 21:49:18 -05:00
|
|
|
|
2013-03-28 23:04:19 -04:00
|
|
|
! Default initial value is f, 0, or the default initial value of
|
|
|
|
! the smallest class. Special case 0 because float is ostensibly
|
2011-11-22 21:49:18 -05:00
|
|
|
! smaller than integer in union{ integer float } because of
|
|
|
|
! alphabetical sorting.
|
|
|
|
M: anonymous-union initial-value*
|
|
|
|
{
|
|
|
|
{ [ f over instance? ] [ drop f t ] }
|
|
|
|
{ [ 0 over instance? ] [ drop 0 t ] }
|
|
|
|
[
|
|
|
|
members>> sort-classes [ initial-value ] { } map>assoc
|
|
|
|
?last [ second t ] [ f f ] if*
|
|
|
|
]
|
|
|
|
} cond ;
|
|
|
|
|
|
|
|
! See if any of the initial values fit the intersection class,
|
2013-03-28 23:04:19 -04:00
|
|
|
! or else return that none do, and leave it up to the user to
|
|
|
|
! provide an initial: value.
|
2011-11-22 21:49:18 -05:00
|
|
|
M: anonymous-intersection initial-value*
|
|
|
|
{
|
|
|
|
{ [ f over instance? ] [ drop f t ] }
|
|
|
|
{ [ 0 over instance? ] [ drop 0 t ] }
|
|
|
|
[
|
|
|
|
[ ]
|
|
|
|
[ participants>> sort-classes [ initial-value ] { } map>assoc ]
|
|
|
|
[ ] tri
|
|
|
|
|
|
|
|
[ [ first2 nip ] dip instance? ] curry find swap [
|
|
|
|
nip second t
|
|
|
|
] [
|
|
|
|
2drop f f
|
|
|
|
] if
|
|
|
|
]
|
|
|
|
} cond ;
|
|
|
|
|
2011-11-12 17:48:00 -05:00
|
|
|
: initial-value ( class -- object ? )
|
2008-06-29 03:12:44 -04:00
|
|
|
{
|
2011-11-22 21:49:18 -05:00
|
|
|
{ [ dup only-classoid? ] [ dup initial-value* ] }
|
2011-11-12 17:48:00 -05:00
|
|
|
{ [ dup "initial-value" word-prop ] [ dup "initial-value" word-prop t ] }
|
|
|
|
{ [ \ f bootstrap-word over class<= ] [ f t ] }
|
|
|
|
{ [ \ array-capacity bootstrap-word over class<= ] [ 0 t ] }
|
2016-03-21 13:10:39 -04:00
|
|
|
{ [ \ integer-array-capacity bootstrap-word over class<= ] [ 0 t ] }
|
2012-07-30 21:16:44 -04:00
|
|
|
{ [ bignum bootstrap-word over class<= ] [ 0 >bignum t ] }
|
2011-11-12 17:48:00 -05:00
|
|
|
{ [ float bootstrap-word over class<= ] [ 0.0 t ] }
|
|
|
|
{ [ string bootstrap-word over class<= ] [ "" t ] }
|
|
|
|
{ [ array bootstrap-word over class<= ] [ { } t ] }
|
|
|
|
{ [ byte-array bootstrap-word over class<= ] [ B{ } t ] }
|
|
|
|
{ [ pinned-alien bootstrap-word over class<= ] [ <bad-alien> t ] }
|
|
|
|
{ [ quotation bootstrap-word over class<= ] [ [ ] t ] }
|
2008-07-12 02:08:30 -04:00
|
|
|
[ dup initial-value* ]
|
2018-06-19 20:15:05 -04:00
|
|
|
} cond nipd ;
|
2008-06-29 03:12:44 -04:00
|
|
|
|
2008-06-28 03:36:20 -04:00
|
|
|
GENERIC: make-slot ( desc -- slot-spec )
|
|
|
|
|
|
|
|
M: string make-slot
|
|
|
|
<slot-spec>
|
|
|
|
swap >>name ;
|
|
|
|
|
|
|
|
: peel-off-name ( slot-spec array -- slot-spec array )
|
|
|
|
[ first >>name ] [ rest ] bi ; inline
|
|
|
|
|
2011-11-12 17:48:00 -05:00
|
|
|
: init-slot-class ( slot-spec class -- slot-spec )
|
|
|
|
[ >>class ] [ initial-value [ >>initial ] [ drop ] if ] bi ;
|
|
|
|
|
2008-06-28 03:36:20 -04:00
|
|
|
: peel-off-class ( slot-spec array -- slot-spec array )
|
|
|
|
dup empty? [
|
2011-11-22 02:00:52 -05:00
|
|
|
dup first classoid? [
|
2016-04-14 19:59:33 -04:00
|
|
|
[ first init-slot-class ] [ rest ] bi
|
2008-06-28 03:36:20 -04:00
|
|
|
] when
|
|
|
|
] unless ;
|
|
|
|
|
2008-06-29 03:12:44 -04:00
|
|
|
ERROR: bad-slot-attribute key ;
|
|
|
|
|
2008-06-28 03:36:20 -04:00
|
|
|
: peel-off-attributes ( slot-spec array -- slot-spec array )
|
|
|
|
dup empty? [
|
|
|
|
unclip {
|
|
|
|
{ initial: [ [ first >>initial ] [ rest ] bi ] }
|
2008-06-30 02:44:58 -04:00
|
|
|
{ read-only [ [ t >>read-only ] dip ] }
|
2015-08-13 19:13:05 -04:00
|
|
|
[ bad-slot-attribute ]
|
2008-06-28 03:36:20 -04:00
|
|
|
} case
|
|
|
|
] unless ;
|
|
|
|
|
2011-11-22 21:49:18 -05:00
|
|
|
ERROR: bad-initial-value name initial-value class ;
|
2008-06-29 03:12:44 -04:00
|
|
|
|
|
|
|
: check-initial-value ( slot-spec -- slot-spec )
|
2011-11-12 17:48:00 -05:00
|
|
|
[ ] [
|
2011-11-22 21:49:18 -05:00
|
|
|
[ ] [ initial>> ] [ class>> ] tri
|
|
|
|
2dup instance? [
|
|
|
|
2drop
|
|
|
|
] [
|
|
|
|
[ name>> ] 2dip bad-initial-value
|
|
|
|
] if
|
2011-11-12 17:48:00 -05:00
|
|
|
] if-bootstrapping ;
|
2008-06-29 03:12:44 -04:00
|
|
|
|
2008-06-28 03:36:20 -04:00
|
|
|
M: array make-slot
|
|
|
|
<slot-spec>
|
|
|
|
swap
|
|
|
|
peel-off-name
|
|
|
|
peel-off-class
|
2009-02-17 20:19:49 -05:00
|
|
|
[ dup empty? ] [ peel-off-attributes ] until drop
|
2008-06-29 03:12:44 -04:00
|
|
|
check-initial-value ;
|
2008-06-28 03:36:20 -04:00
|
|
|
|
2008-07-13 22:06:50 -04:00
|
|
|
M: slot-spec make-slot
|
|
|
|
check-initial-value ;
|
|
|
|
|
|
|
|
: make-slots ( slots -- specs )
|
|
|
|
[ make-slot ] map ;
|
|
|
|
|
|
|
|
: finalize-slots ( specs base -- specs )
|
2017-06-01 17:59:35 -04:00
|
|
|
over length <iota> [ + ] with map [ >>offset ] 2map ;
|
2008-06-28 03:36:20 -04:00
|
|
|
|
2009-08-12 15:40:06 -04:00
|
|
|
: slot-named* ( name specs -- offset spec/f )
|
|
|
|
[ name>> = ] with find ;
|
|
|
|
|
2008-03-31 02:19:34 -04:00
|
|
|
: slot-named ( name specs -- spec/f )
|
2009-08-12 15:40:06 -04:00
|
|
|
slot-named* nip ;
|