From: Joe Groff Date: Fri, 26 Jun 2009 21:31:20 +0000 (-0500) Subject: variants vocab for ADTs X-Git-Tag: 0.97~6041^2~8 X-Git-Url: https://gitweb.factorcode.org/gitweb.cgi?p=factor.git;a=commitdiff_plain;h=7a88c5ae8a884df266e335fd699db82701e97b56 variants vocab for ADTs --- diff --git a/core/classes/tuple/parser/parser.factor b/core/classes/tuple/parser/parser.factor index efb77e3274..6b106e48d9 100644 --- a/core/classes/tuple/parser/parser.factor +++ b/core/classes/tuple/parser/parser.factor @@ -33,7 +33,7 @@ ERROR: invalid-slot-name name ; : parse-long-slot-name ( -- spec ) [ scan , \ } parse-until % ] { } make ; -: parse-slot-name ( string/f -- ? ) +: parse-slot-name-delim ( end-delim string/f -- ? ) #! This isn't meant to enforce any kind of policy, just #! to check for mistakes of this form: #! @@ -43,12 +43,18 @@ ERROR: invalid-slot-name name ; { { [ dup not ] [ unexpected-eof ] } { [ dup { ":" "(" "<" "\"" "!" } member? ] [ invalid-slot-name ] } - { [ dup ";" = ] [ drop f ] } + { [ 2dup = ] [ drop f ] } [ dup "{" = [ drop parse-long-slot-name ] when , t ] - } cond ; + } cond nip ; + +: parse-tuple-slots-delim ( end-delim -- ) + dup scan parse-slot-name-delim [ parse-tuple-slots-delim ] [ drop ] if ; + +: parse-slot-name ( string/f -- ? ) + ";" swap parse-slot-name-delim ; : parse-tuple-slots ( -- ) - scan parse-slot-name [ parse-tuple-slots ] when ; + ";" parse-tuple-slots-delim ; : parse-tuple-definition ( -- class superclass slots ) CREATE-CLASS diff --git a/extra/variants/authors.txt b/extra/variants/authors.txt new file mode 100644 index 0000000000..f13c9c1e77 --- /dev/null +++ b/extra/variants/authors.txt @@ -0,0 +1 @@ +Joe Groff diff --git a/extra/variants/summary.txt b/extra/variants/summary.txt new file mode 100644 index 0000000000..142366be00 --- /dev/null +++ b/extra/variants/summary.txt @@ -0,0 +1 @@ +Syntax and combinators for manipulating algebraic data types diff --git a/extra/variants/variants-tests.factor b/extra/variants/variants-tests.factor new file mode 100644 index 0000000000..ef48b36b9c --- /dev/null +++ b/extra/variants/variants-tests.factor @@ -0,0 +1,21 @@ +! (c)2009 Joe Groff bsd license +USING: kernel math tools.test variants ; +IN: variants.tests + +VARIANT: list + nil + cons: { { first object } { rest list } } + ; + +[ t ] [ nil list? ] unit-test +[ t ] [ 1 nil list? ] unit-test +[ f ] [ 1 list? ] unit-test + +: list-length ( list -- length ) + { + { nil [ 0 ] } + { cons [ nip list-length 1 + ] } + } match ; + +[ 4 ] +[ 5 6 7 8 nil list-length ] unit-test diff --git a/extra/variants/variants.factor b/extra/variants/variants.factor new file mode 100644 index 0000000000..5cb786afde --- /dev/null +++ b/extra/variants/variants.factor @@ -0,0 +1,59 @@ +! (c)2009 Joe Groff bsd license +USING: accessors arrays classes classes.mixin classes.parser +classes.singleton classes.tuple classes.tuple.parser +classes.union combinators inverse kernel lexer macros make +parser quotations sequences slots splitting words ; +IN: variants + +PREDICATE: variant-class < mixin-class "variant" word-prop ; + +M: variant-class initial-value* + dup members [ no-initial-value ] + [ nip first dup word? [ initial-value* ] unless ] if-empty ; + +: define-tuple-class-and-boa-word ( class superclass slots -- ) + pick [ define-tuple-class ] dip + dup name>> "<" ">" surround create-in swap define-boa-word ; + +: define-variant-member ( member -- class ) + dup array? [ first3 pick [ define-tuple-class-and-boa-word ] dip ] [ dup define-singleton-class ] if ; + +: define-variant-class ( class members -- ) + [ [ define-mixin-class ] [ t "variant" set-word-prop ] [ ] tri ] dip + [ define-variant-member swap add-mixin-instance ] with each ; + +: parse-variant-tuple-member ( name -- member ) + create-class-in tuple + "{" expect + [ "}" parse-tuple-slots-delim ] { } make + 3array ; + +: parse-variant-member ( name -- member ) + ":" ?tail [ parse-variant-tuple-member ] [ create-class-in ] if ; + +: parse-variant-members ( -- members ) + [ scan dup ";" = not ] + [ parse-variant-member ] produce nip ; + +SYNTAX: VARIANT: + CREATE-CLASS + parse-variant-members + define-variant-class ; + +MACRO: unboa ( class -- ) + \ boa [ ] 2sequence [undo] ; + +GENERIC# (match-branch) 1 ( class quot -- class quot' ) + +M: singleton-class (match-branch) + \ drop prefix ; +M: object (match-branch) + over \ unboa [ ] 2sequence prepend ; + +: ?class ( object -- class ) + dup word? [ class ] unless ; + +MACRO: match ( branches -- ) + [ dup callable? [ first2 (match-branch) 2array ] unless ] map + [ \ dup \ ?class ] dip \ case [ ] 4sequence ; +