2008-01-28 19:15:21 -05:00
|
|
|
! Copyright (C) 2005, 2008 Slava Pestov.
|
2007-09-20 18:09:08 -04:00
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
2008-07-02 03:03:30 -04:00
|
|
|
USING: arrays byte-arrays kernel kernel.private math namespaces
|
|
|
|
sequences strings words effects generic generic.standard classes
|
|
|
|
classes.algebra slots.private combinators accessors words
|
|
|
|
sequences.private assocs alien ;
|
2007-09-20 18:09:08 -04:00
|
|
|
IN: slots
|
|
|
|
|
2008-06-28 03:36:20 -04:00
|
|
|
TUPLE: slot-spec name offset class initial read-only reader writer ;
|
2007-09-20 18:09:08 -04: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 -- )
|
|
|
|
[ dup define-simple-generic create-method ] 2dip
|
|
|
|
[ [ props>> ] [ drop ] [ [ t ] H{ } map>assoc ] tri* update ]
|
|
|
|
[ drop define ]
|
|
|
|
3bi ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2008-06-28 03:36:20 -04:00
|
|
|
: create-accessor ( name effect -- word )
|
|
|
|
>r "accessors" create dup r>
|
|
|
|
"declared-effect" set-word-prop ;
|
|
|
|
|
2008-06-29 22:37:57 -04:00
|
|
|
: reader-quot ( slot-spec -- quot )
|
2007-09-20 18:09:08 -04:00
|
|
|
[
|
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 )
|
2008-06-08 16:32:55 -04:00
|
|
|
">>" append (( object -- value )) create-accessor ;
|
2008-03-20 16:30:59 -04:00
|
|
|
|
2008-06-29 22:37:57 -04:00
|
|
|
: reader-props ( slot-spec -- seq )
|
|
|
|
read-only>> { "foldable" "flushable" } { "flushable" } ? ;
|
|
|
|
|
2008-06-28 03:36:20 -04:00
|
|
|
: define-reader ( class slot-spec -- )
|
2008-06-29 22:37:57 -04:00
|
|
|
[ name>> reader-word ] [ reader-quot ] [ reader-props ] tri
|
|
|
|
define-typecheck ;
|
2008-03-20 16:30:59 -04:00
|
|
|
|
|
|
|
: writer-word ( name -- word )
|
2008-06-08 16:32:55 -04:00
|
|
|
"(>>" swap ")" 3append (( value object -- )) create-accessor ;
|
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
|
|
|
|
2008-06-29 22:37:57 -04:00
|
|
|
: writer-quot/object ( slot-spec -- )
|
|
|
|
offset>> , \ set-slot , ;
|
2008-06-29 03:12:44 -04:00
|
|
|
|
2008-06-29 22:37:57 -04:00
|
|
|
: writer-quot/coerce ( slot-spec -- )
|
|
|
|
[ \ >r , class>> "coercer" word-prop % \ r> , ]
|
|
|
|
[ offset>> , \ set-slot , ]
|
|
|
|
bi ;
|
2008-06-29 03:12:44 -04:00
|
|
|
|
2008-06-29 22:37:57 -04:00
|
|
|
: writer-quot/check ( slot-spec -- )
|
|
|
|
[ offset>> , ]
|
|
|
|
[
|
|
|
|
\ pick ,
|
2008-06-30 02:44:58 -04:00
|
|
|
dup class>> "predicate" word-prop %
|
|
|
|
[ set-slot ] ,
|
|
|
|
class>> [ 2nip bad-slot-value ] curry [ ] like ,
|
|
|
|
\ if ,
|
2008-06-29 22:37:57 -04:00
|
|
|
]
|
|
|
|
bi ;
|
2008-06-29 03:12:44 -04:00
|
|
|
|
2008-06-29 22:37:57 -04:00
|
|
|
: writer-quot/fixnum ( slot-spec -- )
|
|
|
|
[ >r >fixnum r> ] % writer-quot/check ;
|
2008-06-29 03:12:44 -04:00
|
|
|
|
2008-06-29 22:37:57 -04:00
|
|
|
: writer-quot ( slot-spec -- quot )
|
2008-06-28 00:10:19 -04:00
|
|
|
[
|
2008-06-29 03:12:44 -04:00
|
|
|
{
|
2008-06-29 22:37:57 -04:00
|
|
|
{ [ dup class>> object bootstrap-word eq? ] [ writer-quot/object ] }
|
|
|
|
{ [ dup class>> "coercer" word-prop ] [ writer-quot/coerce ] }
|
|
|
|
{ [ dup class>> fixnum bootstrap-word class<= ] [ writer-quot/fixnum ] }
|
2008-06-29 03:12:44 -04:00
|
|
|
[ writer-quot/check ]
|
|
|
|
} cond
|
2008-06-28 00:10:19 -04:00
|
|
|
] [ ] make ;
|
|
|
|
|
2008-06-28 03:36:20 -04:00
|
|
|
: define-writer ( class slot-spec -- )
|
2008-06-29 22:37:57 -04:00
|
|
|
[ name>> writer-word ] [ writer-quot ] bi { } define-typecheck ;
|
2008-03-20 16:30:59 -04:00
|
|
|
|
|
|
|
: setter-word ( name -- word )
|
2008-06-08 16:32:55 -04:00
|
|
|
">>" prepend (( object value -- object )) create-accessor ;
|
2008-03-20 16:30:59 -04:00
|
|
|
|
2008-06-28 03:36:20 -04:00
|
|
|
: define-setter ( slot-spec -- )
|
|
|
|
name>> dup setter-word dup deferred? [
|
2008-03-20 16:30:59 -04:00
|
|
|
[ \ over , swap writer-word , ] [ ] make define-inline
|
|
|
|
] [ 2drop ] if ;
|
|
|
|
|
|
|
|
: changer-word ( name -- word )
|
2008-06-08 16:32:55 -04:00
|
|
|
"change-" prepend (( object quot -- object )) create-accessor ;
|
2008-03-20 16:30:59 -04:00
|
|
|
|
2008-06-28 03:36:20 -04:00
|
|
|
: define-changer ( slot-spec -- )
|
|
|
|
name>> dup changer-word dup deferred? [
|
2008-03-20 16:30:59 -04:00
|
|
|
[
|
|
|
|
[ over >r >r ] %
|
|
|
|
over reader-word ,
|
|
|
|
[ r> call r> swap ] %
|
|
|
|
swap setter-word ,
|
|
|
|
] [ ] make define-inline
|
|
|
|
] [ 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 ] [
|
|
|
|
[ define-setter drop ]
|
|
|
|
[ 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 ;
|
2008-03-31 02:19:34 -04:00
|
|
|
|
2008-06-28 03:36:20 -04:00
|
|
|
: define-protocol-slot ( name -- )
|
|
|
|
{
|
|
|
|
[ reader-word drop ]
|
|
|
|
[ writer-word drop ]
|
|
|
|
[ setter-word drop ]
|
|
|
|
[ changer-word drop ]
|
|
|
|
} cleave ;
|
|
|
|
|
2008-06-29 03:12:44 -04:00
|
|
|
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 ;
|
|
|
|
|
2008-06-29 03:12:44 -04:00
|
|
|
: initial-value ( class -- object )
|
|
|
|
{
|
2008-06-29 22:37:57 -04:00
|
|
|
{ [ \ f bootstrap-word over class<= ] [ f ] }
|
|
|
|
{ [ \ array-capacity bootstrap-word over class<= ] [ 0 ] }
|
|
|
|
{ [ float bootstrap-word over class<= ] [ 0.0 ] }
|
|
|
|
{ [ string bootstrap-word over class<= ] [ "" ] }
|
|
|
|
{ [ array bootstrap-word over class<= ] [ { } ] }
|
|
|
|
{ [ byte-array bootstrap-word over class<= ] [ B{ } ] }
|
2008-07-01 17:33:45 -04:00
|
|
|
{ [ simple-alien bootstrap-word over class<= ] [ <bad-alien> ] }
|
2008-07-12 02:08:30 -04:00
|
|
|
[ dup initial-value* ]
|
2008-06-29 03:12:44 -04:00
|
|
|
} cond nip ;
|
|
|
|
|
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
|
|
|
|
|
|
|
|
: peel-off-class ( slot-spec array -- slot-spec array )
|
|
|
|
dup empty? [
|
2008-06-29 03:12:44 -04:00
|
|
|
dup first class? [
|
2008-06-28 03:36:20 -04:00
|
|
|
[ first >>class ] [ rest ] bi
|
|
|
|
] 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 ] }
|
2008-06-29 03:12:44 -04:00
|
|
|
[ bad-slot-attribute ]
|
2008-06-28 03:36:20 -04:00
|
|
|
} case
|
|
|
|
] unless ;
|
|
|
|
|
2008-06-29 03:12:44 -04:00
|
|
|
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
|
2008-06-29 03:12:44 -04:00
|
|
|
] [
|
|
|
|
dup class>> initial-value >>initial
|
|
|
|
] if ;
|
|
|
|
|
2008-06-28 03:36:20 -04:00
|
|
|
M: array make-slot
|
|
|
|
<slot-spec>
|
|
|
|
swap
|
|
|
|
peel-off-name
|
|
|
|
peel-off-class
|
2008-06-29 03:12:44 -04:00
|
|
|
[ dup empty? not ] [ peel-off-attributes ] [ ] while drop
|
|
|
|
check-initial-value ;
|
2008-06-28 03:36:20 -04:00
|
|
|
|
|
|
|
: make-slots ( slots base -- specs )
|
|
|
|
over length [ + ] with map
|
|
|
|
[ [ make-slot ] dip >>offset ] 2map ;
|
|
|
|
|
2008-03-31 02:19:34 -04:00
|
|
|
: slot-named ( name specs -- spec/f )
|
|
|
|
[ slot-spec-name = ] with find nip ;
|