]> gitweb.factorcode.org Git - factor.git/commitdiff
tuples gracefully handle changing shape
authorSlava Pestov <slava@factorcode.org>
Thu, 10 Feb 2005 03:35:11 +0000 (03:35 +0000)
committerSlava Pestov <slava@factorcode.org>
Thu, 10 Feb 2005 03:35:11 +0000 (03:35 +0000)
TODO.FACTOR.txt
library/compiler/alien-types.factor
library/generic/generic.factor
library/generic/tuple.factor
library/io/ansi.factor
library/io/stdio.factor
library/syntax/parser.factor
library/test/tuple.factor
library/vocabularies.factor

index 95089dffbaddd94da9ba9a94c9b024c69f8d2cc4..0ebe2d393af2f40deceb5505d780280420817901 100644 (file)
@@ -1,6 +1,5 @@
 72/73:\r
 \r
-- tuples: gracefully handle changing shape\r
 - keep a list of getter/setter words\r
 - default constructor\r
 - move tuple to generic vocab\r
index a978f30d133327aa7b9bafceec2596f36f83cdcc..8ccdda177eaa5fccf71449ceec91e683ffa731c6 100644 (file)
@@ -53,13 +53,13 @@ namespaces parser strings words ;
 : define-getter ( offset type name -- )
     #! Define a word with stack effect ( alien -- obj ) in the
     #! current 'in' vocabulary.
-    "in" get create >r
+    create-in >r
     [ "getter" get ] bind cons r> swap define-compound ;
 
 : define-setter ( offset type name -- )
     #! Define a word with stack effect ( obj alien -- ) in the
     #! current 'in' vocabulary.
-    "set-" swap cat2 "in" get create >r
+    "set-" swap cat2 create-in >r
     [ "setter" get ] bind cons r> swap define-compound ;
 
 : define-field ( offset type name -- offset )
@@ -78,7 +78,7 @@ namespaces parser strings words ;
     #! Used for C functions that expect you to pass in a struct.
     [ <local-alien> ] cons
     [ "<" , "struct-name" get , ">" , ] make-string
-    "in" get create swap
+    create-in swap
     define-compound ;
 
 : define-struct-type ( width -- )
index 4aed76f502123028103282e592f345ed0a4603cf..a7f39e2e728dbdd004fe9ebfd17cf93b8e759f9d 100644 (file)
@@ -7,7 +7,7 @@ namespaces parser strings words vectors math math-internals ;
 ! A simple single-dispatch generic word system.
 
 : predicate-word ( word -- word )
-    word-name "?" cat2 "in" get create ;
+    word-name "?" cat2 create-in ;
 
 ! Terminology:
 ! - type: a datatype built in to the runtime, eg fixnum, word
index a52b6eb8063173f2ed23afaa9fa8e71be17ed8e5..7e4eb4f041c6fbb7e31573967446d5ad90bd1716 100644 (file)
@@ -29,15 +29,27 @@ kernel-internals math hashtables errors vectors ;
     over >r [ single-combination ] \ GENERIC: r> define-generic
     define-method ;
 
-: define-accessor ( word name n -- )
-    >r [ >r dup word-name , "-" , r> , ] make-string
-    "in" get create  r> [ slot ] cons define-tuple-generic ;
-
-: define-mutator ( word name n -- )
-    >r [ "set-" , >r dup word-name , "-" , r> , ] make-string
-    "in" get create  r> [ set-slot ] cons define-tuple-generic ;
-
-: define-field ( word name n -- )
+: accessor-word ( name tuple -- word )
+    [ word-name , "-" , , ] make-string
+    create-in ;
+
+: define-accessor ( tuple name n -- accessor )
+    #! Generic word with a method specializing on the tuple's
+    #! class that reads the right slot.
+    >r over accessor-word  r> [ slot ] cons
+    define-tuple-generic ;
+
+: mutator-word ( name tuple -- word )
+    [ "set-" , word-name , "-" , , ] make-string
+    create-in ;
+
+: define-mutator ( word name n -- mutator )
+    #! Generic word with a method specializing on the tuple's
+    #! class that writes to the right slot.
+    >r over mutator-word  r> [ set-slot ] cons
+    define-tuple-generic ;
+
+: define-slot ( word name n -- )
     over "delegate" = [
         pick over "delegate-field" set-word-property
     ] when
@@ -50,43 +62,54 @@ kernel-internals math hashtables errors vectors ;
     [ swap dup tuple? [ class eq? ] [ 2drop f ] ifte ] cons
     define-compound ;
 
-: define-tuple ( word fields -- )
-    2dup length 1 + "tuple-size" set-word-property
-    dup length [ 3 + ] project zip
-    [ uncons define-field ] each-with ;
-
 : begin-tuple ( word -- )
     dup intern-symbol
     dup tuple-predicate
     dup define-promise
     tuple "metaclass" set-word-property ;
 
+: check-shape ( word slots -- )
+    #! If the new list of slots is different from the previous,
+    #! forget the old definition.
+    >r "use" get search dup [
+        dup "slots" word-property r> = [
+            drop
+        ] [
+            forget
+        ] ifte
+    ] [
+        r> 2drop
+    ] ifte ;
+
+: define-slots ( tuple slots -- )
+    2dup "slots" set-word-property
+    2dup length 1 + "tuple-size" set-word-property
+    dup length [ 3 + ] project zip
+    [ uncons define-slot ] each-with ;
+
+: define-tuple ( tuple slots -- )
+    2dup check-shape
+    >r
+    create-in dup save-location
+    dup begin-tuple
+    r>
+    define-slots ;
+
 : TUPLE:
-    #! Followed by a tuple name, then field names, then ;
-    CREATE dup begin-tuple
+    #! Followed by a tuple name, then slot names, then ;
+    scan
     string-mode on
     [ string-mode off define-tuple ]
     f ; parsing
 
 : constructor-word ( word -- word )
-    word-name "<" swap ">" cat3 "in" get create ;
+    word-name "<" swap ">" cat3 create-in ;
 
 : tuple-constructor ( word def -- )
     over constructor-word >r
     [ swap literal, \ make-tuple , append, ] make-list
     r> swap define-compound ;
 
-: wrapper-constructor ( word -- quot )
-    "delegate-field" word-property [ set-slot ] cons
-    [ keep ] cons ;
-
-: WRAPPER:
-    #! A wrapper is a tuple whose only slot is a delegate slot.
-    CREATE dup begin-tuple
-    dup [ "delegate" ] define-tuple
-    dup wrapper-constructor
-    tuple-constructor ; parsing
-
 : C:
     #! Followed by a tuple name, then constructor code, then ;
     #! Constructor code executes with the empty tuple on the
index 3a47e40ae649a695ad3b714d6215164e282619ef..865b6a9e1e00d79be3c5e5dd0196805655014bca 100644 (file)
@@ -48,7 +48,9 @@ presentation generic ;
 : ansi-attr-string ( string style -- string )
     [ ansi-attrs , reset , ] make-string ;
 
-WRAPPER: ansi-stream
+TUPLE: ansi-stream delegate ;
+C: ansi-stream ( delegate -- stream )
+    [ set-ansi-stream-delegate ] keep ;
 
 M: ansi-stream fwrite-attr ( string style stream -- )
     >r [ default-style ] unless* ansi-attr-string r>
index bf63838666acea933054f0fc53231651881be2a4..c016f0018e8c52ec813d3c8d0ac546022d6346e3 100644 (file)
@@ -29,7 +29,9 @@ SYMBOL: stdio
         call stdio get stream>str
     ] with-stream ;
 
-WRAPPER: stdio-stream
+TUPLE: stdio-stream delegate ;
+C: stdio-stream ( delegate -- stream )
+    [ set-stdio-stream-delegate ] keep ;
 
 M: stdio-stream fauto-flush ( -- )
     stdio-stream-delegate fflush ;
index 245087faf6b748f4875af223f6580214da2cac80..d1223589a3e044bcb95ba8c3ab161f61a7ebbd48 100644 (file)
@@ -1,39 +1,8 @@
-! :folding=indent:collapseFolds=1:
-
-! $Id$
-!
-! Copyright (C) 2004, 2005 Slava Pestov.
-! 
-! Redistribution and use in source and binary forms, with or without
-! modification, are permitted provided that the following conditions are met:
-! 
-! 1. Redistributions of source code must retain the above copyright notice,
-!    this list of conditions and the following disclaimer.
-! 
-! 2. Redistributions in binary form must reproduce the above copyright notice,
-!    this list of conditions and the following disclaimer in the documentation
-!    and/or other materials provided with the distribution.
-! 
-! THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-! INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-! FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-! DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-! SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-! PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-! OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-! WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
+! Copyright (C) 2005 Slava Pestov.
+! See http://factor.sf.net/license.txt for BSD license.
 IN: parser
-USE: errors
-USE: kernel
-USE: lists
-USE: math
-USE: namespaces
-USE: strings
-USE: words
-USE: unparser
+USING: errors kernel lists math namespaces strings words
+unparser ;
 
 ! The parser uses a number of variables:
 ! line - the line being parsed
@@ -137,13 +106,17 @@ global [ string-mode off ] bind
     #! the parser is already line-tokenized.
     (until-eol) (until) ;
 
-: CREATE ( -- word )
-    scan "in" get create dup set-word
-    dup f "documentation" set-word-property
-    dup f "stack-effect" set-word-property
+: save-location ( word -- )
+    #! Remember where this word was defined.
+    dup set-word
     dup "line-number" get "line" set-word-property
-    dup "col"         get "col"  set-word-property
-    dup "file"        get "file" set-word-property ;
+    dup "col" get "col"  set-word-property
+    "file" get "file" set-word-property ;
+
+: create-in "in" get create ;
+
+: CREATE ( -- word )
+    scan create-in dup save-location ;
 
 : escape ( ch -- esc )
     [
index cd2e3ebe5e339b9609c9c0634384a859d3a01166..eea3af872ebe6e90bbd0539247074827d8da06de 100644 (file)
@@ -1,5 +1,5 @@
 IN: scratchpad
-USING: generic kernel test math ;
+USING: generic kernel test math parser ;
 
 TUPLE: rect x y w h ;
 C: rect
@@ -20,7 +20,9 @@ M: object delegation-test drop 3 ;
 TUPLE: quux-tuple ;
 C: quux-tuple ;
 M: quux-tuple delegation-test drop 4 ;
-WRAPPER: quuux-tuple
+TUPLE: quuux-tuple delegate ;
+C: quuux-tuple
+    [ set-quuux-tuple-delegate ] keep ;
 
 [ 3 ] [ <quux-tuple> <quuux-tuple> delegation-test ] unit-test
 
@@ -28,6 +30,24 @@ GENERIC: delegation-test-2
 TUPLE: quux-tuple-2 ;
 C: quux-tuple-2 ;
 M: quux-tuple-2 delegation-test-2 drop 4 ;
-WRAPPER: quuux-tuple-2
+TUPLE: quuux-tuple-2 delegate ;
+C: quuux-tuple-2
+    [ set-quuux-tuple-2-delegate ] keep ;
 
 [ 4 ] [ <quux-tuple-2> <quuux-tuple-2> delegation-test-2 ] unit-test
+
+! Make sure we handle changing shapes!
+
+[
+    100
+] [
+    TUPLE: point x y ;
+    C: point [ set-point-y ] keep [ set-point-x ] keep ;
+    
+    100 200 <point>
+    
+    ! Use eval to sequence parsing explicitly
+    "TUPLE: point y x ;" eval
+    
+    point-x
+] unit-test
index 55c21d280bf21d4f44ca90dc305a561c83463e02..595d20d79b34500aecb4ffae5edd1eae85640eaf 100644 (file)
@@ -57,7 +57,13 @@ IN: words USING: hashtables kernel lists namespaces strings ;
     #! Create a new word in a vocabulary. If the vocabulary
     #! already contains the word, the existing instance is
     #! returned.
-    2dup (search) [ nip ] [ (create) dup reveal ] ?ifte ;
+    2dup (search) [
+        nip
+        dup f "documentation" set-word-property
+        dup f "stack-effect" set-word-property
+    ] [
+        (create) dup reveal
+    ] ?ifte ;
 
 : forget ( word -- )
     #! Remove a word definition.