]> gitweb.factorcode.org Git - factor.git/commitdiff
Merge up
authorErik Charlebois <erikcharlebois@gmail.com>
Thu, 18 Feb 2010 02:16:16 +0000 (18:16 -0800)
committerErik Charlebois <erikcharlebois@gmail.com>
Thu, 18 Feb 2010 02:16:16 +0000 (18:16 -0800)
41 files changed:
basis/classes/struct/struct-tests.factor
basis/classes/struct/struct.factor
basis/debugger/debugger.factor
basis/functors/backend/backend.factor
basis/functors/functors-tests.factor
basis/functors/functors.factor
basis/help/markup/markup.factor
basis/help/stylesheet/stylesheet.factor
basis/listener/listener-docs.factor
basis/math/vectors/simd/simd.factor
basis/prettyprint/prettyprint-tests.factor
basis/see/see.factor
basis/sequences/cords/cords.factor
basis/specialized-arrays/specialized-arrays.factor
basis/stack-checker/dependencies/dependencies.factor
basis/tools/deploy/backend/backend.factor
basis/tuple-arrays/tuple-arrays-docs.factor
basis/tuple-arrays/tuple-arrays-tests.factor
basis/tuple-arrays/tuple-arrays.factor
basis/typed/typed-docs.factor
basis/typed/typed-tests.factor
basis/typed/typed.factor
core/arrays/arrays.factor
core/bootstrap/syntax.factor
core/classes/parser/parser.factor
core/classes/tuple/tuple-docs.factor
core/classes/tuple/tuple-tests.factor
core/classes/tuple/tuple.factor
core/combinators/combinators.factor
core/generic/generic-docs.factor
core/io/pathnames/pathnames-docs.factor
core/parser/parser-tests.factor
core/syntax/syntax-docs.factor
core/syntax/syntax.factor
extra/benchmark/tuple-arrays/tuple-arrays.factor
extra/gpu/gpu-docs.factor
extra/gpu/gpu.factor [changed mode: 0644->0755]
extra/gpu/render/render.factor [changed mode: 0644->0755]
extra/gpu/shaders/shaders-docs.factor
extra/gpu/shaders/shaders.factor [changed mode: 0644->0755]
extra/gpu/state/state.factor [changed mode: 0644->0755]

index 2c0db93522b8e411695cd9fe034ab1c5183eced2..cb7e4ee2b085b9f344856bcccf930e31602651cb 100644 (file)
@@ -1,11 +1,11 @@
 ! (c)Joe Groff bsd license
 USING: accessors alien alien.c-types alien.data ascii
-assocs byte-arrays classes.struct classes.tuple.private
+assocs byte-arrays classes.struct classes.tuple.private classes.tuple
 combinators compiler.tree.debugger compiler.units destructors
 io.encodings.utf8 io.pathnames io.streams.string kernel libc
 literals math mirrors namespaces prettyprint
 prettyprint.config see sequences specialized-arrays system
-tools.test parser lexer eval layouts ;
+tools.test parser lexer eval layouts generic.single classes ;
 FROM: math => float ;
 QUALIFIED-WITH: alien.c-types c
 SPECIALIZED-ARRAY: char
@@ -338,13 +338,28 @@ STRUCT: struct-that's-a-word { x int } ;
 [
     "USE: classes.struct IN: classes.struct.tests TUPLE: not-a-struct ; S{ not-a-struct }"
     eval( -- value )
-] must-fail
+] [ error>> no-method? ] must-fail-with
 
 ! Subclassing a struct class should not be allowed
 [
-    "USE: classes.struct IN: classes.struct.tests STRUCT: a-struct { x int } ; TUPLE: not-a-struct < a-struct ;"
+    "USING: alien.c-types classes.struct ; IN: classes.struct.tests STRUCT: a-struct { x int } ; TUPLE: not-a-struct < a-struct ;"
     eval( -- )
-] must-fail
+] [ error>> bad-superclass? ] must-fail-with
+
+! Changing a superclass into a struct should reset the subclass
+TUPLE: will-become-struct ;
+
+TUPLE: a-subclass < will-become-struct ;
+
+[ f ] [ will-become-struct struct-class? ] unit-test
+
+[ will-become-struct ] [ a-subclass superclass ] unit-test
+
+[ ] [ "IN: classes.struct.tests USING: classes.struct alien.c-types ; STRUCT: will-become-struct { x int } ;" eval( -- ) ] unit-test
+
+[ t ] [ will-become-struct struct-class? ] unit-test
+
+[ tuple ] [ a-subclass superclass ] unit-test
 
 ! Remove c-type when struct class is forgotten
 [ ] [
index fae39cd229e42baadb61d4692cf60281be6824e8..a5711de609f67e83235ab8e89058865260d7cd57 100644 (file)
@@ -32,8 +32,6 @@ TUPLE: struct-bit-slot-spec < struct-slot-spec
 PREDICATE: struct-class < tuple-class
     superclass \ struct eq? ;
 
-M: struct-class valid-superclass? drop f ;
-
 SLOT: fields
 
 : struct-slots ( struct-class -- slots )
@@ -273,7 +271,7 @@ M: struct binary-zero? >c-ptr [ 0 = ] all? ;
     [ type>> c-type drop ] each ;
 
 : redefine-struct-tuple-class ( class -- )
-    [ dup class? [ forget-class ] [ drop ] if ] [ struct f define-tuple-class ] bi ;
+    [ struct f define-tuple-class ] [ make-final ] bi ;
 
 :: (define-struct-class) ( class slots offsets-quot -- )
     slots empty? [ struct-must-have-slots ] when
index 815304b21f9a8e9e779ba2f1233055a142fc4dc4..b6497c52a92c52d4f6ea941b5a0dcfa1ba767917 100644 (file)
@@ -194,7 +194,7 @@ M: not-a-tuple summary
     drop "Not a tuple" ;
 
 M: bad-superclass summary
-    drop "Tuple classes can only inherit from other tuple classes" ;
+    drop "Tuple classes can only inherit from non-final tuple classes" ;
 
 M: no-initial-value summary
     drop "Initial value must be provided for slots specialized to this class" ;
index dd3d891f7bd544bfa870b6bc9bb3fe51a1fd1a55..331864417e3577880f2735787aa323040e269c04 100644 (file)
@@ -1,6 +1,6 @@
 USING: accessors arrays assocs generic.standard kernel
 lexer locals.types namespaces parser quotations vocabs.parser
-words ;
+words classes.tuple ;
 IN: functors.backend
 
 DEFER: functor-words
@@ -27,7 +27,11 @@ SYNTAX: FUNCTOR-SYNTAX:
 
 : define* ( word def -- ) over set-word define ;
 
-: define-declared* ( word def effect -- ) pick set-word define-declared ;
+: define-declared* ( word def effect -- )
+    pick set-word define-declared ;
 
-: define-simple-generic* ( word effect -- ) over set-word define-simple-generic ;
+: define-simple-generic* ( word effect -- )
+    over set-word define-simple-generic ;
 
+: define-tuple-class* ( class superclass slots -- )
+    pick set-word define-tuple-class ;
index 544c2ed1e4a10ca2c69c38d1415588816d58a47e..c756d1b83d58aa774a74f3851a9f21fba07655e6 100644 (file)
@@ -1,5 +1,5 @@
-USING: classes.struct functors tools.test math words kernel
-multiline parser io.streams.string generic ;
+USING: classes.struct classes.tuple functors tools.test math
+words kernel multiline parser io.streams.string generic ;
 QUALIFIED-WITH: alien.c-types c
 IN: functors.tests
 
@@ -36,7 +36,7 @@ WW DEFINES ${W}${W}
 
 WHERE
 
-: WW ( a -- b ) \ W twice ; inline
+: WW ( a -- b ) \ W twice ;
 
 ;FUNCTOR
 
@@ -211,3 +211,44 @@ STRUCT: T-class
     }
 ] [ a-struct struct-slots ] unit-test
 
+<<
+
+FUNCTOR: define-an-inline-word ( W -- )
+
+W DEFINES ${W}
+W-W DEFINES ${W}-${W}
+
+WHERE
+
+: W ( -- ) ; inline
+: W-W ( -- ) W W ;
+
+;FUNCTOR
+
+"an-inline-word" define-an-inline-word
+
+>>
+
+[ t ] [ \ an-inline-word inline? ] unit-test
+[ f ] [ \ an-inline-word-an-inline-word inline? ] unit-test
+
+<<
+
+FUNCTOR: define-a-final-class ( T W -- )
+
+T DEFINES-CLASS ${T}
+W DEFINES ${W}
+
+WHERE
+
+TUPLE: T ; final
+
+: W ( -- ) ;
+
+;FUNCTOR
+
+"a-final-tuple" "a-word" define-a-final-class
+
+>>
+
+[ t ] [ a-final-tuple final-class? ] unit-test
index ac2e52f68eb415e940bd2b10cc8cc9383b37540b..1895c6e0f4b218b0c698f9e7a7ed47a830ad2549 100644 (file)
@@ -61,7 +61,10 @@ FUNCTOR-SYNTAX: TUPLE:
             make suffix!
         ]
     } case
-    \ define-tuple-class suffix! ;
+    \ define-tuple-class* suffix! ;
+
+FUNCTOR-SYNTAX: final
+    [ word make-final ] append! ;
 
 FUNCTOR-SYNTAX: SINGLETON:
     scan-param suffix!
index 75e65382435fa8c60259fe39c6b848e0199a4766..f951f30b2f673f8c156fe37e422bc9e8e884faa6 100644 (file)
@@ -129,8 +129,8 @@ ALIAS: $slot $snippet
     "Examples" $heading print-element ;
 
 : $example ( element -- )
-    1 cut* swap "\n" join dup <input> [
-        input-style get format nl print-element
+    1 cut* [ "\n" join ] bi@ over <input> [
+        [ print ] [ output-style get format ] bi*
     ] ($code) ;
 
 : $unchecked-example ( element -- )
index 8a119823cc367f314b3539e84f35e688646fd302..d5b783fef86534969225afb776dae7b00ed0a8c7 100644 (file)
@@ -80,8 +80,11 @@ H{
     { wrap-margin f }
 } code-style set-global
 
-SYMBOL: input-style
-H{ { font-style bold } } input-style set-global
+SYMBOL: output-style
+H{
+    { font-style bold }
+    { foreground COLOR: dark-red }
+} output-style set-global
 
 SYMBOL: url-style
 H{
index 77bec12c1a4418562079a6359a02c2f68485b318..bb014fef62719069029f70e6e4a0bc0737b8a6e4 100644 (file)
@@ -1,8 +1,9 @@
-USING: help.markup help.syntax kernel io system prettyprint continuations quotations ;
+USING: help.markup help.syntax kernel io system prettyprint
+continuations quotations vocabs.loader parser ;
 IN: listener
 
 ARTICLE: "listener-watch" "Watching variables in the listener"
-"The listener prints the concepts of the data and retain stacks after every expression. It can also print values of dynamic variables which are added to a watch list:"
+"The listener prints values of dynamic variables which are added to a watch list:"
 { $subsections visible-vars }
 "To add or remove a single variable:"
 { $subsections
@@ -14,7 +15,7 @@ ARTICLE: "listener-watch" "Watching variables in the listener"
     show-vars
     hide-vars
 }
-"Hiding all visible variables:"
+"Clearing the watch list:"
 { $subsections hide-all-vars } ;
 
 HELP: only-use-vocabs
@@ -46,21 +47,33 @@ HELP: hide-all-vars
 { $description "Removes all variables from the watch list." } ;
 
 ARTICLE: "listener" "The listener"
-"The listener evaluates Factor expressions read from a stream. The listener is the primary interface to the Factor runtime. Typically, you write Factor code in a text editor, then load it using the listener and test it."
+"The listener evaluates Factor expressions read from the input stream. Typically, you write Factor code in a text editor, load it from the listener by calling " { $link require } ", " { $link reload } " or " { $link run-file } ", and then test it from interactively."
 $nl
 "The classical first program can be run in the listener:"
 { $example "\"Hello, world\" print" "Hello, world" }
+"New words can also be defined in the listener:"
+{ $example
+    "USE: math.functions"
+    ": twice ( word -- ) [ execute ] [ execute ] bi ; inline"
+    "81 \\ sqrt twice ."
+    "3.0"
+}
 "Multi-line expressions are supported:"
 { $example "{ 1 2 3 } [\n    .\n] each" "1\n2\n3" }
-"The listener knows when to expect more input by looking at the height of the stack. Parsing words such as " { $link POSTPONE: { } " leave elements on the parser stack, and corresponding words such as " { $link POSTPONE: } } " pop them."
+"The listener will display the current contents of the datastack after every line of input."
 $nl
-"The listener will display the current contents of the datastack after every expression is evaluated. The listener can additionally watch dynamic variables:"
+"The listener can watch dynamic variables:"
 { $subsections "listener-watch" }
-"To start a nested listener:"
+"Nested listeners can be useful for testing code in other dynamic scopes. For example, when doing database maintanance using the " { $vocab-link "db.tuples" } " vocabulary, it can be useful to start a listener with a database connection:"
+{ $code
+    "USING: db db.sqlite listener ;"
+    "\"data.db\" <sqlite-db> [ listener ] with-db"
+}
+"Starting a nested listener:"
 { $subsections listener }
 "To exit a listener, invoke the " { $link return } " word."
 $nl
-"Multi-line quotations can be read independently of the rest of the listener:"
+"The listener's mechanism for reading multi-line expressions from the input stream can be called from user code:"
 { $subsections read-quot } ;
 
 ABOUT: "listener"
index acf13599c1f059552a8671ca323531e09370a7ce..a60026317d2319744d0de7c57cc7d88eb4ba3541 100644 (file)
@@ -251,7 +251,7 @@ BOA-EFFECT [ N "n" <array> { "v" } <effect> ]
 
 WHERE
 
-TUPLE: A < simd-128 ;
+TUPLE: A < simd-128 ; final
 
 M: A new-underlying    drop \ A boa ; inline
 M: A simd-rep          drop A-rep ; inline
index 8ba6e94a49539aed5f863d6af48059529a1728d0..ec0e20a393c727bbd6a4ae6b0b83aceef2bf8ee4 100644 (file)
@@ -362,3 +362,15 @@ TUPLE: tuple-with-initial-declared-slot { x integer initial: 123 } ;
 ] [
     [ \ tuple-with-initial-declared-slot see ] with-string-writer "\n" split
 ] unit-test
+
+TUPLE: final-tuple ; final
+
+[
+    {
+        "IN: prettyprint.tests"
+        "TUPLE: final-tuple ; final"
+        ""
+    }
+] [
+    [ \ final-tuple see ] with-string-writer "\n" split
+] unit-test
index 0d2388114a43c165cb67bbb217b1f10d50fb91cb..326e0512191a4d5829312aefbb0c8e6b6b6f3cf5 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2009 Slava Pestov.
+! Copyright (C) 2009, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors arrays assocs classes classes.builtin
 classes.intersection classes.mixin classes.predicate classes.singleton
@@ -182,14 +182,21 @@ M: array pprint-slot-name
     dup length 1 = [ first ] when
     pprint-slot-name ;
 
+: tuple-declarations. ( class -- )
+    \ final declaration. ;
+
+: superclass. ( class -- )
+    superclass dup tuple eq? [ drop ] [ "<" text pprint-word ] if ;
+
 M: tuple-class see-class*
     <colon \ TUPLE: pprint-word
-    dup pprint-word
-    dup superclass tuple eq? [
-        "<" text dup superclass pprint-word
-    ] unless
-    <block "slots" word-prop [ pprint-slot ] each block>
-    pprint-; block> ;
+    {
+        [ pprint-word ]
+        [ superclass. ]
+        [ <block "slots" word-prop [ pprint-slot ] each block> pprint-; ]
+        [ tuple-declarations. ]
+    } cleave
+    block> ;
 
 M: word see-class* drop ;
 
index fca005fa6e6847c5047dbd9d73d178a0f07ee08b..4a2d267a120ca7987b2e493877204b11cb84f6b9 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2008 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov, Joe Groff.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors assocs sequences sorting binary-search fry math
 math.order arrays classes combinators kernel functors math.functions
@@ -8,7 +8,7 @@ IN: sequences.cords
 MIXIN: cord
 
 TUPLE: generic-cord
-    { head read-only } { tail read-only } ;
+    { head read-only } { tail read-only } ; final
 INSTANCE: generic-cord cord
 
 M: cord length
@@ -34,7 +34,7 @@ T-cord DEFINES-CLASS ${C}
 WHERE
 
 TUPLE: T-cord
-    { head T read-only } { tail T read-only } ;
+    { head T read-only } { tail T read-only } ; final
 INSTANCE: T-cord cord
 
 M: T cord-append
index eda793ff22030e93478ff3c1fe59098abbf1fe1b..d3db93e7887a5449314a78b5249fae7c2e89a1e1 100644 (file)
@@ -47,7 +47,7 @@ WHERE
 
 TUPLE: A
 { underlying c-ptr read-only }
-{ length array-capacity read-only } ;
+{ length array-capacity read-only } ; final
 
 : <direct-A> ( alien len -- specialized-array ) A boa ; inline
 
index d995354a52f41636026cc5a4b3723b9ced69e626..df68fa8961b83ca8069dcb087115a1d3d94d3521 100644 (file)
@@ -1,7 +1,8 @@
 ! Copyright (C) 2009, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: assocs accessors classes.algebra fry generic kernel math
-namespaces sequences words sets combinators.short-circuit ;
+namespaces sequences words sets combinators.short-circuit
+classes.tuple ;
 FROM: classes.tuple.private => tuple-layout ;
 IN: stack-checker.dependencies
 
@@ -122,6 +123,15 @@ TUPLE: depends-on-flushable word ;
 M: depends-on-flushable satisfied?
     word>> flushable? ;
 
+TUPLE: depends-on-final class ;
+
+: depends-on-final ( word -- )
+    [ depends-on-conditionally ]
+    [ \ depends-on-final add-conditional-dependency ] bi ;
+
+M: depends-on-final satisfied?
+    class>> final-class? ;
+
 : init-dependencies ( -- )
     H{ } clone dependencies set
     H{ } clone generic-dependencies set
index fe63071998613d2863e51040bc2e10eb88bd2bdb..9f25808c9e657ed07039c4063d733db042a8a547 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2007, 2009 Slava Pestov.
+! Copyright (C) 2007, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: namespaces make continuations.private kernel.private init
 assocs kernel vocabs words sequences memory io system arrays
@@ -19,13 +19,12 @@ TUPLE: vocab-manifest vocabs libraries ;
 : copy-resources ( manifest name dir -- )
     append-path swap vocabs>> [ copy-vocab-resources ] with each ;
 
-ERROR: cant-deploy-library-file library ;
-<PRIVATE
+ERROR: can't-deploy-library-file library ;
+
 : copy-library ( dir library -- )
     dup find-library-file
-    [ nip swap over file-name append-path copy-file ]
-    [ cant-deploy-library-file ] if* ;
-PRIVATE>
+    [ swap over file-name append-path copy-file ]
+    [ can't-deploy-library-file ] ?if ;
 
 : copy-libraries ( manifest name dir -- )
     append-path swap libraries>> [ copy-library ] with each ;
index 5e70e15aa7bbe4bafecdaed81affb588cedbde29..72a5ae4df329236d8f9cb0c8ec9bbee2c242e474 100644 (file)
@@ -3,20 +3,24 @@ USING: help.markup help.syntax sequences ;
 
 HELP: TUPLE-ARRAY:
 { $syntax "TUPLE-ARRAY: class" }
+{ $values { "class" "a final tuple class" } }
 { $description "Generates a new data type in the current vocabulary named " { $snippet { $emphasis "class" } "-array" } " for holding instances of " { $snippet "class" } ", which must be a tuple class word. Together with the class itself, this also generates words named " { $snippet "<" { $emphasis "class" } "-array>" } " and " { $snippet ">" { $emphasis "class" } "-array" } ", for creating new instances of this tuple array type." } ;
 
 ARTICLE: "tuple-arrays" "Tuple arrays"
-"The " { $vocab-link "tuple-arrays" } " vocabulary implements space-efficient unboxed tuple arrays. Whereas an ordinary array of tuples would consist of pointers to heap-allocated objects, a tuple array stores its elements inline. Calling " { $link nth } " copies an element into a new tuple, and calling " { $link set-nth } " copies an existing tuple's slots into an array."
+"The " { $vocab-link "tuple-arrays" } " vocabulary implements space-efficient unboxed tuple arrays. Whereas an ordinary array of tuples would consist of references to heap-allocated objects, a tuple array stores its elements as values."
 $nl
-"Since value semantics differ from reference semantics, it is best to use tuple arrays with tuples where all slots are declared " { $link read-only } "."
+"Calling " { $link nth } " copies an element into a new tuple, and calling " { $link set-nth } " copies an existing tuple's slots into an array."
+$nl
+"Since value semantics are incompatible with inheritance, the base type of a tuple array must be declared " { $link POSTPONE: final } ". A best practice that is not enforced is to have all slots in the tuple declared " { $link read-only } "."
+$nl
+"Tuple arrays do not get updated if tuples are redefined to add or remove slots, so caution should be exercised when doing interactive development on code that uses tuple arrays."
 $nl
-"Tuple arrays should not be used with inheritance; storing an instance of a subclass in a tuple array will slice off the subclass slots, and getting the same value out again will yield an instance of the superclass. Also, tuple arrays do not get updated if tuples are redefined to add or remove slots, so caution should be exercised when doing interactive development on code that uses tuple arrays."
 { $subsections POSTPONE: TUPLE-ARRAY: }
 "An example:"
 { $example
   "USE: tuple-arrays"
   "IN: scratchpad"
-  "TUPLE: point x y ;"
+  "TUPLE: point x y ; final"
   "TUPLE-ARRAY: point"
   "{ T{ point f 1 2 } T{ point f 1 3 } T{ point f 2 3 } } >point-array first short."
   "T{ point f 1 2 }"
index 2eeae20aa1d2b0cf1b57c7cea7350a52acc4efb7..0fbf0eeaa017d47ebf84436e7b75af9ce90a73ff 100644 (file)
@@ -1,9 +1,9 @@
 USING: tuple-arrays sequences tools.test namespaces kernel
-math accessors ;
+math accessors classes.tuple eval ;
 IN: tuple-arrays.tests
 
 SYMBOL: mat
-TUPLE: foo bar ;
+TUPLE: foo bar ; final
 C: <foo> foo
 TUPLE-ARRAY: foo
 
@@ -18,15 +18,27 @@ TUPLE-ARRAY: foo
 [ T{ foo } ] [ mat get first ] unit-test
 [ T{ foo f 1 } ] [ T{ foo f 1 } 0 mat get [ set-nth ] keep first ] unit-test
 
-TUPLE: baz { bing integer } bong ;
+TUPLE: baz { bing integer } bong ; final
 TUPLE-ARRAY: baz
 
 [ 0 ] [ 1 <baz-array> first bing>> ] unit-test
 [ f ] [ 1 <baz-array> first bong>> ] unit-test
 
-TUPLE: broken x ;
+TUPLE: broken x ; final
 : broken ( -- ) ;
 
 TUPLE-ARRAY: broken
 
-[ 100 ] [ 100 <broken-array> length ] unit-test
\ No newline at end of file
+[ 100 ] [ 100 <broken-array> length ] unit-test
+
+! Can't define a tuple array for a non-tuple class
+[ "IN: tuple-arrays.tests USING: tuple-arrays words ; TUPLE-ARRAY: word" eval( -- ) ]
+[ error>> not-a-tuple? ]
+must-fail-with
+
+! Can't define a tuple array for a non-final class
+TUPLE: non-final x ;
+
+[ "IN: tuple-arrays.tests USE: tuple-arrays TUPLE-ARRAY: non-final" eval( -- ) ]
+[ error>> not-final? ]
+must-fail-with
\ No newline at end of file
index aea51f7820f54cc0f0ca80318069dc93e97e12a2..1a3091c1e233256f542e4b97be2572d7d6bf6926 100644 (file)
@@ -1,11 +1,13 @@
-! Copyright (C) 2009 Slava Pestov.
+! Copyright (C) 2009, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors arrays combinators.smart fry functors kernel
 kernel.private macros sequences combinators sequences.private
-stack-checker parser math classes.tuple.private ;
+stack-checker parser math classes.tuple classes.tuple.private ;
 FROM: inverse => undo ;
 IN: tuple-arrays
 
+ERROR: not-final class ;
+
 <PRIVATE
 
 MACRO: boa-unsafe ( class -- quot ) tuple-layout '[ _ <tuple-boa> ] ;
@@ -29,6 +31,13 @@ MACRO: write-tuple ( class -- quot )
     [ tuple-arity iota <reversed> [ '[ [ _ ] dip set-nth-unsafe ] ] map '[ _ cleave ] ]
     bi '[ _ dip @ ] ;
 
+: check-final ( class -- )
+    {
+        { [ dup tuple-class? not ] [ not-a-tuple ] }
+        { [ dup final-class? not ] [ not-final ] }
+        [ drop ]
+    } cond ;
+
 PRIVATE>
 
 FUNCTOR: define-tuple-array ( CLASS -- )
@@ -43,6 +52,8 @@ CLASS-array? IS ${CLASS-array}?
 
 WHERE
 
+CLASS check-final
+
 TUPLE: CLASS-array
 { seq array read-only }
 { n array-capacity read-only }
index 0b6838379c14aac553599e49228c3285c898c4dc..c6f80a48bcdb6182d7f8aa249a687f745f4598cf 100644 (file)
@@ -58,10 +58,18 @@ HELP: output-mismatch-error
 
 ARTICLE: "typed" "Strongly-typed word definitions"
 "The Factor compiler supports advanced compiler optimizations that take advantage of the type information it can glean from source code. The " { $vocab-link "typed" } " vocabulary provides syntax that allows words to provide checked type information about their inputs and outputs and improve the performance of compiled code."
+$nl
+"Parameters and return values of typed words where the type is declared to be a " { $link POSTPONE: final } " tuple class with all slots " { $link read-only } " are passed by value."
 { $subsections
     POSTPONE: TYPED:
     POSTPONE: TYPED::
+}
+"Defining typed words at run time:"
+{ $subsections
     define-typed
+}
+"Errors:"
+{ $subsections
     input-mismatch-error
     output-mismatch-error
 } ;
index f7b853cff796911ab36b3655984c3dc4f5cf3218..7f984ccaf25d49fd6a823764ab4e60f995d6b87b 100644 (file)
@@ -14,8 +14,8 @@ TYPED: fix+ ( a: fixnum b: fixnum -- c: fixnum )
 most-positive-fixnum neg 1 - 1quotation
 [ most-positive-fixnum 1 fix+ ] unit-test
 
-TUPLE: tweedle-dee ;
-TUPLE: tweedle-dum ;
+TUPLE: tweedle-dee ; final
+TUPLE: tweedle-dum ; final
 
 TYPED: dee ( x: tweedle-dee -- y )
     drop \ tweedle-dee ;
@@ -39,11 +39,11 @@ TYPED:: f+locals ( a: float b: float -- c: float )
 
 TUPLE: unboxable
     { x fixnum read-only }
-    { y fixnum read-only } ;
+    { y fixnum read-only } ; final
 
 TUPLE: unboxable2
     { u unboxable read-only }
-    { xy fixnum read-only } ;
+    { xy fixnum read-only } ; final
 
 TYPED: unboxy ( in: unboxable -- out: unboxable2 )
     dup [ x>> ] [ y>> ] bi - unboxable2 boa ;
@@ -63,7 +63,7 @@ IN: typed.tests
 TUPLE: unboxable
     { x fixnum read-only }
     { y fixnum read-only }
-    { z float read-only } ;
+    { z float read-only } ; final
 """ eval( -- )
 
 """
@@ -79,13 +79,15 @@ TYPED: no-inputs ( -- out: integer )
 [ 1 ] [ no-inputs ] unit-test
 
 TUPLE: unboxable3
-    { x read-only } ;
+    { x read-only } ; final
 
 TYPED: no-inputs-unboxable-output ( -- out: unboxable3 )
     T{ unboxable3 } ;
 
 [ T{ unboxable3 } ] [ no-inputs-unboxable-output ] unit-test
 
+[ f ] [ no-inputs-unboxable-output no-inputs-unboxable-output eq? ] unit-test
+
 SYMBOL: buh
 
 TYPED: no-outputs ( x: integer -- )
@@ -97,3 +99,26 @@ TYPED: no-outputs-unboxable-input ( x: unboxable3 -- )
     buh set ;
 
 [ T{ unboxable3 } ] [ T{ unboxable3 } no-outputs-unboxable-input buh get ] unit-test
+
+[ f ] [
+    T{ unboxable3 } no-outputs-unboxable-input buh get
+    T{ unboxable3 } no-outputs-unboxable-input buh get
+    eq?
+] unit-test
+
+! Reported by littledan
+TUPLE: superclass { x read-only } ;
+TUPLE: subclass < superclass { y read-only } ; final
+
+TYPED: unbox-fail ( a: superclass -- ? ) subclass? ;
+
+[ t ] [ subclass new unbox-fail ] unit-test
+
+! If a final class becomes non-final, typed words need to be recompiled
+TYPED: recompile-fail ( a: subclass -- ? ) buh get eq? ;
+
+[ f ] [ subclass new [ buh set ] [ recompile-fail ] bi ] unit-test
+
+[ ] [ "IN: typed.tests TUPLE: subclass < superclass { y read-only } ;" eval( -- ) ] unit-test
+
+[ t ] [ subclass new [ buh set ] [ recompile-fail ] bi ] unit-test
index e71196e3eeb274be9e75ca6666d90fc022344578..8a85ca1afbd4256199db1f233d7fe04ca86651a9 100644 (file)
@@ -20,6 +20,7 @@ PREDICATE: typed-word < word "typed-word" word-prop ;
     {
         [ all-slots empty? not ]
         [ immutable-tuple-class? ]
+        [ final-class? ]
     } 1&& ;
 
 ! typed inputs
@@ -30,9 +31,14 @@ PREDICATE: typed-word < word "typed-word" word-prop ;
 : input-mismatch-quot ( word types -- quot )
     [ input-mismatch-error ] 2curry ;
 
+: depends-on-unboxing ( class -- )
+    [ dup tuple-layout depends-on-tuple-layout ]
+    [ depends-on-final ]
+    bi ;
+
 : (unboxer) ( type -- quot )
     dup unboxable-tuple-class? [
-        dup dup tuple-layout depends-on-tuple-layout
+        dup depends-on-unboxing
         all-slots [
             [ name>> reader-word 1quotation ]
             [ class>> (unboxer) ] bi compose
@@ -52,7 +58,7 @@ PREDICATE: typed-word < word "typed-word" word-prop ;
 : (unboxed-types) ( type -- types )
     dup unboxable-tuple-class?
     [
-        dup dup tuple-layout depends-on-tuple-layout
+        dup depends-on-unboxing
         all-slots [ class>> (unboxed-types) ] map concat
     ]
     [ 1array ] if ;
@@ -81,7 +87,7 @@ DEFER: make-boxer
 : boxer ( type -- quot )
     dup unboxable-tuple-class?
     [
-        dup dup tuple-layout depends-on-tuple-layout
+        dup depends-on-unboxing
         [ all-slots [ class>> ] map make-boxer ]
         [ [ boa ] curry ]
         bi compose
index fa4d4b2f6951d0938d557edd49ae89899a4246e0..62a0774444887ff59079ee81e9edb889b7da1aa8 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2005, 2008 Slava Pestov.
+! Copyright (C) 2005, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors kernel kernel.private math math.private
 sequences sequences.private ;
@@ -9,24 +9,16 @@ M: array length length>> ; inline
 M: array nth-unsafe [ >fixnum ] dip array-nth ; inline
 M: array set-nth-unsafe [ >fixnum ] dip set-array-nth ; inline
 M: array resize resize-array ; inline
-
-: >array ( seq -- array ) { } clone-like ;
-
+M: array equal? over array? [ sequence= ] [ 2drop f ] if ;
 M: object new-sequence drop 0 <array> ; inline
-
 M: f new-sequence drop [ f ] [ 0 <array> ] if-zero ; inline
 
-M: array equal?
-    over array? [ sequence= ] [ 2drop f ] if ;
-
 INSTANCE: array sequence
 
+: >array ( seq -- array ) { } clone-like ;
 : 1array ( x -- array ) 1 swap <array> ; inline
-
 : 2array ( x y -- array ) { } 2sequence ; inline
-
 : 3array ( x y z -- array ) { } 3sequence ; inline
-
 : 4array ( w x y z -- array ) { } 4sequence ; inline
 
 PREDICATE: pair < array length 2 number= ;
index bb159f04df985a28c2826e6623cdf5ac2f5ac7f2..1870f4ac1bc5ad5e2a1ed33cddd20601a0c2f99b 100644 (file)
@@ -49,6 +49,7 @@ IN: bootstrap.syntax
         "SYMBOLS:"
         "CONSTANT:"
         "TUPLE:"
+        "final"
         "SLOT:"
         "T{"
         "UNION:"
index 8233d8cff367d2fd63ad2dbaa7bd01df88aa61b4..41ce32105da525f70528dc4923e3c4bb4e3faaf6 100644 (file)
@@ -8,8 +8,9 @@ IN: classes.parser
 
 : create-class-in ( string -- word )
     current-vocab create
+    dup set-word
     dup save-class-location
-    dup create-predicate-word dup set-word save-location ;
+    dup create-predicate-word save-location ;
 
 : CREATE-CLASS ( -- word )
     scan create-class-in ;
index 0fd790749231064b31d7b8a6520ad57385edc992..7f6078e321f72f9e194dfa2da258c24e14cc428c 100644 (file)
@@ -191,6 +191,8 @@ $nl
     "tuple-inheritance-example"
     "tuple-inheritance-anti-example"
 } 
+"Declaring a tuple class final prohibits other classes from subclassing it:"
+{ $subsections POSTPONE: final }
 { $see-also "call-next-method" "parametrized-constructors" "unions" "mixins" } ;
 
 ARTICLE: "tuple-introspection" "Tuple introspection"
@@ -440,4 +442,7 @@ HELP: boa
 { $values { "..." "slot values" } { "class" tuple-class } { "tuple" tuple } }
 { $description "Creates a new instance of " { $snippet "class" } " and fill in the slots from the stack, with the top-most stack element being stored in the right-most slot." }
 { $notes "The name " { $snippet "boa" } " is shorthand for “by order of arguments”, and “BOA constructor” is a pun on “boa constrictor”." }
-{ $errors "Throws an error if the slot values do not match class declarations on slots (see " { $link "tuple-declarations" } ")." } ;
+{ $errors "Throws an error if the slot values do not match class declarations on slots (see" { $link "tuple-declarations" } ")." } ;
+
+HELP: bad-superclass
+{ $error-description "Thrown if an attempt is made to subclass a class that is not a tuple class, or a tuple class declared " { $link POSTPONE: final } "." } ;
index 36d402c61dbec55d849e9b42a50bc566c07c025f..276c6b407c1c7fecca57b00427203954dc7ad1c2 100644 (file)
@@ -770,3 +770,30 @@ TUPLE: tuple-predicate-redefine-test ;
 [ ] [ "IN: classes.tuple.tests TUPLE: tuple-predicate-redefine-test ;" eval( -- ) ] unit-test
 
 [ t ] [ \ tuple-predicate-redefine-test? predicate? ] unit-test
+
+! Final classes
+TUPLE: final-superclass ;
+TUPLE: final-subclass < final-superclass ;
+
+[ final-superclass ] [ final-subclass superclass ] unit-test
+
+! Making the superclass final should change the superclass of the subclass
+[ ] [ "IN: classes.tuple.tests TUPLE: final-superclass ; final" eval( -- ) ] unit-test
+
+[ tuple ] [ final-subclass superclass ] unit-test
+
+[ f ] [ \ final-subclass final-class? ] unit-test
+
+! Subclassing a final class should fail
+[ "IN: classes.tuple.tests TUPLE: final-subclass < final-superclass ;" eval( -- ) ]
+[ error>> bad-superclass? ] must-fail-with
+
+! Making a final class non-final should work
+[ ] [ "IN: classes.tuple.tests TUPLE: final-superclass ;" eval( -- ) ] unit-test
+
+[ ] [ "IN: classes.tuple.tests TUPLE: final-subclass < final-superclass ; final" eval( -- ) ] unit-test
+
+! Changing a superclass should not change the final status of a subclass
+[ ] [ "IN: classes.tuple.tests TUPLE: final-superclass x ;" eval( -- ) ] unit-test
+
+[ t ] [ \ final-subclass final-class? ] unit-test
index 363c2879e98dbcc43a0c256376d302d91cc7f7b1..64c34d221ad1f0c8de77251f04459343018cbb93 100644 (file)
@@ -93,6 +93,14 @@ ERROR: bad-superclass class ;
         ] [ 2drop f ] if
     ] [ 2drop f ] if ; inline
 
+GENERIC: final-class? ( class -- ? )
+
+M: tuple-class final-class? "final" word-prop ;
+
+M: builtin-class final-class? tuple eq? not ;
+
+M: class final-class? drop t ;
+
 <PRIVATE
 
 : tuple-predicate-quot/1 ( class -- quot )
@@ -238,16 +246,8 @@ M: tuple-class update-class
     [ [ "slots" word-prop ] dip = ]
     bi-curry* bi and ;
 
-GENERIC: valid-superclass? ( class -- ? )
-
-M: tuple-class valid-superclass? drop t ;
-
-M: builtin-class valid-superclass? tuple eq? ;
-
-M: class valid-superclass? drop f ;
-
 : check-superclass ( superclass -- )
-    dup valid-superclass? [ bad-superclass ] unless drop ;
+    dup final-class? [ bad-superclass ] when drop ;
 
 GENERIC# (define-tuple-class) 2 ( class superclass slots -- )
 
@@ -261,6 +261,13 @@ GENERIC# (define-tuple-class) 2 ( class superclass slots -- )
         read-only suffix
     ] map ;
 
+: reset-final ( class -- )
+    dup final-class? [
+        [ f "final" set-word-prop ]
+        [ changed-conditionally ]
+        bi
+    ] [ drop ] if ;
+
 PRIVATE>
 
 : define-tuple-class ( class superclass slots -- )
@@ -268,10 +275,18 @@ PRIVATE>
     over prepare-slots
     (define-tuple-class) ;
 
+GENERIC: make-final ( class -- )
+
+M: tuple-class make-final
+    [ dup class-usage keys ?metaclass-changed ]
+    [ t "final" set-word-prop ]
+    bi ;
+
 M: word (define-tuple-class)
     define-new-tuple-class ;
 
 M: tuple-class (define-tuple-class)
+    pick reset-final
     3dup tuple-class-unchanged?
     [ 2drop ?define-symbol ] [ redefine-tuple-class ] if ;
 
@@ -301,7 +316,7 @@ M: tuple-class reset-class
         ] with each
     ] [
         [ call-next-method ]
-        [ { "layout" "slots" "boa-check" "prototype" } reset-props ]
+        [ { "layout" "slots" "boa-check" "prototype" "final" } reset-props ]
         bi
     ] bi ;
 
index 95b62fc3f3e6f9a4b3a78efe99d52c92864d85c5..7b9481825bdd8a68cbb08822bd8ed9ad59d54bfa 100644 (file)
@@ -5,6 +5,10 @@ kernel kernel.private math assocs quotations vectors
 hashtables sorting words sets math.order make ;
 IN: combinators
 
+! Most of these combinators have compile-time expansions in
+! the optimizing compiler. See stack-checker.transforms and
+! compiler.tree.propagation.call-effect
+
 <PRIVATE
 
 : call-effect-unsafe ( quot effect -- ) drop call ;
@@ -17,7 +21,7 @@ M: object throw
 
 PRIVATE>
 
-ERROR: wrong-values quot effect ;
+ERROR: wrong-values quot call-site ;
 
 ! We can't USE: effects here so we forward reference slots instead
 SLOT: in
index 3a9314fb5645016729ddeab0f0c75598aae41e67..8d4f1f61a5fe94295c56b511d612f938b66a7a2a 100644 (file)
@@ -166,7 +166,13 @@ HELP: create-method
 HELP: (call-next-method)
 { $values { "method" method } }
 { $description "Low-level word implementing " { $link POSTPONE: call-next-method } "." }
-{ $notes "In most cases, " { $link POSTPONE: call-next-method } " should be used instead." } ;
+{ $notes
+    "The " { $link POSTPONE: call-next-method } " word parses into this word. The following are equivalent:"
+    { $code
+        "M: class generic call-next-method ;"
+        "M: class generic M\\ class generic (call-next-method) ;"
+    }
+} ;
 
 HELP: no-next-method
 { $error-description "Thrown by " { $link POSTPONE: call-next-method } " if the current method is already the least specific method." }
index 8dacef6f8c5699f0277281a0312da233f104761b..cc637b59c353f89345eabf994557d8747933e23a 100644 (file)
@@ -92,7 +92,7 @@ HELP: normalize-path
 { $values { "path" "a pathname string" } { "path'" "a new pathname string" } }
 { $description "Prepends the " { $link current-directory } " to the pathname, resolves a " { $snippet "resource:" } " or " { $snippet "vocab:" } " prefix, if present (see " { $link "io.pathnames.special" } "). Also converts the path into a UNC path on Windows." }
 { $notes "High-level words, such as " { $link <file-reader> } " and " { $link delete-file } " call this word for you. It only needs to be called directly when passing pathnames to C functions or external processes. This is because Factor does not use the operating system's notion of a current directory, and instead maintains its own dynamically-scoped " { $link current-directory } " variable." }
-{ $notes "On Windows NT platforms, this word does prepends the Unicode path prefix." }
+{ $notes "On Windows NT platforms, this word prepends the Unicode path prefix." }
 { $examples
   "For example, if you create a file named " { $snippet "data.txt" } " in the current directory, and wish to pass it to a process, you must normalize it:"
   { $code
index f30eb686840470841b32f7c3fafe09003af957b2..266a65b957b7cae55b02c158116dd4f72a2415cf 100644 (file)
@@ -339,7 +339,7 @@ IN: parser.tests
 ] unit-test
 
 [ t ] [
-    "foo?" "parser.tests" lookup word eq?
+    "foo" "parser.tests" lookup word eq?
 ] unit-test
 
 [ ] [
index 8ad608418833c60406bb9f5d5c7b06c5a347ccd2..4a1af4c57808ccd3852c7682a6611ef689687d54 100644 (file)
@@ -792,6 +792,10 @@ $nl
     { $code "TUPLE: person" "{ age integer initial: 0 }" "{ department string initial: \"Marketing\" }" "manager ;" }
 } ;
 
+HELP: final
+{ $syntax "TUPLE: ... ; final" }
+{ $description "Declares the most recently defined word as a final tuple class which cannot be subclassed. Attempting to subclass a final class raises a " { $link bad-superclass } " error." } ;
+
 HELP: initial:
 { $syntax "TUPLE: ... { slot initial: value } ... ;" }
 { $values { "slot" "a slot name" } { "value" "any literal" } }
index cf2c49fff989c22b20796d3ad5e1a0d76ae70a2f..0b5b32e289174a7336a8d64382c104f76af644e4 100644 (file)
@@ -204,6 +204,10 @@ IN: bootstrap.syntax
         parse-tuple-definition define-tuple-class
     ] define-core-syntax
 
+    "final" [
+        word make-final
+    ] define-core-syntax
+
     "SLOT:" [
         scan define-protocol-slot
     ] define-core-syntax
index 701db7713591de56154ca5c6a02218aa554ab84c..80c31553c1dace5fcbf90f46e0ca1c94cf9c6445 100644 (file)
@@ -1,10 +1,10 @@
-! Copyright (C) 2009 Slava Pestov.
+! Copyright (C) 2009, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel math math.functions tuple-arrays accessors fry sequences
 prettyprint ;
 IN: benchmark.tuple-arrays
 
-TUPLE: point { x float } { y float } { z float } ;
+TUPLE: point { x float } { y float } { z float } ; final
 
 TUPLE-ARRAY: point
 
index 3c0c24e97eeeab05bb821ad51438db350f390a42..103e0c60a13a118846663bcce6cfe44c7b978f2c 100644 (file)
@@ -42,6 +42,6 @@ ARTICLE: "gpu-summary" "GPU-accelerated rendering"
     "gpu.shaders"
     "gpu.render"
 }
-"The library is built on top of the OpenGL API, but it aims to be complete enough that raw OpenGL calls are never needed. OpenGL 2.0 with the vertex array object extension (" { $snippet "GL_APPLE_vertex_array_object" } " or " { $snippet "GL_ARB_vertex_array_object" } ") is required. Some features require later OpenGL versions or additional extensions; these requirements are documented alongside individual words. To make full use of the library, an OpenGL 3.1 or later implementation is recommended." ;
+"The library is built on top of the OpenGL API, but it aims to be complete enough that raw OpenGL calls are never needed. OpenGL 2.0 is required. Some features require later OpenGL versions or additional extensions; these requirements are documented alongside individual words. To make full use of the library, an OpenGL 3.1 or later implementation is recommended." ;
 
 ABOUT: "gpu-summary"
old mode 100644 (file)
new mode 100755 (executable)
index 6a61e2e..1d02b3f
@@ -9,10 +9,12 @@ TUPLE: gpu-object < identity-tuple handle ;
 VARIANT: gpu-api
     opengl-2 opengl-3 ;
 
+SYMBOL: has-vertex-array-objects?
+
 : set-gpu-api ( -- )
     "2.0" require-gl-version
     "3.0" { { "GL_ARB_vertex_array_object" "GL_APPLE_vertex_array_object" } }
-    require-gl-version-or-extensions
+    has-gl-version-or-extensions? has-vertex-array-objects? set-global
     "3.0" has-gl-version? opengl-3 opengl-2 ? gpu-api set-global ;
 
 HOOK: init-gpu-api gpu-api ( -- )
old mode 100644 (file)
new mode 100755 (executable)
index 1d4813a..2b7d75a
@@ -520,9 +520,6 @@ SYNTAX: UNIFORM-TUPLE:
 
 <PRIVATE 
 
-: bind-vertex-array ( vertex-array -- )
-    handle>> glBindVertexArray ;
-
 : bind-unnamed-output-attachments ( framebuffer attachments -- )
     [ gl-attachment ] with map
     dup length 1 =
@@ -567,7 +564,7 @@ UNION: transform-feedback-output buffer buffer-range POSTPONE: f ;
 
 TUPLE: render-set
     { primitive-mode primitive-mode read-only }
-    { vertex-array vertex-array read-only }
+    { vertex-array vertex-array initial: T{ vertex-array-collection } read-only }
     { uniforms uniform-tuple read-only }
     { indexes vertex-indexes initial: T{ index-range } read-only } 
     { instances ?integer initial: f read-only }
index dd162245290af31313be81a7657d21af90e6c199..96a8561e9f7ab1e42023131fac52705fc23268b4 100644 (file)
@@ -167,14 +167,23 @@ HELP: vertex-shader
 { $class-description "This " { $link shader-kind } " indicates that a " { $link shader } " is a vertex shader." } ;
 
 HELP: vertex-array
-{ $class-description "A " { $snippet "vertex-array" } " object associates a shader " { $link program-instance } " with vertex attribute data from one or more " { $link buffer } "s. The format of the binary data inside these buffers is described using " { $link vertex-format } "s. " { $snippet "vertex-array" } "s are constructed using the " { $link <multi-vertex-array> } " or " { $link <vertex-array*> } " words." } ;
+{ $class-description "A " { $snippet "vertex-array" } " object associates a shader " { $link program-instance } " with vertex attribute data from one or more " { $link buffer } "s. The format of the binary data inside these buffers is described using " { $link vertex-format } "s. " { $snippet "vertex-array" } "s are constructed using the " { $link <multi-vertex-array> } " or " { $link <vertex-array*> } " words. The actual type of a vertex-array object is opaque, but the " { $link vertex-array-buffers } " word can be used to query a vertex array object for its component buffers." } ;
+
+HELP: vertex-array-buffers
+{ $values
+    { "vertex-array" vertex-array }
+    { "vertex-buffer" buffer }
+}
+{ $description "Returns a sequence containing all of the " { $link buffer } " objects that make up " { $snippet "vertex-array" } "." } ;
 
 HELP: vertex-array-buffer
 { $values
     { "vertex-array" vertex-array }
     { "vertex-buffer" buffer }
 }
-{ $description "Returns the first " { $link buffer } " object comprised in " { $snippet "vertex-array" } "." } ;
+{ $description "Returns the first " { $link buffer } " object that makes up " { $snippet "vertex-array" } "." } ;
+
+{ vertex-array-buffer vertex-array-buffers } related-words
 
 HELP: vertex-attribute
 { $class-description "This tuple type is passed to " { $link define-vertex-format } " to define a new " { $link vertex-format } " type." } ;
@@ -204,7 +213,8 @@ ARTICLE: "gpu.shaders" "Shader objects"
 { $subsections
     vertex-array
     <multi-vertex-array>
-    vertex-array
+    <vertex-array*>
+    <vertex-array>
     POSTPONE: VERTEX-FORMAT:
 } ;
 
old mode 100644 (file)
new mode 100755 (executable)
index 0401584..025acba
@@ -2,9 +2,9 @@
 USING: accessors alien alien.c-types alien.data alien.strings
 arrays assocs byte-arrays classes.mixin classes.parser
 classes.singleton classes.struct combinators combinators.short-circuit
-definitions destructors fry generic.parser gpu gpu.buffers hashtables
-images io.encodings.ascii io.files io.pathnames kernel lexer
-literals locals math math.parser memoize multiline namespaces
+definitions destructors fry generic.parser gpu gpu.buffers gpu.private
+gpu.state hashtables images io.encodings.ascii io.files io.pathnames
+kernel lexer literals locals math math.parser memoize multiline namespaces
 opengl opengl.gl opengl.shaders parser quotations sequences
 specialized-arrays splitting strings tr ui.gadgets.worlds
 variants vectors vocabs vocabs.loader vocabs.parser words
@@ -319,11 +319,18 @@ SYNTAX: VERTEX-FORMAT:
 SYNTAX: VERTEX-STRUCT:
     CREATE-CLASS scan-word define-vertex-struct ;
 
-TUPLE: vertex-array < gpu-object
+TUPLE: vertex-array-object < gpu-object
     { program-instance program-instance read-only }
     { vertex-buffers sequence read-only } ;
 
-M: vertex-array dispose
+TUPLE: vertex-array-collection
+    { vertex-formats sequence read-only }
+    { program-instance program-instance read-only } ;
+
+UNION: vertex-array
+    vertex-array-object vertex-array-collection ;
+
+M: vertex-array-object dispose
     [ [ delete-vertex-array ] when* f ] change-handle drop ;
 
 : ?>buffer-ptr ( buffer/ptr -- buffer-ptr )
@@ -331,26 +338,73 @@ M: vertex-array dispose
 : ?>buffer ( buffer/ptr -- buffer )
     dup buffer? [ buffer>> ] unless ; inline
 
-:: <multi-vertex-array> ( vertex-formats program-instance -- vertex-array )
+<PRIVATE
+
+: normalize-vertex-formats ( vertex-formats -- vertex-formats' )
+    [ first2 [ ?>buffer-ptr ] dip 2array ] map ; inline
+
+: (bind-vertex-array) ( vertex-formats program-instance -- )
+    '[ _ swap first2 bind-vertex-format ] each ; inline
+
+: (reset-vertex-array) ( -- )
+    GL_MAX_VERTEX_ATTRIBS get-gl-int iota [ glDisableVertexAttribArray ] each ; inline
+
+:: <multi-vertex-array-object> ( vertex-formats program-instance -- vertex-array )
     gen-vertex-array :> handle
     handle glBindVertexArray
 
-    vertex-formats [ program-instance swap first2 [ ?>buffer-ptr ] dip bind-vertex-format ] each
+    vertex-formats normalize-vertex-formats program-instance (bind-vertex-array)
+
     handle program-instance vertex-formats [ first ?>buffer ] map
-    vertex-array boa window-resource ; inline
+    vertex-array-object boa window-resource ; inline
 
-:: <vertex-array*> ( vertex-buffer program-instance format -- vertex-array )
+: <multi-vertex-array-collection> ( vertex-formats program-instance -- vertex-array )
+    [ normalize-vertex-formats ] dip vertex-array-collection boa ; inline
+
+:: <vertex-array-object> ( vertex-buffer program-instance format -- vertex-array )
     gen-vertex-array :> handle
     handle glBindVertexArray
     program-instance vertex-buffer ?>buffer-ptr format bind-vertex-format
     handle program-instance vertex-buffer ?>buffer 1array
-    vertex-array boa window-resource ; inline
+    vertex-array-object boa window-resource ; inline
+
+: <vertex-array-collection> ( vertex-buffer program-instance format -- vertex-array )
+    swap [ [ ?>buffer-ptr ] dip 2array 1array ] dip <multi-vertex-array-collection> ; inline
+
+PRIVATE>
+
+GENERIC: bind-vertex-array ( vertex-array -- )
+
+M: vertex-array-object bind-vertex-array
+    handle>> glBindVertexArray ; inline
+
+M: vertex-array-collection bind-vertex-array
+    (reset-vertex-array)
+    [ vertex-formats>> ] [ program-instance>> ] bi (bind-vertex-array) ; inline
+
+: <multi-vertex-array> ( vertex-formats program-instance -- vertex-array )
+    has-vertex-array-objects? get
+    [ <multi-vertex-array-object> ]
+    [ <multi-vertex-array-collection> ] if ; inline
+    
+: <vertex-array*> ( vertex-buffer program-instance format -- vertex-array )
+    has-vertex-array-objects? get
+    [ <vertex-array-object> ]
+    [ <vertex-array-collection> ] if ; inline
 
 : <vertex-array> ( vertex-buffer program-instance -- vertex-array )
     dup program>> vertex-formats>> first <vertex-array*> ; inline
 
-TYPED: vertex-array-buffer ( vertex-array: vertex-array -- vertex-buffer: buffer )
-    vertex-buffers>> first ;
+GENERIC: vertex-array-buffers ( vertex-array -- buffers )
+
+M: vertex-array-object vertex-array-buffers
+    vertex-buffers>> ; inline
+
+M: vertex-array-collection vertex-array-buffers
+    vertex-formats>> [ first buffer>> ] map ; inline
+
+: vertex-array-buffer ( vertex-array: vertex-array -- vertex-buffer: buffer )
+    vertex-array-buffers first ; inline
 
 TUPLE: compile-shader-error shader log ;
 TUPLE: link-program-error program log ;
old mode 100644 (file)
new mode 100755 (executable)
index 3064ed4..db76774
@@ -415,8 +415,6 @@ M: mask-state set-gpu-state*
     [ [ set-gpu-state* ] each ]
     [ set-gpu-state* ] if ; inline
 
-<PRIVATE
-
 : get-gl-bool ( enum -- value )
     0 <uchar> [ glGetBooleanv ] keep *uchar c-bool> ;
 : get-gl-int ( enum -- value )
@@ -437,8 +435,6 @@ M: mask-state set-gpu-state*
 : gl-enabled? ( enum -- ? )
     glIsEnabled c-bool> ;
 
-PRIVATE>
-
 TYPED: get-viewport-state ( -- viewport-state: viewport-state )
     GL_VIEWPORT get-gl-rect <viewport-state> ;