Inefficient, experimental multi-methods implementation

db4
Slava Pestov 2008-01-06 00:07:12 -04:00
parent e84ad1f2ba
commit b61c41163b
1 changed files with 53 additions and 0 deletions

View File

@ -0,0 +1,53 @@
USING: kernel math sequences vectors classes combinators
generic.standard arrays words combinators.lib assocs parser ;
IN: multi-methods
: maximal-element ( seq quot -- n elt )
dupd [
swapd [ call 0 < ] 2curry subset empty?
] 2curry find [ "Topological sort failed" throw ] unless* ;
inline
: topological-sort ( seq quot -- newseq )
>r >vector [ dup empty? not ] r>
[ dupd maximal-element >r over delete-nth r> ] curry
[ ] unfold nip ; inline
: classes< ( seq1 seq2 -- -1/0/1 )
[
{
{ [ 2dup eq? ] [ 0 ] }
{ [ 2dup class< ] [ -1 ] }
{ [ 2dup swap class< ] [ 1 ] }
{ [ t ] [ 0 ] }
} cond 2nip
] 2map [ zero? not ] find nip 0 or ;
: multi-predicate ( classes -- quot )
dup length <reversed> [
>r "predicate" word-prop r>
(picker) swap append
] 2map [ && ] curry ;
: multi-dispatch-quot ( methods -- quot )
[ >r multi-predicate r> ] assoc-map
[ "No method" throw ] swap reverse alist>quot ;
: sorted-methods ( word -- methods )
"multi-methods" word-prop >alist
[ [ first ] 2apply classes< ] topological-sort ;
: make-generic ( word -- )
dup sorted-methods multi-dispatch-quot define ;
: GENERIC:
CREATE
dup H{ } clone "multi-methods" set-word-prop
make-generic ; parsing
: add-method ( quot classes word -- )
[ "multi-methods" word-prop set-at ] keep make-generic ;
: METHOD:
parse-definition unclip swap unclip swap spin
add-method ; parsing