factor/core/generic/standard/standard.factor

187 lines
5.0 KiB
Factor
Raw Normal View History

2008-02-17 01:37:54 -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.
USING: arrays assocs kernel kernel.private slots.private math
namespaces sequences vectors words quotations definitions
2008-02-11 02:19:53 -05:00
hashtables layouts combinators sequences.private generic
2008-03-24 20:52:21 -04:00
classes classes.algebra classes.private ;
2007-09-20 18:09:08 -04:00
IN: generic.standard
TUPLE: standard-combination # ;
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 ;
2008-03-20 16:00:49 -04:00
ERROR: no-method object generic ;
2007-09-20 18:09:08 -04:00
: error-method ( word -- quot )
2007-09-20 18:09:08 -04:00
picker swap [ no-method ] curry append ;
: empty-method ( word -- quot )
2007-09-20 18:09:08 -04:00
[
picker % [ delegate dup ] %
unpicker over suffix ,
error-method \ drop prefix , \ if ,
2007-09-20 18:09:08 -04:00
] [ ] make ;
: class-predicates ( assoc -- assoc )
2008-04-01 02:40:30 -04:00
[ >r "predicate" word-prop picker prepend r> ] assoc-map ;
2007-09-20 18:09:08 -04:00
: simplify-alist ( class assoc -- default assoc' )
{
{ [ dup empty? ] [ 2drop [ "Unreachable" throw ] { } ] }
{ [ dup length 1 = ] [ nip first second { } ] }
{ [ 2dup second first class< ] [ 1 tail-slice simplify-alist ] }
{ [ t ] [ nip [ first second ] [ 1 tail-slice ] bi ] }
} cond ;
2007-09-20 18:09:08 -04:00
: default-method ( word -- pair )
"default-method" word-prop
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 )
object method-alist>quot ;
: hash-methods ( methods -- buckets )
V{ } clone [
tuple bootstrap-word over class< [
drop t
] [
class-hashes
] if
] distribute-buckets ;
: class-hash-dispatch-quot ( methods quot picker -- quot )
>r >r hash-methods r> map
2008-02-05 00:30:59 -05:00
hash-dispatch-quot r> [ class-hash ] rot 3append ; inline
2007-09-20 18:09:08 -04:00
: big-generic ( methods -- quot )
[ small-generic ] picker class-hash-dispatch-quot ;
2007-09-20 18:09:08 -04:00
: vtable-class ( n -- class )
bootstrap-type>class [ \ hi-tag bootstrap-word ] unless* ;
2007-09-20 18:09:08 -04:00
: 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 [
vtable-class
2008-02-17 01:37:54 -05:00
swap 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 prefix
2008-02-17 01:37:54 -05:00
[ 1quotation ] assoc-map ;
2007-09-20 18:09:08 -04: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
: with-hook ( combination quot -- quot' )
2007-09-20 18:09:08 -04:00
0 (dispatch#) [
swap slip
hook-combination-var [ get ] curry
2008-03-19 20:15:43 -04:00
prepend
] with-variable ; inline
M: hook-combination make-default-method
[ error-method ] with-hook ;
M: hook-combination perform-combination
2008-02-17 01:37:54 -05:00
[
standard-methods
2008-03-19 20:15:43 -04:00
[ [ drop ] prepend ] assoc-map
2008-02-17 01:37:54 -05:00
single-combination
] with-hook ;
2007-09-20 18:09:08 -04:00
: define-simple-generic ( word -- )
T{ standard-combination f 0 } define-generic ;
2008-03-26 19:23:19 -04:00
PREDICATE: standard-generic < generic
2007-09-20 18:09:08 -04:00
"combination" word-prop standard-combination? ;
2008-03-26 19:23:19 -04:00
PREDICATE: simple-generic < standard-generic
2007-09-20 18:09:08 -04:00
"combination" word-prop standard-combination-# zero? ;
2008-03-26 19:23:19 -04:00
PREDICATE: hook-generic < generic
2007-09-20 18:09:08 -04:00
"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 ;