factor/core/slots/slots.factor

240 lines
6.4 KiB
Factor
Raw Normal View History

! Copyright (C) 2005, 2010 Slava Pestov.
2007-09-20 18:09:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
USING: arrays byte-arrays kernel kernel.private math namespaces
make sequences strings effects generic generic.standard
classes classes.algebra slots.private combinators accessors
2009-01-21 20:55:47 -05:00
words sequences.private assocs alien quotations hashtables ;
2007-09-20 18:09:08 -04:00
IN: slots
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 ;
PREDICATE: reader-method < method "reading" word-prop ;
2008-07-25 03:07:45 -04:00
PREDICATE: writer < word "writer" word-prop ;
PREDICATE: writer-method < method "writing" word-prop ;
: <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 -- )
[ create-method ] 2dip
[ [ props>> ] [ drop ] [ ] tri* assoc-union! drop ]
2008-06-29 22:37:57 -04:00
[ drop define ]
[ 2drop make-inline ]
3tri ;
2007-09-20 18:09:08 -04:00
GENERIC# reader-quot 1 ( class slot-spec -- quot )
M: object reader-quot
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 )
">>" append "accessors" create
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 )
"reading" associate ;
2008-06-29 22:37:57 -04:00
: define-reader-generic ( name -- )
reader-word ( object -- value ) define-simple-generic ;
: define-reader ( class slot-spec -- )
[ nip name>> define-reader-generic ]
[
{
[ drop ]
[ nip name>> reader-word ]
[ reader-quot ]
[ nip reader-props ]
} 2cleave define-typecheck
] 2bi ;
2008-03-20 16:30:59 -04:00
: writer-word ( name -- word )
"<<" append "accessors" create
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
: (instance-check-quot) ( class -- quot )
2008-06-29 22:37:57 -04:00
[
\ dup ,
[ "predicate" word-prop % ]
[ [ bad-slot-value ] curry , ] bi
\ unless ,
] [ ] make ;
: instance-check-quot ( class -- quot )
{
{ [ dup object bootstrap-word eq? ] [ drop [ ] ] }
{ [ dup "coercer" word-prop ] [ "coercer" word-prop ] }
{ [ dup integer bootstrap-word eq? ] [ drop [ >integer ] ] }
[ (instance-check-quot) ]
} cond ;
GENERIC# writer-quot 1 ( class slot-spec -- quot )
M: object writer-quot
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
: define-writer-generic ( name -- )
writer-word ( value object -- ) define-simple-generic ;
: define-writer ( class slot-spec -- )
[ nip name>> define-writer-generic ] [
{
[ drop ]
[ nip name>> writer-word ]
[ writer-quot ]
[ nip writer-props ]
} 2cleave define-typecheck
] 2bi ;
2008-03-20 16:30:59 -04:00
: setter-word ( name -- word )
">>" prepend "accessors" create ;
2008-03-20 16:30:59 -04:00
: define-setter ( name -- )
dup setter-word dup deferred? [
[ \ over , swap writer-word , ] [ ] make
( object value -- object ) define-inline
2008-03-20 16:30:59 -04:00
] [ 2drop ] if ;
: changer-word ( name -- word )
"change-" prepend "accessors" create ;
2008-03-20 16:30:59 -04:00
: define-changer ( name -- )
dup changer-word dup deferred? [
2008-03-20 16:30:59 -04: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 ,
] [ ] 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 -- )
[ define-reader ]
[
dup read-only>> [ 2drop ] [
[ name>> define-setter drop ]
[ name>> define-changer drop ]
[ 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 ;
: define-protocol-slot ( name -- )
{
[ define-reader-generic ]
[ define-writer-generic ]
[ define-setter ]
[ define-changer ]
} cleave ;
ERROR: no-initial-value class ;
2008-07-12 02:08:30 -04:00
GENERIC: initial-value* ( class -- object )
M: class initial-value* no-initial-value ;
: initial-value ( class -- object )
{
{ [ dup "initial-value" word-prop ] [ dup "initial-value" word-prop ] }
2008-06-29 22:37:57 -04:00
{ [ \ f bootstrap-word over class<= ] [ f ] }
2009-08-13 12:05:20 -04:00
{ [ \ array-capacity bootstrap-word over class<= ] [ 0 ] }
2008-06-29 22:37:57 -04:00
{ [ float bootstrap-word over class<= ] [ 0.0 ] }
{ [ string bootstrap-word over class<= ] [ "" ] }
{ [ array bootstrap-word over class<= ] [ { } ] }
{ [ byte-array bootstrap-word over class<= ] [ B{ } ] }
2009-11-02 21:21:10 -05:00
{ [ pinned-alien bootstrap-word over class<= ] [ <bad-alien> ] }
{ [ quotation bootstrap-word over class<= ] [ [ ] ] }
2008-07-12 02:08:30 -04:00
[ dup initial-value* ]
} cond nip ;
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
: peel-off-class ( slot-spec array -- slot-spec array )
dup empty? [
dup first class? [
[ first >>class ] [ rest ] bi
] when
] unless ;
ERROR: bad-slot-attribute key ;
: 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 ] }
[ bad-slot-attribute ]
} case
] unless ;
ERROR: bad-initial-value name ;
: check-initial-value ( slot-spec -- slot-spec )
dup initial>> [
2008-06-29 22:37:57 -04:00
[ ] [
dup [ initial>> ] [ class>> ] bi instance?
[ name>> bad-initial-value ] unless
] if-bootstrapping
] [
dup class>> initial-value >>initial
] if ;
M: array make-slot
<slot-spec>
swap
peel-off-name
peel-off-class
[ dup empty? ] [ peel-off-attributes ] until drop
check-initial-value ;
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 )
over length iota [ + ] with map [ >>offset ] 2map ;
2009-08-12 15:40:06 -04:00
: slot-named* ( name specs -- offset spec/f )
[ name>> = ] with find ;
: slot-named ( name specs -- spec/f )
2009-08-12 15:40:06 -04:00
slot-named* nip ;
! Predefine some slots, because there are change-* words in other vocabs
! that nondeterministically cause ambiguities when USEd alongside
! accessors
SLOT: at
SLOT: nth
SLOT: global