1 ! Copyright (C) 2006 Chris Double.
2 ! See http://factorcode.org/license.txt for BSD license.
4 ! Based on pattern matching code from Paul Graham's book 'On Lisp'.
5 USING: parser kernel words namespaces sequences tuples
6 combinators macros assocs math ;
11 : define-match-var ( name -- )
13 dup t "match-var" set-word-prop
14 dup [ get ] curry define ;
16 : define-match-vars ( seq -- )
17 [ define-match-var ] each ;
19 : MATCH-VARS: ! vars ...
20 ";" parse-tokens define-match-vars ; parsing
22 : match-var? ( symbol -- bool )
23 dup word? [ "match-var" word-prop ] [ drop f ] if ;
25 : set-match-var ( value var -- ? )
26 dup namespace key? [ get = ] [ set t ] if ;
28 : (match) ( value1 value2 -- matched? )
30 { [ dup match-var? ] [ set-match-var ] }
31 { [ over match-var? ] [ swap set-match-var ] }
32 { [ 2dup = ] [ 2drop t ] }
33 { [ 2dup [ _ eq? ] either? ] [ 2drop t ] }
34 { [ 2dup [ sequence? ] both? ] [
35 2dup [ length ] 2apply =
36 [ [ (match) ] 2all? ] [ 2drop f ] if ] }
37 { [ 2dup [ tuple? ] both? ]
38 [ [ tuple>array ] 2apply [ (match) ] 2all? ] }
42 : match ( value1 value2 -- bindings )
43 [ (match) ] H{ } make-assoc swap [ drop f ] unless ;
45 MACRO: match-cond ( assoc -- )
47 [ "Fall-through in match-cond" throw ]
50 >r [ dupd match ] curry r>
55 : replace-patterns ( object -- result )
57 { [ dup number? ] [ ] }
58 { [ dup match-var? ] [ get ] }
59 { [ dup sequence? ] [ [ replace-patterns ] map ] }
60 { [ dup tuple? ] [ tuple>array replace-patterns >tuple ] }
64 : match-replace ( object pattern1 pattern2 -- result )
66 match [ "Pattern does not match" throw ] unless*
67 [ replace-patterns ] bind ;