factor/basis/match/match.factor

86 lines
2.5 KiB
Factor
Raw Normal View History

2007-09-20 18:09:08 -04:00
! Copyright (C) 2006 Chris Double.
! See http://factorcode.org/license.txt for BSD license.
!
! Based on pattern matching code from Paul Graham's book 'On Lisp'.
2014-11-29 20:10:54 -05:00
USING: assocs classes.tuple combinators kernel lexer macros make
math namespaces parser sequences words ;
2007-09-20 18:09:08 -04:00
IN: match
SYMBOL: _
: define-match-var ( name -- )
create-word-in
2007-09-20 18:09:08 -04:00
dup t "match-var" set-word-prop
dup [ get ] curry ( -- value ) define-declared ;
2007-09-20 18:09:08 -04:00
: define-match-vars ( seq -- )
[ define-match-var ] each ;
SYNTAX: MATCH-VARS: ! vars ...
";" [ define-match-var ] each-token ;
2007-09-20 18:09:08 -04:00
: match-var? ( symbol -- bool )
dup word? [ "match-var" word-prop ] [ drop f ] if ;
2007-10-28 00:28:46 -04:00
: set-match-var ( value var -- ? )
2012-07-19 20:35:00 -04:00
building get ?at [ = ] [ ,, t ] if ;
2007-10-28 00:28:46 -04:00
2007-09-20 18:09:08 -04:00
: (match) ( value1 value2 -- matched? )
{
2007-10-28 00:28:46 -04:00
{ [ dup match-var? ] [ set-match-var ] }
{ [ over match-var? ] [ swap set-match-var ] }
2007-09-20 18:09:08 -04:00
{ [ 2dup = ] [ 2drop t ] }
{ [ 2dup [ _ eq? ] either? ] [ 2drop t ] }
{ [ 2dup [ sequence? ] both? ] [
2012-07-21 13:22:44 -04:00
2dup [ length ] same?
2007-09-20 18:09:08 -04:00
[ [ (match) ] 2all? ] [ 2drop f ] if ] }
{ [ 2dup [ tuple? ] both? ]
2008-03-29 21:36:58 -04:00
[ [ tuple>array ] bi@ [ (match) ] 2all? ] }
2007-09-20 18:09:08 -04:00
{ [ t ] [ 2drop f ] }
} cond ;
: match ( value1 value2 -- bindings )
2012-07-19 20:35:00 -04:00
[ (match) ] H{ } make swap [ drop f ] unless ;
2007-09-20 18:09:08 -04:00
MACRO: match-cond ( assoc -- quot )
2007-09-20 18:09:08 -04:00
<reversed>
[ "Fall-through in match-cond" throw ]
[
first2
2008-12-17 20:17:37 -05:00
[ [ dupd match ] curry ] dip
[ with-variables ] curry rot
2007-09-20 18:09:08 -04:00
[ ?if ] 2curry append
] reduce ;
: replace-patterns ( object -- result )
{
{ [ dup number? ] [ ] }
2007-09-20 18:09:08 -04:00
{ [ dup match-var? ] [ get ] }
{ [ dup sequence? ] [ [ replace-patterns ] map ] }
{ [ dup tuple? ] [ tuple>array replace-patterns >tuple ] }
2008-04-11 13:56:48 -04:00
[ ]
2007-09-20 18:09:08 -04:00
} cond ;
: match-replace ( object pattern1 pattern2 -- result )
2009-04-18 22:53:22 -04:00
[ match [ "Pattern does not match" throw ] unless* ] dip swap
[ replace-patterns ] with-variables ;
2014-11-29 20:10:54 -05:00
: ?rest ( seq -- tailseq/f )
[ f ] [ rest ] if-empty ;
: (match-first) ( seq pattern-seq -- bindings leftover/f )
2009-09-04 07:11:28 -04:00
2dup shorter? [ 2drop f f ] [
2dup length head over match
2014-11-29 20:10:54 -05:00
[ swap ?rest ] [ [ rest ] dip (match-first) ] ?if
] if ;
2012-07-19 17:38:22 -04:00
: match-first ( seq pattern-seq -- bindings )
(match-first) drop ;
: (match-all) ( seq pattern-seq -- )
2009-01-23 19:20:47 -05:00
[ nip ] [ (match-first) swap ] 2bi
2009-09-04 07:11:28 -04:00
[ , [ swap (match-all) ] [ drop ] if* ] [ 2drop ] if* ;
: match-all ( seq pattern-seq -- bindings-seq )
[ (match-all) ] { } make ;