2007-09-20 18:09:08 -04:00
|
|
|
! Copyright (C) 2005, 2007 Slava Pestov.
|
|
|
|
! See http://factorcode.org/license.txt for BSD license.
|
|
|
|
USING: arrays assocs kernel kernel.private slots.private math
|
|
|
|
namespaces sequences vectors words quotations definitions
|
|
|
|
hashtables layouts combinators combinators.private generic
|
|
|
|
classes classes.private ;
|
|
|
|
IN: generic.standard
|
|
|
|
|
|
|
|
TUPLE: standard-combination # ;
|
|
|
|
|
2008-02-04 17:20:07 -05:00
|
|
|
M: standard-combination method-prologue
|
|
|
|
standard-combination-# object
|
2008-02-04 20:38:31 -05:00
|
|
|
<array> swap add* [ declare ] curry ;
|
2008-02-04 17:20:07 -05:00
|
|
|
|
2007-09-20 18:09:08 -04:00
|
|
|
C: <standard-combination> standard-combination
|
|
|
|
|
|
|
|
SYMBOL: (dispatch#)
|
|
|
|
|
|
|
|
: (picker) ( n -- quot )
|
|
|
|
{
|
|
|
|
{ 0 [ [ dup ] ] }
|
|
|
|
{ 1 [ [ over ] ] }
|
|
|
|
{ 2 [ [ pick ] ] }
|
|
|
|
[ 1- (picker) [ >r ] swap [ r> swap ] 3append ]
|
|
|
|
} case ;
|
|
|
|
|
|
|
|
: picker ( -- quot ) \ (dispatch#) get (picker) ;
|
|
|
|
|
|
|
|
: unpickers { [ nip ] [ >r nip r> swap ] [ >r >r nip r> r> -rot ] } ; inline
|
|
|
|
|
|
|
|
: unpicker ( -- quot ) \ (dispatch#) get unpickers nth ;
|
|
|
|
|
|
|
|
TUPLE: no-method object generic ;
|
|
|
|
|
|
|
|
: no-method ( object generic -- * )
|
|
|
|
\ no-method construct-boa throw ;
|
|
|
|
|
2008-02-04 17:20:07 -05:00
|
|
|
: error-method ( word -- quot )
|
2007-09-20 18:09:08 -04:00
|
|
|
picker swap [ no-method ] curry append ;
|
|
|
|
|
2008-02-04 17:20:07 -05:00
|
|
|
: empty-method ( word -- quot )
|
2007-09-20 18:09:08 -04:00
|
|
|
[
|
|
|
|
picker % [ delegate dup ] %
|
|
|
|
unpicker over add ,
|
|
|
|
error-method \ drop add* , \ if ,
|
|
|
|
] [ ] make ;
|
|
|
|
|
|
|
|
: class-predicates ( assoc -- assoc )
|
|
|
|
[
|
|
|
|
>r >r picker r> "predicate" word-prop append r>
|
|
|
|
] assoc-map ;
|
|
|
|
|
|
|
|
: (simplify-alist) ( class i assoc -- default assoc )
|
|
|
|
2dup length 1- = [
|
|
|
|
nth second { } rot drop
|
|
|
|
] [
|
|
|
|
3dup >r 1+ r> nth first class< [
|
|
|
|
>r 1+ r> (simplify-alist)
|
|
|
|
] [
|
|
|
|
[ nth second ] 2keep swap 1+ tail rot drop
|
|
|
|
] if
|
|
|
|
] if ;
|
|
|
|
|
|
|
|
: simplify-alist ( class assoc -- default assoc )
|
|
|
|
dup empty? [
|
|
|
|
2drop [ "Unreachable" throw ] { }
|
|
|
|
] [
|
|
|
|
0 swap (simplify-alist)
|
|
|
|
] if ;
|
|
|
|
|
|
|
|
: default-method ( word -- pair )
|
2008-02-04 17:20:07 -05:00
|
|
|
"default-method" word-prop method-word
|
|
|
|
object bootstrap-word swap 2array ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
|
|
|
: method-alist>quot ( alist base-class -- quot )
|
|
|
|
bootstrap-word swap simplify-alist
|
|
|
|
class-predicates alist>quot ;
|
|
|
|
|
|
|
|
: small-generic ( methods -- def )
|
2008-02-04 17:20:07 -05:00
|
|
|
[ 1quotation ] assoc-map
|
2007-09-20 18:09:08 -04:00
|
|
|
object method-alist>quot ;
|
|
|
|
|
|
|
|
: hash-methods ( methods -- buckets )
|
|
|
|
V{ } clone [
|
|
|
|
tuple bootstrap-word over class< [
|
|
|
|
drop t
|
|
|
|
] [
|
|
|
|
class-hashes
|
|
|
|
] if
|
|
|
|
] distribute-buckets ;
|
|
|
|
|
2008-02-04 17:20:07 -05:00
|
|
|
: class-hash-dispatch-quot ( methods quot picker -- quot )
|
|
|
|
>r >r hash-methods r> map
|
|
|
|
hash-dispatch-quot r> [ class-hash ] rot 3append ;
|
|
|
|
|
2007-09-20 18:09:08 -04:00
|
|
|
: big-generic ( methods -- quot )
|
2008-02-04 17:20:07 -05:00
|
|
|
[ small-generic ] picker class-hash-dispatch-quot ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
|
|
|
: vtable-class ( n -- class )
|
|
|
|
type>class [ hi-tag bootstrap-word ] unless* ;
|
|
|
|
|
|
|
|
: group-methods ( assoc -- vtable )
|
|
|
|
#! Input is a predicate -> method association.
|
|
|
|
#! n is vtable size (either num-types or num-tags).
|
|
|
|
num-tags get [
|
|
|
|
vtable-class
|
|
|
|
[ swap first classes-intersect? ] curry subset
|
2008-01-09 17:36:30 -05:00
|
|
|
] with map ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
|
|
|
: build-type-vtable ( alist-seq -- alist-seq )
|
|
|
|
dup length [
|
2008-02-04 17:20:07 -05:00
|
|
|
vtable-class
|
|
|
|
swap [ word-def ] assoc-map simplify-alist
|
2007-09-20 18:09:08 -04:00
|
|
|
class-predicates alist>quot
|
|
|
|
] 2map ;
|
|
|
|
|
|
|
|
: tag-generic ( methods -- quot )
|
|
|
|
[
|
|
|
|
picker %
|
|
|
|
\ tag ,
|
|
|
|
group-methods build-type-vtable ,
|
|
|
|
\ dispatch ,
|
|
|
|
] [ ] make ;
|
|
|
|
|
|
|
|
: flatten-method ( class body -- )
|
|
|
|
over members pick object bootstrap-word eq? not and [
|
|
|
|
>r members r> [ flatten-method ] curry each
|
|
|
|
] [
|
|
|
|
swap set
|
|
|
|
] if ;
|
|
|
|
|
|
|
|
: flatten-methods ( methods -- newmethods )
|
|
|
|
[ [ flatten-method ] assoc-each ] V{ } make-assoc ;
|
|
|
|
|
|
|
|
: dispatched-types ( methods -- seq )
|
|
|
|
keys object bootstrap-word swap remove prune ;
|
|
|
|
|
|
|
|
: single-combination ( methods -- quot )
|
|
|
|
dup length 4 <= [
|
|
|
|
small-generic
|
|
|
|
] [
|
|
|
|
flatten-methods
|
|
|
|
dup dispatched-types [ number class< ] all?
|
|
|
|
[ tag-generic ] [ big-generic ] if
|
|
|
|
] if ;
|
|
|
|
|
|
|
|
: standard-methods ( word -- alist )
|
|
|
|
dup methods swap default-method add* ;
|
|
|
|
|
2008-02-04 17:20:07 -05:00
|
|
|
M: standard-combination make-default-method
|
|
|
|
standard-combination-# (dispatch#)
|
|
|
|
[ empty-method ] with-variable ;
|
|
|
|
|
2007-09-20 18:09:08 -04:00
|
|
|
M: standard-combination perform-combination
|
|
|
|
standard-combination-# (dispatch#) [
|
2008-01-17 17:55:51 -05:00
|
|
|
[ standard-methods ] keep "inline" word-prop
|
|
|
|
[ small-generic ] [ single-combination ] if
|
2007-09-20 18:09:08 -04:00
|
|
|
] with-variable ;
|
|
|
|
|
|
|
|
TUPLE: hook-combination var ;
|
|
|
|
|
|
|
|
C: <hook-combination> hook-combination
|
|
|
|
|
2008-02-04 17:20:07 -05:00
|
|
|
M: hook-combination method-prologue
|
|
|
|
2drop [ drop ] ;
|
|
|
|
|
|
|
|
: with-hook ( combination quot -- quot' )
|
2007-09-20 18:09:08 -04:00
|
|
|
0 (dispatch#) [
|
2008-02-04 17:20:07 -05:00
|
|
|
swap slip
|
|
|
|
hook-combination-var [ get ] curry
|
|
|
|
swap append
|
|
|
|
] with-variable ; inline
|
|
|
|
|
|
|
|
M: hook-combination make-default-method
|
|
|
|
[ error-method ] with-hook ;
|
|
|
|
|
|
|
|
M: hook-combination perform-combination
|
|
|
|
[ standard-methods single-combination ] with-hook ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
|
|
|
: define-simple-generic ( word -- )
|
|
|
|
T{ standard-combination f 0 } define-generic ;
|
|
|
|
|
|
|
|
PREDICATE: generic standard-generic
|
|
|
|
"combination" word-prop standard-combination? ;
|
|
|
|
|
|
|
|
PREDICATE: standard-generic simple-generic
|
|
|
|
"combination" word-prop standard-combination-# zero? ;
|
|
|
|
|
|
|
|
PREDICATE: generic hook-generic
|
|
|
|
"combination" word-prop hook-combination? ;
|
|
|
|
|
|
|
|
GENERIC: dispatch# ( word -- n )
|
|
|
|
|
|
|
|
M: word dispatch# "combination" word-prop dispatch# ;
|
|
|
|
|
|
|
|
M: standard-combination dispatch# standard-combination-# ;
|
|
|
|
|
|
|
|
M: hook-combination dispatch# drop 0 ;
|
|
|
|
|
|
|
|
M: simple-generic definer drop \ GENERIC: f ;
|
2008-01-06 11:13:44 -05:00
|
|
|
|
|
|
|
M: standard-generic definer drop \ GENERIC# f ;
|
|
|
|
|
|
|
|
M: hook-generic definer drop \ HOOK: f ;
|