]> gitweb.factorcode.org Git - factor.git/commitdiff
Merge branch 'master' of git://factorcode.org/git/littledan
authorSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Fri, 11 Apr 2008 21:17:01 +0000 (16:17 -0500)
committerSlava Pestov <slava@slava-pestovs-macbook-pro.local>
Fri, 11 Apr 2008 21:17:01 +0000 (16:17 -0500)
352 files changed:
build-support/factor.sh
core/alien/alien-docs.factor
core/alien/alien.factor
core/alien/arrays/arrays.factor
core/alien/c-types/c-types.factor
core/alien/compiler/compiler-tests.factor
core/alien/compiler/compiler.factor
core/alien/syntax/syntax.factor
core/assocs/assocs.factor
core/bootstrap/compiler/compiler.factor
core/bootstrap/image/image.factor
core/bootstrap/primitives.factor
core/bootstrap/stage2.factor
core/classes/algebra/algebra-tests.factor
core/classes/algebra/algebra.factor
core/classes/builtin/builtin-docs.factor [new file with mode: 0644]
core/classes/builtin/builtin.factor [new file with mode: 0644]
core/classes/classes-docs.factor
core/classes/classes.factor
core/classes/mixin/mixin-docs.factor
core/classes/mixin/mixin.factor
core/classes/singleton/singleton-docs.factor
core/classes/tuple/tuple-docs.factor
core/classes/tuple/tuple-tests.factor
core/classes/tuple/tuple.factor
core/classes/union/union-docs.factor
core/combinators/combinators-docs.factor
core/combinators/combinators-tests.factor
core/combinators/combinators.factor
core/compiler/compiler.factor
core/compiler/tests/float.factor
core/compiler/tests/simple.factor
core/compiler/tests/templates-early.factor
core/compiler/tests/templates.factor
core/compiler/tests/tuples.factor
core/compiler/units/units.factor
core/continuations/continuations-docs.factor
core/continuations/continuations-tests.factor
core/continuations/continuations.factor
core/cpu/architecture/architecture.factor
core/cpu/ppc/architecture/architecture.factor
core/cpu/x86/32/32.factor
core/cpu/x86/64/64.factor
core/cpu/x86/architecture/architecture.factor
core/cpu/x86/assembler/assembler.factor
core/debugger/debugger.factor
core/definitions/definitions-docs.factor
core/definitions/definitions-tests.factor
core/definitions/definitions.factor
core/dlists/dlists.factor
core/effects/effects.factor
core/generator/fixup/fixup.factor
core/generator/generator.factor
core/generator/registers/registers.factor
core/generic/generic-docs.factor
core/generic/generic-tests.factor
core/generic/generic.factor
core/generic/math/math.factor
core/generic/standard/engines/engines.factor
core/generic/standard/engines/predicate/predicate.factor
core/generic/standard/engines/tuple/tuple.factor
core/generic/standard/standard-docs.factor
core/generic/standard/standard-tests.factor
core/generic/standard/standard.factor
core/heaps/heaps-tests.factor
core/heaps/heaps.factor
core/inference/backend/backend-docs.factor
core/inference/backend/backend.factor
core/inference/dataflow/dataflow.factor
core/inference/errors/errors.factor
core/inference/inference-docs.factor
core/inference/inference-tests.factor
core/inference/known-words/known-words.factor
core/io/encodings/utf8/utf8.factor
core/io/files/files-docs.factor
core/io/files/files-tests.factor
core/io/files/files.factor
core/io/streams/duplex/duplex-docs.factor
core/io/streams/nested/nested.factor
core/io/streams/plain/plain.factor
core/io/streams/string/string-docs.factor
core/kernel/kernel-docs.factor
core/kernel/kernel-tests.factor
core/kernel/kernel.factor
core/layouts/layouts-docs.factor
core/listener/listener.factor
core/math/intervals/intervals.factor
core/math/math-docs.factor
core/math/parser/parser.factor
core/memory/memory-docs.factor
core/memory/memory-tests.factor
core/mirrors/mirrors.factor
core/optimizer/backend/backend.factor
core/optimizer/control/control-tests.factor
core/optimizer/control/control.factor
core/optimizer/def-use/def-use.factor
core/optimizer/inlining/inlining.factor
core/optimizer/optimizer-tests.factor
core/optimizer/pattern-match/pattern-match.factor
core/optimizer/specializers/specializers.factor
core/parser/parser-docs.factor
core/parser/parser-tests.factor
core/parser/parser.factor
core/prettyprint/config/config-docs.factor
core/prettyprint/prettyprint-docs.factor
core/prettyprint/prettyprint-tests.factor
core/prettyprint/prettyprint.factor
core/prettyprint/sections/sections-docs.factor
core/prettyprint/sections/sections.factor
core/refs/refs-tests.factor [new file with mode: 0644]
core/refs/refs.factor
core/sequences/sequences-tests.factor
core/sequences/sequences.factor
core/slots/slots-docs.factor
core/source-files/source-files.factor
core/syntax/syntax-docs.factor
core/syntax/syntax.factor
core/system/system-docs.factor
core/system/system-tests.factor
core/threads/threads.factor
core/vocabs/loader/loader-tests.factor
core/words/words-docs.factor
core/words/words-tests.factor
core/words/words.factor
extra/assocs/lib/lib.factor
extra/bootstrap/random/random.factor
extra/bubble-chamber/bubble-chamber.factor [new file with mode: 0644]
extra/bubble-chamber/common/common.factor [new file with mode: 0644]
extra/bubble-chamber/particle/axion/axion.factor [new file with mode: 0644]
extra/bubble-chamber/particle/hadron/hadron.factor [new file with mode: 0644]
extra/bubble-chamber/particle/muon/colors/colors.factor [new file with mode: 0644]
extra/bubble-chamber/particle/muon/muon.factor [new file with mode: 0644]
extra/bubble-chamber/particle/particle.factor [new file with mode: 0644]
extra/bubble-chamber/particle/quark/quark.factor [new file with mode: 0644]
extra/builder/builder.factor
extra/builder/release/release.factor
extra/builder/test/test.factor
extra/bunny/model/model.factor
extra/cairo/png/png.factor
extra/calendar/windows/windows.factor
extra/cel-shading/authors.txt [deleted file]
extra/cel-shading/summary.txt [deleted file]
extra/cel-shading/tags.txt [deleted file]
extra/cocoa/application/application.factor
extra/cocoa/cocoa-tests.factor
extra/cocoa/cocoa.factor
extra/cocoa/messages/messages.factor
extra/cocoa/plists/plists.factor
extra/concurrency/mailboxes/mailboxes-docs.factor
extra/concurrency/mailboxes/mailboxes-tests.factor
extra/concurrency/mailboxes/mailboxes.factor
extra/concurrency/messaging/messaging-docs.factor
extra/concurrency/messaging/messaging-tests.factor
extra/contributors/contributors.factor
extra/core-foundation/core-foundation.factor
extra/core-foundation/fsevents/fsevents.factor
extra/core-foundation/run-loop/run-loop.factor [new file with mode: 0644]
extra/crypto/sha1/sha1.factor
extra/crypto/test/blum-blum-shub.factor [deleted file]
extra/db/db.factor
extra/db/mysql/lib/lib.factor
extra/db/postgresql/ffi/ffi.factor
extra/db/postgresql/postgresql.factor
extra/db/sql/sql-tests.factor
extra/db/sql/sql.factor
extra/db/sqlite/lib/lib.factor
extra/db/sqlite/sqlite.factor
extra/db/tuples/tuples-tests.factor
extra/delegate/delegate-tests.factor
extra/delegate/protocols/protocols.factor
extra/documents/documents.factor
extra/editors/editors.factor
extra/fry/fry.factor
extra/hardware-info/backend/backend.factor
extra/hardware-info/hardware-info.factor
extra/hardware-info/macosx/macosx.factor
extra/hardware-info/windows/ce/ce.factor
extra/help/cookbook/cookbook.factor
extra/help/crossref/crossref.factor
extra/help/handbook/handbook.factor
extra/help/help.factor
extra/help/syntax/syntax.factor
extra/html/parser/printer/printer.factor
extra/http/http.factor
extra/http/server/server.factor
extra/http/server/static/static.factor
extra/http/server/templating/fhtml/fhtml.factor
extra/io/launcher/launcher-docs.factor
extra/io/launcher/launcher.factor
extra/io/mmap/mmap-tests.factor
extra/io/monitors/monitors-docs.factor
extra/io/monitors/monitors-tests.factor [new file with mode: 0644]
extra/io/monitors/monitors.factor
extra/io/monitors/recursive/recursive-tests.factor [new file with mode: 0644]
extra/io/monitors/recursive/recursive.factor [new file with mode: 0644]
extra/io/nonblocking/nonblocking-docs.factor
extra/io/nonblocking/nonblocking.factor
extra/io/server/server.factor
extra/io/sockets/impl/impl.factor
extra/io/sockets/sockets-docs.factor
extra/io/sockets/sockets.factor
extra/io/timeouts/timeouts-docs.factor
extra/io/unix/backend/backend.factor [changed mode: 0755->0644]
extra/io/unix/bsd/bsd.factor
extra/io/unix/epoll/epoll.factor
extra/io/unix/files/files.factor
extra/io/unix/kqueue/kqueue.factor [changed mode: 0755->0644]
extra/io/unix/launcher/launcher.factor
extra/io/unix/linux/linux.factor
extra/io/unix/linux/monitors/monitors.factor [new file with mode: 0644]
extra/io/unix/macosx/macosx.factor
extra/io/unix/netbsd/netbsd.factor
extra/io/unix/openbsd/openbsd.factor
extra/io/unix/select/select.factor
extra/io/unix/sockets/sockets.factor
extra/io/unix/unix-tests.factor
extra/io/unix/unix.factor
extra/io/windows/launcher/launcher-tests.factor [new file with mode: 0755]
extra/io/windows/launcher/launcher.factor
extra/io/windows/nt/backend/backend.factor
extra/io/windows/nt/files/files-tests.factor
extra/io/windows/nt/files/files.factor
extra/io/windows/nt/launcher/launcher-tests.factor
extra/io/windows/nt/launcher/launcher.factor
extra/io/windows/nt/monitors/monitors.factor
extra/io/windows/nt/sockets/sockets.factor
extra/io/windows/windows.factor
extra/irc/irc.factor
extra/koszul/koszul.factor
extra/lazy-lists/lazy-lists.factor
extra/locals/locals.factor
extra/logging/parser/parser.factor
extra/logging/server/server.factor
extra/match/match.factor
extra/math/functions/functions.factor
extra/math/miller-rabin/miller-rabin.factor
extra/math/points/points.factor [new file with mode: 0644]
extra/math/primes/primes.factor
extra/multi-methods/multi-methods-tests.factor [deleted file]
extra/multi-methods/multi-methods.factor
extra/multi-methods/tests/canonicalize.factor [new file with mode: 0644]
extra/multi-methods/tests/definitions.factor [new file with mode: 0644]
extra/multi-methods/tests/legacy.factor [new file with mode: 0644]
extra/multi-methods/tests/syntax.factor [new file with mode: 0644]
extra/multi-methods/tests/topological-sort.factor [new file with mode: 0644]
extra/newfx/newfx.factor
extra/odbc/odbc.factor
extra/ogg/player/player.factor
extra/opengl/gl/extensions/extensions.factor
extra/opengl/opengl-docs.factor
extra/optimizer/debugger/debugger.factor
extra/oracle/oracle.factor
extra/pack/pack.factor
extra/peg/ebnf/ebnf.factor
extra/peg/parsers/parsers-docs.factor
extra/peg/parsers/parsers.factor
extra/peg/peg-docs.factor
extra/peg/peg.factor
extra/porter-stemmer/porter-stemmer.factor
extra/processing/color/color.factor [new file with mode: 0644]
extra/processing/gadget/gadget.factor [new file with mode: 0644]
extra/processing/gallery/trails/trails.factor [new file with mode: 0644]
extra/processing/processing.factor [new file with mode: 0644]
extra/project-euler/169/169.factor
extra/project-euler/175/175.factor
extra/random-tester/safe-words/safe-words.factor
extra/random/blum-blum-shub/blum-blum-shub-tests.factor [new file with mode: 0644]
extra/random/blum-blum-shub/blum-blum-shub.factor
extra/reports/noise/noise.factor
extra/rot13/rot13.factor
extra/sequences/lib/lib.factor
extra/serialize/serialize.factor
extra/smtp/server/server.factor
extra/smtp/smtp.factor
extra/space-invaders/space-invaders.factor
extra/sudoku/sudoku.factor
extra/tar/tar.factor
extra/tools/annotations/annotations.factor
extra/tools/completion/completion.factor
extra/tools/deploy/backend/backend.factor
extra/tools/deploy/deploy-tests.factor
extra/tools/deploy/macosx/macosx.factor
extra/tools/deploy/shaker/shaker.factor
extra/tools/deploy/windows/windows.factor
extra/tools/disassembler/disassembler.factor
extra/tools/memory/memory-docs.factor
extra/tools/memory/memory-tests.factor
extra/tools/memory/memory.factor
extra/tools/profiler/profiler-tests.factor
extra/tools/threads/threads.factor
extra/tools/vocabs/browser/browser.factor
extra/tools/vocabs/monitor/monitor-tests.factor [new file with mode: 0644]
extra/tools/vocabs/monitor/monitor.factor
extra/tools/vocabs/vocabs-tests.factor [new file with mode: 0644]
extra/tools/vocabs/vocabs.factor
extra/tools/walker/walker.factor
extra/trees/avl/avl.factor
extra/trees/trees.factor
extra/ui/gadgets/buttons/buttons.factor
extra/ui/gadgets/frame-buffer/frame-buffer.factor [new file with mode: 0644]
extra/ui/gadgets/gadgets.factor
extra/ui/gadgets/panes/panes-tests.factor
extra/ui/gadgets/panes/panes.factor
extra/ui/gadgets/scrollers/scrollers.factor
extra/ui/gestures/gestures.factor
extra/ui/render/render.factor
extra/ui/tools/interactor/interactor-tests.factor
extra/ui/tools/interactor/interactor.factor
extra/ui/tools/listener/listener-tests.factor
extra/ui/tools/listener/listener.factor
extra/ui/tools/walker/walker.factor
extra/ui/traverse/traverse.factor
extra/ui/windows/windows.factor
extra/ui/x11/x11.factor
extra/unicode/breaks/breaks.factor
extra/unicode/case/case.factor
extra/unicode/data/data.factor
extra/unicode/normalize/normalize.factor
extra/unionfind/authors.txt [new file with mode: 0644]
extra/unionfind/summary.txt [new file with mode: 0644]
extra/unionfind/unionfind.factor [new file with mode: 0644]
extra/unix/stat/stat.factor
extra/unix/unix.factor
extra/windows/advapi32/advapi32.factor
extra/windows/messages/messages.factor
extra/x11/events/events.factor
extra/xml-rpc/xml-rpc.factor
extra/xml/tokenize/tokenize.factor
vm/code_gc.c
vm/code_gc.h
vm/code_heap.c
vm/data_gc.c
vm/data_gc.h
vm/debug.c
vm/debug.h
vm/errors.c
vm/errors.h
vm/factor.c
vm/image.c
vm/image.h
vm/master.h
vm/os-linux-ppc.h
vm/os-macosx.h
vm/os-unix-ucontext.h [deleted file]
vm/os-unix.c
vm/os-windows.c
vm/platform.h
vm/primitives.c
vm/profiler.c
vm/run.c
vm/run.h
vm/types.c

index 476e885257323bb01224d0693982d5b82b8fdd86..4bcd9e3086222d8957db3e25eeaa1815dc82a2f6 100755 (executable)
@@ -190,6 +190,7 @@ find_architecture() {
        i386) ARCH=x86;;
        i686) ARCH=x86;;
        amd64) ARCH=x86;;
+       ppc64) ARCH=ppc;;
        *86) ARCH=x86;;
        *86_64) ARCH=x86;;
        "Power Macintosh") ARCH=ppc;;
index fcafe3441c36b81e90e346b6584a2c5520e7d979..7d13080e3c046deb72ae93a5af04eeecd0b3c05d 100755 (executable)
@@ -78,7 +78,7 @@ $nl
     "<< \"freetype\" {"
     "    { [ os macosx? ] [ \"libfreetype.6.dylib\" \"cdecl\" add-library ] }"
     "    { [ os windows? ] [ \"freetype6.dll\" \"cdecl\" add-library ] }"
-    "    { [ t ] [ drop ] }"
+    "    [ drop ]"
     "} cond >>"
 }
 "Note the parse time evaluation with " { $link POSTPONE: << } "." } ;
@@ -204,7 +204,7 @@ ARTICLE: "alien-callback-gc" "Callbacks and code GC"
 "A callback consits of two parts; the callback word, which pushes the address of the callback on the stack when executed, and the callback body itself. If the callback word is redefined, removed from the dictionary using " { $link forget } ", or recompiled, the callback body will not be reclaimed by the garbage collector, since potentially C code may be holding a reference to the callback body."
 $nl
 "This is the safest approach, however it can lead to code heap leaks when repeatedly reloading code which defines callbacks. If you are " { $emphasis "completely sure" } " that no running C code is holding a reference to any callbacks, you can blow them all away:"
-{ $code "USE: alien callbacks get clear-hash code-gc" }
+{ $code "USE: alien callbacks get clear-hash gc" }
 "This will reclaim all callback bodies which are otherwise unreachable from the dictionary (that is, their associated callback words have since been redefined, recompiled or forgotten)." ;
 
 ARTICLE: "alien-callback" "Calling Factor from C"
index 56be3e66a5ec32a6ef6c2c3466c68c2ddd37a600..2f82e5db9844b2547567dde140015cc478feaf50 100755 (executable)
@@ -62,22 +62,16 @@ TUPLE: library path abi dll ;
 : add-library ( name path abi -- )
     <library> swap libraries get set-at ;
 
-TUPLE: alien-callback return parameters abi quot xt ;
-
 ERROR: alien-callback-error ;
 
 : alien-callback ( return parameters abi quot -- alien )
     alien-callback-error ;
 
-TUPLE: alien-indirect return parameters abi ;
-
 ERROR: alien-indirect-error ;
 
 : alien-indirect ( ... funcptr return parameters abi -- )
     alien-indirect-error ;
 
-TUPLE: alien-invoke library function return parameters abi ;
-
 ERROR: alien-invoke-error library symbol ;
 
 : alien-invoke ( ... return library function parameters -- ... )
index c9b9d838dd4b88dbdd552d5d472325428db7026b..402b01550bb4091a31f8b56cfd028dd1682d72d1 100644 (file)
@@ -25,7 +25,7 @@ M: array box-return drop "void*" box-return ;
 
 M: array stack-size drop "void*" stack-size ;
 
-M: value-type c-type-reg-class drop T{ int-regs } ;
+M: value-type c-type-reg-class drop int-regs ;
 
 M: value-type c-type-prep drop f ;
 
index ca1a89b4aeebab38306aff05d3fc12540d1eb205..508fcd61a61d0960ad2ac846c25b0ee9300178d2 100755 (executable)
@@ -4,7 +4,8 @@ USING: bit-arrays byte-arrays float-arrays arrays
 generator.registers assocs kernel kernel.private libc math
 namespaces parser sequences strings words assocs splitting
 math.parser cpu.architecture alien alien.accessors quotations
-layouts system compiler.units io.files io.encodings.binary ;
+layouts system compiler.units io.files io.encodings.binary
+accessors combinators ;
 IN: alien.c-types
 
 DEFER: <int>
@@ -17,8 +18,12 @@ boxer prep unboxer
 getter setter
 reg-class size align stack-align? ;
 
+: construct-c-type ( class -- type )
+    construct-empty
+        int-regs >>reg-class ;
+
 : <c-type> ( -- type )
-    T{ int-regs } { set-c-type-reg-class } \ c-type construct ;
+    \ c-type construct-c-type ;
 
 SYMBOL: c-types
 
@@ -181,10 +186,10 @@ DEFER: >c-ushort-array
 : define-c-type ( type name vocab -- )
     >r tuck typedef r> [ define-nth ] 2keep define-set-nth ;
 
-TUPLE: long-long-type ;
+TUPLE: long-long-type < c-type ;
 
-: <long-long-type> ( type -- type )
-    long-long-type construct-delegate ;
+: <long-long-type> ( -- type )
+    long-long-type construct-c-type ;
 
 M: long-long-type unbox-parameter ( n type -- )
     c-type-unboxer %unbox-long-long ;
@@ -235,22 +240,15 @@ M: long-long-type box-return ( type -- )
 : define-from-array ( type vocab -- )
     [ from-array-word ] 2keep c-array>quot define ;
 
-: <primitive-type> ( getter setter width boxer unboxer -- type )
-    <c-type>
-    [ set-c-type-unboxer ] keep
-    [ set-c-type-boxer ] keep
-    [ set-c-type-size ] 2keep
-    [ set-c-type-align ] keep
-    [ set-c-type-setter ] keep
-    [ set-c-type-getter ] keep ;
-
 : define-primitive-type ( type name -- )
     "alien.c-types"
-    [ define-c-type ] 2keep
-    [ define-deref ] 2keep
-    [ define-to-array ] 2keep
-    [ define-from-array ] 2keep
-    define-out ;
+    {
+        [ define-c-type ]
+        [ define-deref ]
+        [ define-to-array ]
+        [ define-from-array ]
+        [ define-out ]
+    } 2cleave ;
 
 : expand-constants ( c-type -- c-type' )
     #! We use word-def call instead of execute to get around
@@ -264,130 +262,157 @@ M: long-long-type box-return ( type -- )
     binary file-contents dup malloc-byte-array swap length ;
 
 [
-    [ alien-cell ]
-    [ set-alien-cell ]
-    bootstrap-cell
-    "box_alien"
-    "alien_offset" <primitive-type>
+    <c-type>
+        [ alien-cell ] >>getter
+        [ set-alien-cell ] >>setter
+        bootstrap-cell >>size
+        bootstrap-cell >>align
+        "box_alien" >>boxer
+        "alien_offset" >>unboxer
     "void*" define-primitive-type
 
-    [ alien-signed-8 ]
-    [ set-alien-signed-8 ]
-    8
-    "box_signed_8"
-    "to_signed_8" <primitive-type> <long-long-type>
+    <long-long-type>
+        [ alien-signed-8 ] >>getter
+        [ set-alien-signed-8 ] >>setter
+        8 >>size
+        8 >>align
+        "box_signed_8" >>boxer
+        "to_signed_8" >>unboxer
     "longlong" define-primitive-type
 
-    [ alien-unsigned-8 ]
-    [ set-alien-unsigned-8 ]
-    8
-    "box_unsigned_8"
-    "to_unsigned_8" <primitive-type> <long-long-type>
+    <long-long-type>
+        [ alien-unsigned-8 ] >>getter
+        [ set-alien-unsigned-8 ] >>setter
+        8 >>size
+        8 >>align
+        "box_unsigned_8" >>boxer
+        "to_unsigned_8" >>unboxer
     "ulonglong" define-primitive-type
 
-    [ alien-signed-cell ]
-    [ set-alien-signed-cell ]
-    bootstrap-cell
-    "box_signed_cell"
-    "to_fixnum" <primitive-type>
+    <c-type>
+        [ alien-signed-cell ] >>getter
+        [ set-alien-signed-cell ] >>setter
+        bootstrap-cell >>size
+        bootstrap-cell >>align
+        "box_signed_cell" >>boxer
+        "to_fixnum" >>unboxer
     "long" define-primitive-type
 
-    [ alien-unsigned-cell ]
-    [ set-alien-unsigned-cell ]
-    bootstrap-cell
-    "box_unsigned_cell"
-    "to_cell" <primitive-type>
+    <c-type>
+        [ alien-unsigned-cell ] >>getter
+        [ set-alien-unsigned-cell ] >>setter
+        bootstrap-cell >>size
+        bootstrap-cell >>align
+        "box_unsigned_cell" >>boxer
+        "to_cell" >>unboxer
     "ulong" define-primitive-type
 
-    [ alien-signed-4 ]
-    [ set-alien-signed-4 ]
-    4
-    "box_signed_4"
-    "to_fixnum" <primitive-type>
+    <c-type>
+        [ alien-signed-4 ] >>getter
+        [ set-alien-signed-4 ] >>setter
+        4 >>size
+        4 >>align
+        "box_signed_4" >>boxer
+        "to_fixnum" >>unboxer
     "int" define-primitive-type
 
-    [ alien-unsigned-4 ]
-    [ set-alien-unsigned-4 ]
-    4
-    "box_unsigned_4"
-    "to_cell" <primitive-type>
+    <c-type>
+        [ alien-unsigned-4 ] >>getter
+        [ set-alien-unsigned-4 ] >>setter
+        4 >>size
+        4 >>align
+        "box_unsigned_4" >>boxer
+        "to_cell" >>unboxer
     "uint" define-primitive-type
 
-    [ alien-signed-2 ]
-    [ set-alien-signed-2 ]
-    2
-    "box_signed_2"
-    "to_fixnum" <primitive-type>
+    <c-type>
+        [ alien-signed-2 ] >>getter
+        [ set-alien-signed-2 ] >>setter
+        2 >>size
+        2 >>align
+        "box_signed_2" >>boxer
+        "to_fixnum" >>unboxer
     "short" define-primitive-type
 
-    [ alien-unsigned-2 ]
-    [ set-alien-unsigned-2 ]
-    2
-    "box_unsigned_2"
-    "to_cell" <primitive-type>
+    <c-type>
+        [ alien-unsigned-2 ] >>getter
+        [ set-alien-unsigned-2 ] >>setter
+        2 >>size
+        2 >>align
+        "box_unsigned_2" >>boxer
+        "to_cell" >>unboxer
     "ushort" define-primitive-type
 
-    [ alien-signed-1 ]
-    [ set-alien-signed-1 ]
-    1
-    "box_signed_1"
-    "to_fixnum" <primitive-type>
+    <c-type>
+        [ alien-signed-1 ] >>getter
+        [ set-alien-signed-1 ] >>setter
+        1 >>size
+        1 >>align
+        "box_signed_1" >>boxer
+        "to_fixnum" >>unboxer
     "char" define-primitive-type
 
-    [ alien-unsigned-1 ]
-    [ set-alien-unsigned-1 ]
-    1
-    "box_unsigned_1"
-    "to_cell" <primitive-type>
+    <c-type>
+        [ alien-unsigned-1 ] >>getter
+        [ set-alien-unsigned-1 ] >>setter
+        1 >>size
+        1 >>align
+        "box_unsigned_1" >>boxer
+        "to_cell" >>unboxer
     "uchar" define-primitive-type
 
-    [ alien-unsigned-4 zero? not ]
-    [ 1 0 ? set-alien-unsigned-4 ]
-    4
-    "box_boolean"
-    "to_boolean" <primitive-type>
+    <c-type>
+        [ alien-unsigned-4 zero? not ] >>getter
+        [ 1 0 ? set-alien-unsigned-4 ] >>setter
+        4 >>size
+        4 >>align
+        "box_boolean" >>boxer
+        "to_boolean" >>unboxer
     "bool" define-primitive-type
 
-    [ alien-float ]
-    [ >r >r >float r> r> set-alien-float ]
-    4
-    "box_float"
-    "to_float" <primitive-type>
+    <c-type>
+        [ alien-float ] >>getter
+        [ >r >r >float r> r> set-alien-float ] >>setter
+        4 >>size
+        4 >>align
+        "box_float" >>boxer
+        "to_float" >>unboxer
+        single-float-regs >>reg-class
+        [ >float ] >>prep
     "float" define-primitive-type
 
-    T{ float-regs f 4 } "float" c-type set-c-type-reg-class
-    [ >float ] "float" c-type set-c-type-prep
-
-    [ alien-double ]
-    [ >r >r >float r> r> set-alien-double ]
-    8
-    "box_double"
-    "to_double" <primitive-type>
+    <c-type>
+        [ alien-double ] >>getter
+        [ >r >r >float r> r> set-alien-double ] >>setter
+        8 >>size
+        8 >>align
+        "box_double" >>boxer
+        "to_double" >>unboxer
+        double-float-regs >>reg-class
+        [ >float ] >>prep
     "double" define-primitive-type
 
-    T{ float-regs f 8 } "double" c-type set-c-type-reg-class
-    [ >float ] "double" c-type set-c-type-prep
-
-    [ alien-cell alien>char-string ]
-    [ set-alien-cell ]
-    bootstrap-cell
-    "box_char_string"
-    "alien_offset" <primitive-type>
+    <c-type>
+        [ alien-cell alien>char-string ] >>getter
+        [ set-alien-cell ] >>setter
+        bootstrap-cell >>size
+        bootstrap-cell >>align
+        "box_char_string" >>boxer
+        "alien_offset" >>unboxer
+        [ string>char-alien ] >>prep
     "char*" define-primitive-type
 
     "char*" "uchar*" typedef
 
-    [ string>char-alien ] "char*" c-type set-c-type-prep
-
-    [ alien-cell alien>u16-string ]
-    [ set-alien-cell ]
-    4
-    "box_u16_string"
-    "alien_offset" <primitive-type>
+    <c-type>
+        [ alien-cell alien>u16-string ] >>getter
+        [ set-alien-cell ] >>setter
+        4 >>size
+        4 >>align
+        "box_u16_string" >>boxer
+        "alien_offset" >>unboxer
+        [ string>u16-alien ] >>prep
     "ushort*" define-primitive-type
 
-    [ string>u16-alien ] "ushort*" c-type set-c-type-prep
-    
     os winnt? cpu x86.64? and "longlong" "long" ? "ptrdiff_t" typedef
-    
 ] with-compilation-unit
index f9dc426de1a8d0522dbea0527e01c6a9d2779973..dd2d9587cb10a8a329b43d68e0a718cb8fd5033c 100755 (executable)
@@ -87,7 +87,7 @@ FUNCTION: tiny ffi_test_17 int x ;
 [ -1 indirect-test-1 ] must-fail\r
 \r
 : indirect-test-2\r
-    "int" { "int" "int" } "cdecl" alien-indirect data-gc ;\r
+    "int" { "int" "int" } "cdecl" alien-indirect gc ;\r
 \r
 { 3 1 } [ indirect-test-2 ] must-infer-as\r
 \r
@@ -97,7 +97,7 @@ unit-test
 \r
 : indirect-test-3\r
     "int" { "int" "int" "int" "int" } "stdcall" alien-indirect\r
-    data-gc ;\r
+    gc ;\r
 \r
 << "f-stdcall" f "stdcall" add-library >>\r
 \r
@@ -106,13 +106,13 @@ unit-test
 \r
 : ffi_test_18 ( w x y z -- int )\r
     "int" "f-stdcall" "ffi_test_18" { "int" "int" "int" "int" }\r
-    alien-invoke data-gc ;\r
+    alien-invoke gc ;\r
 \r
 [ 25 ] [ 2 3 4 5 ffi_test_18 ] unit-test\r
 \r
 : ffi_test_19 ( x y z -- bar )\r
     "bar" "f-stdcall" "ffi_test_19" { "long" "long" "long" }\r
-    alien-invoke data-gc ;\r
+    alien-invoke gc ;\r
 \r
 [ 11 6 -7 ] [\r
     11 6 -7 ffi_test_19 dup bar-x over bar-y rot bar-z\r
@@ -143,7 +143,7 @@ FUNCTION: void ffi_test_20 double x1, double x2, double x3,
     "void"\r
     f "ffi_test_31"\r
     { "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" "int" }\r
-    alien-invoke code-gc 3 ;\r
+    alien-invoke gc 3 ;\r
 \r
 [ 3 ] [ 42 [ ] each ffi_test_31 ] unit-test\r
 \r
@@ -312,14 +312,14 @@ FUNCTION: double ffi_test_36 ( test-struct-12 x ) ;
 \r
 : callback-4\r
     "void" { } "cdecl" [ "Hello world" write ] alien-callback\r
-    data-gc ;\r
+    gc ;\r
 \r
 [ "Hello world" ] [ \r
     [ callback-4 callback_test_1 ] with-string-writer\r
 ] unit-test\r
 \r
 : callback-5\r
-    "void" { } "cdecl" [ data-gc ] alien-callback ;\r
+    "void" { } "cdecl" [ gc ] alien-callback ;\r
 \r
 [ "testing" ] [\r
     "testing" callback-5 callback_test_1\r
index 1a9d5b5392044e2d5ad30e693d2a86872c54b308..594c42268c95c30f3280ff8eb97e950ac24d1782 100755 (executable)
@@ -9,6 +9,14 @@ kernel.private threads continuations.private libc combinators
 compiler.errors continuations layouts accessors ;
 IN: alien.compiler
 
+TUPLE: #alien-node < node return parameters abi ;
+
+TUPLE: #alien-callback < #alien-node quot xt ;
+
+TUPLE: #alien-indirect < #alien-node ;
+
+TUPLE: #alien-invoke < #alien-node library function ;
+
 : large-struct? ( ctype -- ? )
     dup c-struct? [
         heap-size struct-small-enough? not
@@ -62,29 +70,36 @@ GENERIC: reg-size ( register-class -- n )
 
 M: int-regs reg-size drop cell ;
 
-M: float-regs reg-size float-regs-size ;
+M: single-float-regs reg-size drop 4 ;
+
+M: double-float-regs reg-size drop 8 ;
+
+GENERIC: reg-class-variable ( register-class -- symbol )
+
+M: reg-class reg-class-variable ;
+
+M: float-regs reg-class-variable drop float-regs ;
 
 GENERIC: inc-reg-class ( register-class -- )
 
-: (inc-reg-class)
-    dup class inc
+M: reg-class inc-reg-class
+    dup reg-class-variable inc
     fp-shadows-int? [ reg-size stack-params +@ ] [ drop ] if ;
 
-M: int-regs inc-reg-class
-    (inc-reg-class) ;
-
 M: float-regs inc-reg-class
-    dup (inc-reg-class)
+    dup call-next-method
     fp-shadows-int? [ reg-size cell /i int-regs +@ ] [ drop ] if ;
 
 : reg-class-full? ( class -- ? )
-    dup class get swap param-regs length >= ;
+    [ reg-class-variable get ] [ param-regs length ] bi >= ;
 
 : spill-param ( reg-class -- n reg-class )
-    reg-size stack-params dup get -rot +@ T{ stack-params } ;
+    stack-params get
+    >r reg-size stack-params +@ r>
+    stack-params ;
 
 : fastcall-param ( reg-class -- n reg-class )
-    [ dup class get swap inc-reg-class ] keep ;
+    [ reg-class-variable get ] [ inc-reg-class ] [ ] tri ;
 
 : alloc-parameter ( parameter -- reg reg-class )
     c-type-reg-class dup reg-class-full?
@@ -229,32 +244,32 @@ M: no-such-symbol compiler-error-type
     ] if ;
 
 : alien-invoke-dlsym ( node -- symbols dll )
-    dup alien-invoke-function dup pick stdcall-mangle 2array
-    swap alien-invoke-library library dup [ library-dll ] when
+    dup function>> dup pick stdcall-mangle 2array
+    swap library>> library dup [ dll>> ] when
     2dup check-dlsym ;
 
 \ alien-invoke [
     ! Four literals
     4 ensure-values
-    \ alien-invoke empty-node
+    #alien-invoke construct-empty
     ! Compile-time parameters
-    pop-parameters over set-alien-invoke-parameters
-    pop-literal nip over set-alien-invoke-function
-    pop-literal nip over set-alien-invoke-library
-    pop-literal nip over set-alien-invoke-return
+    pop-parameters >>parameters
+    pop-literal nip >>function
+    pop-literal nip >>library
+    pop-literal nip >>return
     ! Quotation which coerces parameters to required types
     dup make-prep-quot recursive-state get infer-quot
     ! Set ABI
-    dup alien-invoke-library
-    library [ library-abi ] [ "cdecl" ] if*
-    over set-alien-invoke-abi
+    dup library>>
+    library [ abi>> ] [ "cdecl" ] if*
+    >>abi
     ! Add node to IR
     dup node,
     ! Magic #: consume exactly the number of inputs
     0 alien-invoke-stack
 ] "infer" set-word-prop
 
-M: alien-invoke generate-node
+M: #alien-invoke generate-node
     dup alien-invoke-frame [
         end-basic-block
         %prepare-alien-invoke
@@ -273,11 +288,11 @@ M: alien-indirect-error summary
     ! Three literals and function pointer
     4 ensure-values
     4 reify-curries
-    \ alien-indirect empty-node
+    #alien-indirect construct-empty
     ! Compile-time parameters
-    pop-literal nip over set-alien-indirect-abi
-    pop-parameters over set-alien-indirect-parameters
-    pop-literal nip over set-alien-indirect-return
+    pop-literal nip >>abi
+    pop-parameters >>parameters
+    pop-literal nip >>return
     ! Quotation which coerces parameters to required types
     dup make-prep-quot [ dip ] curry recursive-state get infer-quot
     ! Add node to IR
@@ -286,7 +301,7 @@ M: alien-indirect-error summary
     1 alien-invoke-stack
 ] "infer" set-word-prop
 
-M: alien-indirect generate-node
+M: #alien-indirect generate-node
     dup alien-invoke-frame [
         ! Flush registers
         end-basic-block
@@ -315,17 +330,17 @@ M: alien-callback-error summary
     drop "Words calling ``alien-callback'' must be compiled with the optimizing compiler." ;
 
 : callback-bottom ( node -- )
-    alien-callback-xt [ word-xt drop <alien> ] curry
+    xt>> [ word-xt drop <alien> ] curry
     recursive-state get infer-quot ;
 
 \ alien-callback [
     4 ensure-values
-    \ alien-callback empty-node dup node,
-    pop-literal nip over set-alien-callback-quot
-    pop-literal nip over set-alien-callback-abi
-    pop-parameters over set-alien-callback-parameters
-    pop-literal nip over set-alien-callback-return
-    gensym dup register-callback over set-alien-callback-xt
+    #alien-callback construct-empty dup node,
+    pop-literal nip >>quot
+    pop-literal nip >>abi
+    pop-parameters >>parameters
+    pop-literal nip >>return
+    gensym dup register-callback >>xt
     callback-bottom
 ] "infer" set-word-prop
 
@@ -360,13 +375,12 @@ TUPLE: callback-context ;
     return>> {
         { [ dup "void" = ] [ drop [ ] ] }
         { [ dup large-struct? ] [ heap-size [ memcpy ] curry ] }
-        { [ t ] [ c-type c-type-prep ] }
+        [ c-type c-type-prep ]
     } cond ;
 
 : wrap-callback-quot ( node -- quot )
     [
-        dup alien-callback-quot
-        swap prepare-callback-return append ,
+        [ quot>> ] [ prepare-callback-return ] bi append ,
         [ callback-context construct-empty do-callback ] %
     ] [ ] make ;
 
@@ -376,7 +390,7 @@ TUPLE: callback-context ;
     {
         { [ dup abi>> "stdcall" = ] [ alien-stack-frame ] }
         { [ dup return>> large-struct? ] [ drop 4 ] }
-        { [ t ] [ drop 0 ] }
+        [ drop 0 ]
     } cond ;
 
 : %callback-return ( node -- )
@@ -387,7 +401,7 @@ TUPLE: callback-context ;
     callback-unwind %unwind ;
 
 : generate-callback ( node -- )
-    dup alien-callback-xt dup [
+    dup xt>> dup [
         init-templates
         %save-word-xt
         %prologue-later
@@ -398,5 +412,5 @@ TUPLE: callback-context ;
         ] with-stack-frame
     ] with-generator ;
 
-M: alien-callback generate-node
+M: #alien-callback generate-node
     end-basic-block generate-callback iterate-next ;
index 6e4b8b4e21d8bef988fddfb6778f937a37d6edd9..67ea30f379f9ee330609df42517a9663cb55eaf5 100755 (executable)
@@ -68,7 +68,7 @@ M: alien pprint*
     {
         { [ dup expired? ] [ drop "( alien expired )" text ] }
         { [ dup pinned-c-ptr? not ] [ drop "( displaced alien )" text ] }
-        { [ t ] [ \ ALIEN: [ alien-address pprint* ] pprint-prefix ] }
+        [ \ ALIEN: [ alien-address pprint* ] pprint-prefix ]
     } cond ;
 
 M: dll pprint* dll-path dup "DLL\" " "\"" pprint-string ;
index 6b6bd3d51ab690358a9aa856b01c8dcb29a754b2..adb69d317c40d4cff0a1b52907bb965352a48448 100755 (executable)
@@ -155,6 +155,9 @@ M: assoc >alist [ 2array ] { } assoc>map ;
 : value-at ( value assoc -- key/f )
     swap [ = nip ] curry assoc-find 2drop ;
 
+: zip ( keys values -- alist )
+    2array flip ; inline
+
 : search-alist ( key alist -- pair i )
     [ first = ] with find swap ; inline
 
@@ -204,7 +207,7 @@ M: enum set-at seq>> set-nth ;
 M: enum delete-at enum-seq delete-nth ;
 
 M: enum >alist ( enum -- alist )
-    seq>> [ length ] keep 2array flip ;
+    seq>> [ length ] keep zip ;
 
 M: enum assoc-size seq>> length ;
 
index 6b467caa5a2a97f06dbf73576a54ace6254143dc..9e101126e6683ab4996d2d0efe84d4ed7eba843d 100755 (executable)
@@ -19,7 +19,7 @@ IN: bootstrap.compiler
 enable-compiler
 
 nl
-"Compiling some words to speed up bootstrap..." write flush
+"Compiling..." write flush
 
 ! Compile a set of words ahead of the full compile.
 ! This set of words was determined semi-empirically
@@ -37,8 +37,6 @@ nl
 
     wrap probe
 
-    delegate
-
     underlying
 
     find-pair-next namestack*
@@ -76,4 +74,6 @@ nl
     malloc calloc free memcpy
 } compile
 
+vocabs [ words [ compiled? not ] subset compile "." write flush ] each
+
 " done" print flush
index 6e0f8e2970625b7dc57f25af61017f965c7a5583..05d48af2e8be3745416913832306b9ff65824a7b 100755 (executable)
@@ -4,9 +4,9 @@ USING: alien arrays bit-arrays byte-arrays generic assocs
 hashtables assocs hashtables.private io kernel kernel.private
 math namespaces parser prettyprint sequences sequences.private
 strings sbufs vectors words quotations assocs system layouts
-splitting growable classes classes.tuple classes.tuple.private
-words.private io.binary io.files vocabs vocabs.loader
-source-files definitions debugger float-arrays
+splitting growable classes classes.builtin classes.tuple
+classes.tuple.private words.private io.binary io.files vocabs
+vocabs.loader source-files definitions debugger float-arrays
 quotations.private sequences.private combinators
 io.encodings.binary ;
 IN: bootstrap.image
index 6c877302783f0704873252a5fb6cf4734757be7d..9d3c28b068ded91f4e27e2a7a228073c51314ea7 100755 (executable)
@@ -3,10 +3,10 @@
 USING: alien arrays byte-arrays generic hashtables
 hashtables.private io kernel math namespaces parser sequences
 strings vectors words quotations assocs layouts classes
-classes.tuple classes.tuple.private kernel.private vocabs
-vocabs.loader source-files definitions slots.deprecated
-classes.union compiler.units bootstrap.image.private io.files
-accessors combinators ;
+classes.builtin classes.tuple classes.tuple.private
+kernel.private vocabs vocabs.loader source-files definitions
+slots.deprecated classes.union compiler.units
+bootstrap.image.private io.files accessors combinators ;
 IN: bootstrap.primitives
 
 "Creating primitives and basic runtime structures..." print flush
@@ -30,7 +30,7 @@ crossref off
 ! Bring up a bare cross-compiling vocabulary.
 "syntax" vocab vocab-words bootstrap-syntax set
 H{ } clone dictionary set
-H{ } clone changed-words set
+H{ } clone changed-definitions set
 H{ } clone forgotten-definitions set
 H{ } clone root-cache set
 H{ } clone source-files set
@@ -640,8 +640,7 @@ define-builtin
     { "setenv" "kernel.private" }
     { "(exists?)" "io.files.private" }
     { "(directory)" "io.files.private" }
-    { "data-gc" "memory" }
-    { "code-gc" "memory" }
+    { "gc" "memory" }
     { "gc-time" "memory" }
     { "save-image" "memory" }
     { "save-image-and-exit" "memory" }
@@ -733,11 +732,14 @@ define-builtin
     { "set-innermost-frame-quot" "kernel.private" }
     { "call-clear" "kernel" }
     { "(os-envs)" "system.private" }
+    { "set-os-env" "system" }
+    { "unset-os-env" "system" }
     { "(set-os-envs)" "system.private" }
     { "resize-byte-array" "byte-arrays" }
     { "resize-bit-array" "bit-arrays" }
     { "resize-float-array" "float-arrays" }
     { "dll-valid?" "alien" }
+    { "unimplemented" "kernel.private" }
 }
 dup length [ >r first2 r> make-primitive ] 2each
 
index c82ebbe9f87f068fbdd2dc655ea775053f982e3a..a75b111e78a944394bb3931bdef6b7306717305a 100755 (executable)
@@ -27,9 +27,9 @@ SYMBOL: bootstrap-time
     seq-diff
     [ "bootstrap." prepend require ] each ;
 
-: compile-remaining ( -- )
-    "Compiling remaining words..." print flush
-    vocabs [ words [ compiled? not ] subset compile ] each ;
+: compile-remaining ( -- )
+    "Compiling remaining words..." print flush
+    vocabs [ words [ compiled? not ] subset compile ] each ;
 
 : count-words ( pred -- )
     all-words swap subset length number>string write ;
@@ -57,7 +57,7 @@ millis >r
 
 default-image-name "output-image" set-global
 
-"math help handbook compiler random tools ui ui.tools io" "include" set-global
+"math compiler help random tools ui ui.tools io handbook" "include" set-global
 "" "exclude" set-global
 
 parse-command-line
@@ -79,10 +79,6 @@ os winnt? [ "windows.nt" require ] when
     load-components
 
     run-bootstrap-init
-
-    "bootstrap.compiler" vocab [
-        compile-remaining
-    ] when
 ] with-compiler-errors
 :errors
 
index 0f468908a95ecde2b62cae036bd97b5e684b48a3..d61b62af3b9e94925f36f71b2a137cdcef44aeef 100755 (executable)
@@ -68,13 +68,13 @@ UNION: c a b ;
 [ t ] [ \ tuple-class \ class class< ] unit-test\r
 [ f ] [ \ class \ tuple-class class< ] unit-test\r
 \r
-TUPLE: delegate-clone ;\r
+TUPLE: tuple-example ;\r
 \r
-[ t ] [ \ null \ delegate-clone class< ] unit-test\r
-[ f ] [ \ object \ delegate-clone class< ] unit-test\r
-[ f ] [ \ object \ delegate-clone class< ] unit-test\r
-[ t ] [ \ delegate-clone \ tuple class< ] unit-test\r
-[ f ] [ \ tuple \ delegate-clone class< ] unit-test\r
+[ t ] [ \ null \ tuple-example class< ] unit-test\r
+[ f ] [ \ object \ tuple-example class< ] unit-test\r
+[ f ] [ \ object \ tuple-example class< ] unit-test\r
+[ t ] [ \ tuple-example \ tuple class< ] unit-test\r
+[ f ] [ \ tuple \ tuple-example class< ] unit-test\r
 \r
 TUPLE: a1 ;\r
 TUPLE: b1 ;\r
index 97309dbea257d584408448bc84a1cb8f6ac9a9ff..faf57fcd0df6bedf088205fc79c7b79b3785aa94 100755 (executable)
@@ -1,8 +1,8 @@
 ! Copyright (C) 2004, 2008 Slava Pestov.\r
 ! See http://factorcode.org/license.txt for BSD license.\r
-USING: kernel classes combinators accessors sequences arrays\r
-vectors assocs namespaces words sorting layouts math hashtables\r
-kernel.private ;\r
+USING: kernel classes classes.builtin combinators accessors\r
+sequences arrays vectors assocs namespaces words sorting layouts\r
+math hashtables kernel.private ;\r
 IN: classes.algebra\r
 \r
 : 2cache ( key1 key2 assoc quot -- value )\r
@@ -84,7 +84,7 @@ C: <anonymous-complement> anonymous-complement
         { [ dup anonymous-complement? ] [ class>> classes-intersect? not ] }\r
         { [ dup members ] [ right-union-class< ] }\r
         { [ over superclass ] [ superclass< ] }\r
-        { [ t ] [ 2drop f ] }\r
+        [ 2drop f ]\r
     } cond ;\r
 \r
 : anonymous-union-intersect? ( first second -- ? )\r
@@ -103,15 +103,15 @@ C: <anonymous-complement> anonymous-complement
     {\r
         { [ over tuple eq? ] [ 2drop t ] }\r
         { [ over builtin-class? ] [ 2drop f ] }\r
-        { [ over tuple-class? ] [ [ class< ] 2keep swap class< or ] }\r
-        { [ t ] [ swap classes-intersect? ] }\r
+        { [ over tuple-class? ] [ [ class< ] [ swap class< ] 2bi or ] }\r
+        [ swap classes-intersect? ]\r
     } cond ;\r
 \r
 : builtin-class-intersect? ( first second -- ? )\r
     {\r
         { [ 2dup eq? ] [ 2drop t ] }\r
         { [ over builtin-class? ] [ 2drop f ] }\r
-        { [ t ] [ swap classes-intersect? ] }\r
+        [ swap classes-intersect? ]\r
     } cond ;\r
 \r
 : (classes-intersect?) ( first second -- ? )\r
@@ -154,7 +154,7 @@ C: <anonymous-complement> anonymous-complement
         { [ over members ] [ left-union-and ] }\r
         { [ over anonymous-union? ] [ left-anonymous-union-and ] }\r
         { [ over anonymous-intersection? ] [ left-anonymous-intersection-and ] }\r
-        { [ t ] [ 2array <anonymous-intersection> ] }\r
+        [ 2array <anonymous-intersection> ]\r
     } cond ;\r
 \r
 : left-anonymous-union-or ( first second -- class )\r
@@ -169,7 +169,7 @@ C: <anonymous-complement> anonymous-complement
         { [ 2dup swap class< ] [ drop ] }\r
         { [ dup anonymous-union? ] [ right-anonymous-union-or ] }\r
         { [ over anonymous-union? ] [ left-anonymous-union-or ] }\r
-        { [ t ] [ 2array <anonymous-union> ] }\r
+        [ 2array <anonymous-union> ]\r
     } cond ;\r
 \r
 : (class-not) ( class -- complement )\r
@@ -177,7 +177,7 @@ C: <anonymous-complement> anonymous-complement
         { [ dup anonymous-complement? ] [ class>> ] }\r
         { [ dup object eq? ] [ drop null ] }\r
         { [ dup null eq? ] [ drop object ] }\r
-        { [ t ] [ <anonymous-complement> ] }\r
+        [ <anonymous-complement> ]\r
     } cond ;\r
 \r
 : largest-class ( seq -- n elt )\r
@@ -205,7 +205,7 @@ C: <anonymous-complement> anonymous-complement
         { [ dup builtin-class? ] [ dup set ] }\r
         { [ dup members ] [ members [ (flatten-class) ] each ] }\r
         { [ dup superclass ] [ superclass (flatten-class) ] }\r
-        { [ t ] [ drop ] }\r
+        [ drop ]\r
     } cond ;\r
 \r
 : flatten-class ( class -- assoc )\r
diff --git a/core/classes/builtin/builtin-docs.factor b/core/classes/builtin/builtin-docs.factor
new file mode 100644 (file)
index 0000000..054587f
--- /dev/null
@@ -0,0 +1,28 @@
+USING: help.syntax help.markup classes layouts ;
+IN: classes.builtin
+
+ARTICLE: "builtin-classes" "Built-in classes"
+"Every object is an instance of exactly one canonical " { $emphasis "built-in class" } " which defines its layout in memory and basic behavior."
+$nl
+"The set of built-in classes is a class:"
+{ $subsection builtin-class }
+{ $subsection builtin-class? }
+"See " { $link "type-index" } " for a list of built-in classes." ;
+
+HELP: builtin-class
+{ $class-description "The class of built-in classes." }
+{ $examples
+    "The class of arrays is a built-in class:"
+    { $example "USING: arrays classes.builtin prettyprint ;" "array builtin-class? ." "t" }
+    "However, an instance of the array class is not a built-in class; it is not even a class:"
+    { $example "USING: classes.builtin prettyprint ;" "{ 1 2 3 } builtin-class? ." "f" }
+} ;
+
+HELP: builtins
+{ $var-description "Vector mapping type numbers to builtin class words." } ;
+
+HELP: type>class
+{ $values { "n" "a non-negative integer" } { "class" class } }
+{ $description "Outputs a builtin class whose instances are precisely those having a given pointer tag." }
+{ $notes "The parameter " { $snippet "n" } " must be between 0 and the return value of " { $link num-types } "." } ;
+
diff --git a/core/classes/builtin/builtin.factor b/core/classes/builtin/builtin.factor
new file mode 100644 (file)
index 0000000..1c2871b
--- /dev/null
@@ -0,0 +1,18 @@
+! Copyright (C) 2004, 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: classes words kernel kernel.private namespaces
+sequences ;
+IN: classes.builtin
+
+SYMBOL: builtins
+
+PREDICATE: builtin-class < class
+    "metaclass" word-prop builtin-class eq? ;
+
+: type>class ( n -- class ) builtins get-global nth ;
+
+: bootstrap-type>class ( n -- class ) builtins get nth ;
+
+M: hi-tag class hi-tag type>class ;
+
+M: object class tag type>class ;
index 3f30b71457bfb7954468c783e5fe2badc166e145..dd3782e877f80295c58f2589f6496716a434c007 100755 (executable)
@@ -4,14 +4,6 @@ layouts classes.private classes.union classes.mixin
 classes.predicate quotations ;
 IN: classes
 
-ARTICLE: "builtin-classes" "Built-in classes"
-"Every object is an instance of exactly one canonical " { $emphasis "built-in class" } " which defines its layout in memory and basic behavior."
-$nl
-"The set of built-in classes is a class:"
-{ $subsection builtin-class }
-{ $subsection builtin-class? }
-"See " { $link "type-index" } " for a list of built-in classes." ;
-
 ARTICLE: "class-predicates" "Class predicate words"
 "With a handful of exceptions, each class has a membership predicate word, named " { $snippet { $emphasis "class" } "?" } " . A quotation calling this predicate is stored in the " { $snippet "\"predicate\"" } " word property."
 $nl
@@ -38,17 +30,21 @@ $nl
 { $subsection class? }
 "You can ask an object for its class:"
 { $subsection class }
+"Testing if an object is an instance of a class:"
+{ $subsection instance? }
 "There is a universal class which all objects are an instance of, and an empty class with no instances:"
 { $subsection object }
 { $subsection null }
 "Obtaining a list of all defined classes:"
 { $subsection classes }
-"Other sorts of classes:"
+"There are several sorts of classes:"
 { $subsection "builtin-classes" }
 { $subsection "unions" }
-{ $subsection "singletons" }
 { $subsection "mixins" }
 { $subsection "predicates" }
+{ $subsection "singletons" }
+{ $link "tuples" } " are documented in their own section."
+$nl
 "Classes can be inspected and operated upon:"
 { $subsection "class-operations" }
 { $see-also "class-index" } ;
@@ -58,37 +54,20 @@ ABOUT: "classes"
 HELP: class
 { $values { "object" object } { "class" class } }
 { $description "Outputs an object's canonical class. While an object may be an instance of more than one class, the canonical class is either its built-in class, or if the object is a tuple, its tuple class." }
-{ $class-description "The class of all class words. Subclasses include " { $link builtin-class } ", " { $link union-class } ", " { $link mixin-class } ", " { $link predicate-class } " and " { $link tuple-class } "." }
+{ $class-description "The class of all class words." }
 { $examples { $example "USING: classes prettyprint ;" "1.0 class ." "float" } { $example "USING: classes prettyprint ;" "TUPLE: point x y z ;\nT{ point f 1 2 3 } class ." "point" } } ;
 
 HELP: classes
 { $values { "seq" "a sequence of class words" } }
 { $description "Finds all class words in the dictionary." } ;
 
-HELP: builtin-class
-{ $class-description "The class of built-in classes." }
-{ $examples
-    "The class of arrays is a built-in class:"
-    { $example "USING: arrays classes prettyprint ;" "array builtin-class? ." "t" }
-    "However, an instance of the array class is not a built-in class; it is not even a class:"
-    { $example "USING: classes prettyprint ;" "{ 1 2 3 } builtin-class? ." "f" }
-} ;
-
 HELP: tuple-class
 { $class-description "The class of tuple class words." }
 { $examples { $example "USING: classes prettyprint ;" "TUPLE: name title first last ;" "name tuple-class? ." "t" } } ;
 
-HELP: builtins
-{ $var-description "Vector mapping type numbers to builtin class words." } ;
-
 HELP: update-map
 { $var-description "Hashtable mapping each class to a set of classes defined in terms of this class. The " { $link define-class } " word uses this information to update generic words when classes are redefined." } ;
 
-HELP: type>class
-{ $values { "n" "a non-negative integer" } { "class" class } }
-{ $description "Outputs a builtin class whose instances are precisely those having a given pointer tag." }
-{ $notes "The parameter " { $snippet "n" } " must be between 0 and the return value of " { $link num-types } "." } ;
-
 HELP: predicate-word
 { $values { "word" "a word" } { "predicate" "a predicate word" } }
 { $description "Suffixes the word's name with \"?\" and creates a word with that name in the same vocabulary as the word itself." } ;
index c45fd7360b8a3d5cf8a101ac7f9e740c5f3c33d0..b22e21eb9288ec5571b93ce293abbc46dcddcb04 100755 (executable)
@@ -30,20 +30,11 @@ SYMBOL: update-map
 PREDICATE: class < word
     "class" word-prop ;
 
-SYMBOL: builtins
-
-PREDICATE: builtin-class < class
-    "metaclass" word-prop builtin-class eq? ;
-
 PREDICATE: tuple-class < class
     "metaclass" word-prop tuple-class eq? ;
 
 : classes ( -- seq ) all-words [ class? ] subset ;
 
-: type>class ( n -- class ) builtins get-global nth ;
-
-: bootstrap-type>class ( n -- class ) builtins get nth ;
-
 : predicate-word ( word -- predicate )
     [ word-name "?" append ] keep word-vocabulary create ;
 
@@ -130,9 +121,5 @@ GENERIC: update-methods ( assoc -- )
 
 GENERIC: class ( object -- class )
 
-M: hi-tag class hi-tag type>class ;
-
-M: object class tag type>class ;
-
 : instance? ( obj class -- ? )
     "predicate" word-prop call ;
index 1fa6f7bd830af94d4fc0a594ced5dd65770ef3bf..82dec5cec02c0b78d114cddf27efaca156924997 100755 (executable)
@@ -1,16 +1,18 @@
 USING: help.markup help.syntax help words compiler.units
-classes ;
+classes sequences ;
 IN: classes.mixin
 
 ARTICLE: "mixins" "Mixin classes"
-"An object is an instance of a union class if it is an instance of one of its members. In this respect, mixin classes are identical to union classes. However, new classes can be made into instances of a mixin class after the original definition of the mixin."
+"An object is an instance of a union class if it is an instance of one of its members. In this respect, mixin classes are identical to union classes. However, mixin classes have the additional property that they are " { $emphasis "open" } "; new classes can be added to the mixin after the original definition of the mixin."
 { $subsection POSTPONE: MIXIN: }
 { $subsection POSTPONE: INSTANCE: }
 { $subsection define-mixin-class }
 { $subsection add-mixin-instance }
 "The set of mixin classes is a class:"
 { $subsection mixin-class }
-{ $subsection mixin-class? } ;
+{ $subsection mixin-class? }
+"Mixins are used to defines suites of behavior which are generally useful and can be applied to user-defined classes. For example, the " { $link immutable-sequence } " mixin can be used with user-defined sequences to make them immutable."
+{ $see-also "unions" "tuple-subclassing" } ;
 
 HELP: mixin-class
 { $class-description "The class of mixin classes." } ;
index aefd522269320c064a5b815312d241e194011c8d..9bbe89d7d90375c0c3a1596bc743c73e2eab15de 100755 (executable)
@@ -49,7 +49,7 @@ M: mixin-instance equal?
         { [ over mixin-instance? not ] [ f ] }
         { [ 2dup [ mixin-instance-class ] bi@ = not ] [ f ] }
         { [ 2dup [ mixin-instance-mixin ] bi@ = not ] [ f ] }
-        { [ t ] [ t ] }
+        [ t ]
     } cond 2nip ;
 
 M: mixin-instance hashcode*
index 8548f84a3afda3515ee856e71edc6549aabc5d0e..a8dae809ec085242e58c5ecd777451d84a8a0378 100644 (file)
@@ -2,27 +2,33 @@ USING: help.markup help.syntax kernel words ;
 IN: classes.singleton
 
 ARTICLE: "singletons" "Singleton classes"
-"A singleton is a class with only one instance and with no state.  Methods may dispatch off of singleton classes."
+"A singleton is a class with only one instance and with no state."
 { $subsection POSTPONE: SINGLETON: }
-{ $subsection define-singleton-class } ;
+{ $subsection define-singleton-class }
+"The set of all singleton classes is itself a class:"
+{ $subsection singleton-class? }
+{ $subsection singleton-class } ;
 
 HELP: SINGLETON:
-{ $syntax "SINGLETON: class"
-{ $values
+{ $syntax "SINGLETON: class" }
+{ $values
     { "class" "a new singleton to define" }
-} { $description
-    "Defines a new predicate class whose superclass is " { $link word } ".  Only one instance of a singleton may exist because classes are " { $link eq? } " to themselves.  Methods may be defined on a singleton."
-} { $examples
+}
+{ $description
+    "Defines a new singleton class. The class word itself is the sole instance of the singleton class."
+}
+{ $examples
     { $example "USING: classes.singleton kernel io ;" "SINGLETON: foo\nGENERIC: bar ( obj -- )\nM: foo bar drop \"a foo!\" print ;\nfoo bar" "a foo!" }
-} { $see-also
-    POSTPONE: PREDICATE:
 } ;
 
 HELP: define-singleton-class
 { $values { "word" "a new word" } }
 { $description
-    "Defines a newly created word to be a singleton class." } ;
+    "Defines a singleton class. This is the run-time equivalent of " { $link POSTPONE: SINGLETON: } "." } ;
 
 { POSTPONE: SINGLETON: define-singleton-class } related-words
 
+HELP: singleton-class
+{ $class-description "The class of singleton classes." } ;
+
 ABOUT: "singletons"
index 664f0545facc301458f0ace28d9f78f57f186a61..5d35afb7d3bc82ade46f71e1b9ba62c799483cfa 100755 (executable)
@@ -3,14 +3,63 @@ classes.tuple.private classes slots quotations words arrays
 generic.standard sequences definitions compiler.units ;
 IN: classes.tuple
 
-ARTICLE: "tuple-constructors" "Constructors"
-"Tuples are created by calling one of two words:"
+ARTICLE: "parametrized-constructors" "Parameterized constructors"
+"A " { $emphasis "parametrized constructor" } " is a word which directly or indirectly calls " { $link construct-empty } " or " { $link construct-boa } ", but instead of passing a literal class symbol, it takes the class symbol as an input from the stack."
+$nl
+"Parametrized constructors are useful in many situations, in particular with subclassing. For example, consider the following code:"
+{ $code
+    "TUPLE: vehicle max-speed occupants ;"
+    ""
+    ": add-occupant ( person vehicle -- ) occupants>> push ;"
+    ""
+    "TUPLE: car < vehicle engine ;"
+    ": <car> ( max-speed engine -- car )"
+    "    car construct-empty"
+    "        V{ } clone >>occupants"
+    "        swap >>engine"
+    "        swap >>max-speed ;"
+    ""
+    "TUPLE: aeroplane < vehicle max-altitude ;"
+    ": <aeroplane> ( max-speed max-altitude -- aeroplane )"
+    "    aeroplane construct-empty"
+    "        V{ } clone >>occupants"
+    "        swap >>max-altitude"
+    "        swap >>max-speed ;"
+}
+"The two constructors depend on the implementation of " { $snippet "vehicle" } " because they are responsible for initializing the " { $snippet "occupants" } " slot to an empty vector. If this slot is changed to contain a hashtable instead, there will be two places instead of one. A better approach is to use a parametrized constructor for vehicles:"
+{ $code
+    "TUPLE: vehicle max-speed occupants ;"
+    ""
+    ": add-occupant ( person vehicle -- ) occupants>> push ;"
+    ""
+    ": construct-vehicle ( class -- vehicle )"
+    "    construct-empty"
+    "        V{ } clone >>occupants ;"
+    ""
+    "TUPLE: car < vehicle engine ;"
+    ": <car> ( max-speed engine -- car )"
+    "    car construct-vehicle"
+    "        swap >>engine"
+    "        swap >>max-speed ;"
+    ""
+    "TUPLE: aeroplane < vehicle max-altitude ;"
+    ": <aeroplane> ( max-speed max-altitude -- aeroplane )"
+    "    aeroplane construct-vehicle"
+    "        swap >>max-altitude"
+    "        swap >>max-speed ;"
+}
+"The naming convention for parametrized constructors is " { $snippet "construct-" { $emphasis "class" } } "." ;
+
+ARTICLE: "tuple-constructors" "Tuple constructors"
+"Tuples are created by calling one of two constructor primitives:"
 { $subsection construct-empty }
 { $subsection construct-boa }
-"By convention, construction logic is encapsulated in a word named after the tuple class surrounded in angle brackets; for example, the constructor word for a " { $snippet "point" } " class might be named " { $snippet "<point>" } "."
-$nl
 "A shortcut for defining BOA constructors:"
 { $subsection POSTPONE: C: }
+"By convention, construction logic is encapsulated in a word named after the tuple class surrounded in angle brackets; for example, the constructor word for a " { $snippet "point" } " class might be named " { $snippet "<point>" } "."
+$nl
+"All tuple construction should be done through constructor words, and construction primitives should be encapsulated and never called outside of the vocabulary where the class is defined, because this encourages looser coupling. For example, a constructor word could be changed to use memoization instead of always constructing a new instance, or it could be changed to construt a different class, without breaking callers."
+$nl
 "Examples of constructors:"
 { $code
     "TUPLE: color red green blue alpha ;"
@@ -22,29 +71,77 @@ $nl
     ""
     ": <color> construct-empty ;"
     ": <color> f f f f <rgba> ; ! identical to above"
+}
+{ $subsection "parametrized-constructors" } ;
+
+ARTICLE: "tuple-inheritance-example" "Tuple subclassing example"
+"Rectangles, parallelograms and circles are all shapes. We support two operations on shapes:"
+{ $list
+    "Computing the area"
+    "Computing the perimiter"
+}
+"Rectangles and parallelograms use the same algorithm for computing the area, whereas they use different algorithms for computing perimiter. Also, rectangles and parallelograms both have " { $snippet "width" } " and " { $snippet "height" } " slots. We can exploit this with subclassing:"
+{ $code
+    "GENERIC: area ( shape -- n )"
+    "GENERIC: perimiter ( shape -- n )"
+    ""
+    "TUPLE: shape ;"
+    ""
+    "TUPLE: circle < shape radius ;"
+    "M: area circle radius>> sq pi * ;"
+    "M: perimiter circle radius>> 2 * pi * ;"
+    ""
+    "TUPLE: quad < shape width height"
+    "M: area quad [ width>> ] [ height>> ] bi * ;"
+    ""
+    "TUPLE: rectangle < quad ;"
+    "M: rectangle perimiter [ width>> 2 * ] [ height>> 2 * ] bi + ;"
+    ""
+    ": hypot ( a b -- c ) [ sq ] bi@ + sqrt ;"
+    ""
+    "TUPLE: parallelogram < quad skew ;"
+    "M: parallelogram perimiter"
+    "    [ width>> 2 * ] [ [ height>> ] [ skew>> ] bi hypot 2 * ] bi + ;"
 } ;
 
-ARTICLE: "tuple-delegation" "Tuple delegation"
-"If a generic word having the " { $link standard-combination } " method combination is called on a tuple for which it does not have an applicable method, the method call is forwarded to the tuple's " { $emphasis "delegate" } ". If no delegate is set, a " { $link no-method } " error is thrown."
-{ $subsection delegate }
-{ $subsection set-delegate }
-"A tuple's delegate should either be another tuple, or " { $link f } ", indicating no delegate is set. Delegation from a tuple to an object of some other type is not fully supported and should be used with caution."
+ARTICLE: "tuple-inheritance-anti-example" "When not to use tuple subclassing"
+"Tuple subclassing should only be used for " { $emphasis "is-a" } " relationships; for example, a car " { $emphasis "is a" } " vehicle, and a circle " { $emphasis "is a" } " shape."
+{ $heading "Anti-pattern #1: subclassing for has-a" }
+"Subclassing should not be used for " { $emphasis "has-a" } " relationships. For example, if a shape " { $emphasis "has a" } " color, then " { $snippet "shape" } " should not subclass " { $snippet "color" } ". Using tuple subclassing in inappropriate situations leads to code which is more brittle and less flexible than it should be."
 $nl
-"Factor uses delegation in place of implementation inheritance, but it is not a direct substitute; in particular, the semantics differ in that a delegated method call receives the delegate on the stack, not the original object."
+"For example, suppose that " { $snippet "shape" } " inherits from " { $snippet "color" } ":"
+{ $code
+    "TUPLE: color r g b ;"
+    "TUPLE: shape < color ... ;"
+}
+"Now, the implementation of " { $snippet "shape" } " depends on a specific representation of colors as RGB colors. If a new generic color protocol is devised which also allows HSB and YUV colors to be used, the shape class will not be able to take advantage of them without changes. A better approach is to store the color in a slot:"
+{ $code
+    "TUPLE: rgb-color r g b ;"
+    "TUPLE: hsv-color h s v ;"
+    "..."
+    "TUPLE: shape color ... ;"
+}
+"The " { $vocab-link "delegate" } " library provides a language abstraction for expressing has-a relationships."
+{ $heading "Anti-pattern #2: subclassing for implementation sharing only" }
+"Tuple subclassing purely for sharing implementations of methods is not a good idea either. If a class " { $snippet "A" } " is a subclass of a class " { $snippet "B" } ", then instances of " { $snippet "A" } " should be usable anywhere that an instance of " { $snippet "B" } " is. If this properly does not hold, then subclassing should not be used."
 $nl
-"A pair of words examine delegation chains:"
-{ $subsection delegates }
-{ $subsection is? }
-"An example:"
-{ $example
-    "TUPLE: ellipse center radius ;"
-    "TUPLE: colored color ;"
-    "{ 0 0 } 10 <ellipse> \"my-ellipse\" set"
-    "{ 1 0 0 } <colored> \"my-shape\" set"
-    "\"my-ellipse\" get \"my-shape\" get set-delegate"
-    "\"my-shape\" get dup color>> swap center>> .s"
-    "{ 0 0 }\n{ 1 0 0 }"
-} ;
+"There are two alternatives which are preferred to subclassing in this case. The first is " { $link "mixins" } "."
+$nl
+"The second is to use ad-hoc slot polymorphism. If two classes define a slot with the same name, then code which uses " { $link "accessors" } " can operate on instances of both objects, assuming the values stored in that slot implement a common protocol. This allows code to be shared without creating contrieved relationships between classes."
+{ $heading "Anti-pattern #3: subclassing to override a method definition" }
+"While method overriding is a very powerful tool, improper use can cause tight coupling of code and lead to difficulty in testing and refactoring. Subclassing should not be used as a means of ``monkey patching'' methods to fix bugs and add features. Only subclass from classes which were designed to be inherited from, and when writing classes of your own which are intended to be subclassed, clearly document that subclasses may and may not do. This includes construction policy; document whether subclasses should use " { $link construct-empty } ", " { $link construct-boa } ", or a custom parametrized constructor."
+{ $see-also "parametrized-constructors" } ;
+
+ARTICLE: "tuple-subclassing" "Tuple subclassing"
+"Tuple subclassing can be used to express natural relationships between classes at the language level. For example, every car " { $emphasis "is a" } " vehicle, so if the " { $snippet "car" } " class subclasses the " { $snippet "vehicle" } " class, it can " { $emphasis "inherit" } " the slots and methods of " { $snippet "vehicle" } "."
+$nl
+"To define one tuple class as a subclass of another, use the optional superclass parameter to " { $link POSTPONE: TUPLE: } ":"
+{ $code
+    "TUPLE: subclass < superclass ... ;"
+}
+{ $subsection "tuple-inheritance-example" }
+{ $subsection "tuple-inheritance-anti-example" } 
+{ $see-also "call-next-method" "parametrized-constructors" "unions" "mixins" } ;
 
 ARTICLE: "tuple-introspection" "Tuple introspection"
 "In addition to the slot reader and writer words which " { $link POSTPONE: TUPLE: } " defines for every tuple class, it is possible to construct and take apart entire tuples in a generic way."
@@ -119,7 +216,28 @@ ARTICLE: "tuple-examples" "Tuple examples"
     ": promote ( person -- person )"
     "    [ 1.2 * ] change-salary"
     "    [ next-position ] change-position ;"
-} ;
+}
+"An example using subclassing can be found in " { $link "tuple-inheritance-example" } "." ;
+
+ARTICLE: "tuple-redefinition" "Tuple redefinition"
+"In the following, the " { $emphasis "direct slots" } " of a tuple class refers to the slot names specified in the " { $link POSTPONE: TUPLE: } " form defining the tuple class, and the " { $emphasis "effective slots" } " refers to the concatenation of the direct slots together with slots defined on superclasses."
+$nl
+"When a tuple class is redefined, all instances of the class, including subclasses, are updated. For each instance, the list of effective slots is compared with the previous list. If any slots were removed, the values are removed from the instance and are lost forever. If any slots were added, the instance gains these slots with an initial value of " { $link f } "."
+$nl
+"There are three ways to change the list of effective slots of a class:"
+{ $list
+    "Adding or removing direct slots of the class"
+    "Adding or removing direct slots of a superclass of the class"
+    "Changing the inheritance hierarchy by redefining a class to have a different superclass"
+}
+"In all cases, the new effective slots are compared with the old effective slots, and each instance is updated as follows:"
+{ $list
+    "If any slots were removed, the values are removed from the instance and are lost forever."
+    { "If any slots were added, the instance gains these slots with an initial value of " { $link f } "." }
+    "If any slots are permuted, their values in instances do not change; only the layout of the instance changes in memory."
+    "If the number or order of effective slots changes, any BOA constructors are recompiled."
+}
+"Note that if a slot is moved from a class to its superclass (or vice versa) in the same compilation unit, the value of the slot is preserved in existing instances, because tuple instance update always runs at the end of a compilation unit. However, if it is removed in one compilation unit and added in another, the value in existing instances is lost." ;
 
 ARTICLE: "tuples" "Tuples"
 "Tuples are user-defined classes composed of named slots."
@@ -132,22 +250,16 @@ $nl
 { $subsection "accessors" }
 "Initially, no specific words are defined for constructing new instances of the tuple. Constructors must be defined explicitly:"
 { $subsection "tuple-constructors" }
-"Further topics:"
-{ $subsection "tuple-delegation" }
+"Expressing relationships through the object system:"
+{ $subsection "tuple-subclassing" }
+"Introspection:"
 { $subsection "tuple-introspection" }
+"Tuple classes can be redefined; this updates existing instances:"
+{ $subsection "tuple-redefinition" }
 "Tuple literal syntax is documented in " { $link "syntax-tuples" } "." ;
 
 ABOUT: "tuples"
 
-HELP: delegate
-{ $values { "obj" object } { "delegate" object } }
-{ $description "Returns an object's delegate, or " { $link f } " if no delegate is set." }
-{ $notes "A direct consequence of this behavior is that an object may not have a delegate of " { $link f } "." } ;
-
-HELP: set-delegate
-{ $values { "delegate" object } { "tuple" tuple } }
-{ $description "Sets a tuple's delegate. Method calls not handled by the tuple's class will now be passed on to the delegate." } ;
-
 HELP: tuple=
 { $values { "tuple1" tuple } { "tuple2" tuple } { "?" "a boolean" } }
 { $description "Low-level tuple equality test. User code should use " { $link = } " instead." }
@@ -179,12 +291,12 @@ $low-level-note ;
 
 HELP: tuple-slots
 { $values { "tuple" tuple } { "seq" sequence } }
-{ $description "Pushes a sequence of tuple slot values, not including the tuple class word and delegate." } ;
+{ $description "Pushes a sequence of tuple slot values, not including the tuple class word." } ;
 
 { tuple-slots tuple>array } related-words
 
 HELP: define-tuple-slots
-{ $values { "class" tuple-class } { "slots" "a sequence of strings" } }
+{ $values { "class" tuple-class } }
 { $description "Defines slot accessor and mutator words for the tuple." }
 $low-level-note ;
 
@@ -201,26 +313,16 @@ HELP: define-tuple-class
 
 { tuple-class define-tuple-class POSTPONE: TUPLE: } related-words
 
-HELP: delegates
-{ $values { "obj" object } { "seq" sequence } }
-{ $description "Outputs the delegation chain of an object. The first element of " { $snippet "seq" } " is " { $snippet "obj" } " itself. If " { $snippet "obj" } " is " { $link f } ", an empty sequence is output." } ;
-
-HELP: is?
-{ $values { "obj" object } { "quot" "a quotation with stack effect " { $snippet "( obj -- ? )" } } { "?" "a boolean" } }
-{ $description "Tests if the object or one of its delegates satisfies the predicate quotation."
-$nl
-"Class membership test predicates only test if an object is a direct instance of that class. Sometimes, you need to check delegates, since this gives a clearer picture of what operations the object supports." } ;
-
 HELP: >tuple
 { $values { "seq" sequence } { "tuple" tuple } }
-{ $description "Creates a tuple with slot values taken from a sequence. The first element of the sequence must be a tuple class word, the second a delegate, and the remainder the declared slots."
+{ $description "Creates a tuple with slot values taken from a sequence. The first element of the sequence must be a tuple class word and the remainder the declared slots."
 $nl
 "If the sequence has too many elements, they are ignored, and if it has too few, the remaining slots in the tuple are set to " { $link f } "." }
 { $errors "Throws an error if the first element of the sequence is not a tuple class word." } ;
 
 HELP: tuple>array ( tuple -- array )
 { $values { "tuple" tuple } { "array" array } }
-{ $description "Outputs an array having the tuple's slots as elements. The first element is the tuple class word and the second is the delegate; the remainder are declared slots." } ;
+{ $description "Outputs an array having the tuple's slots as elements. The first element is the tuple class word and remainder are declared slots." } ;
 
 HELP: <tuple> ( layout -- tuple )
 { $values { "layout" tuple-layout } { "tuple" tuple } }
index a8e9066f56d3450b0d4a702aadc1714e34989745..2575570d2f2dfb11e18f438dfc3b6d1d3798dda6 100755 (executable)
@@ -16,25 +16,6 @@ TUPLE: rect x y w h ;
 
 [ t ] [ 10 20 30 40 <rect> dup clone 0 swap move = ] unit-test
 
-GENERIC: delegation-test
-M: object delegation-test drop 3 ;
-TUPLE: quux-tuple ;
-: <quux-tuple> quux-tuple construct-empty ;
-M: quux-tuple delegation-test drop 4 ;
-TUPLE: quuux-tuple ;
-: <quuux-tuple> { set-delegate } quuux-tuple construct ;
-
-[ 3 ] [ <quux-tuple> <quuux-tuple> delegation-test ] unit-test
-
-GENERIC: delegation-test-2
-TUPLE: quux-tuple-2 ;
-: <quux-tuple-2> quux-tuple-2 construct-empty ;
-M: quux-tuple-2 delegation-test-2 drop 4 ;
-TUPLE: quuux-tuple-2 ;
-: <quuux-tuple-2> { set-delegate } quuux-tuple-2 construct ;
-
-[ 4 ] [ <quux-tuple-2> <quuux-tuple-2> delegation-test-2 ] unit-test
-
 ! Make sure we handle tuple class redefinition
 TUPLE: redefinition-test ;
 
@@ -102,11 +83,6 @@ C: <empty> empty
 
 [ t ] [ <empty> hashcode fixnum? ] unit-test
 
-TUPLE: delegate-clone ;
-
-[ T{ delegate-clone T{ empty f } } ]
-[ T{ delegate-clone T{ empty f } } clone ] unit-test
-
 ! Compiler regression
 [ t length ] [ object>> t eq? ] must-fail-with
 
@@ -242,7 +218,7 @@ C: <erg's-reshape-problem> erg's-reshape-problem
 
 [
     "IN: classes.tuple.tests SYMBOL: not-a-class C: <not-a-class> not-a-class" eval
-] [ [ no-tuple-class? ] is? ] must-fail-with
+] [ error>> no-tuple-class? ] must-fail-with
 
 ! Inheritance
 TUPLE: computer cpu ram ;
@@ -512,7 +488,7 @@ USE: vocabs
     ] with-compilation-unit
 ] unit-test
 
-[ "USE: words T{ word }" eval ] [ [ no-method? ] is? ] must-fail-with
+[ "USE: words T{ word }" eval ] [ error>> no-method? ] must-fail-with
 
 ! Accessors not being forgotten...
 [ [ ] ] [
@@ -553,3 +529,12 @@ TUPLE: another-forget-accessors-test ;
 ] unit-test
 
 [ t ] [ \ another-forget-accessors-test class? ] unit-test
+
+! Shadowing test
+[ f ] [
+    t parser-notes? [
+        [
+            "IN: classes.tuple.tests TUPLE: shadow-1 a b ; TUPLE: shadow-2 < shadow-1 a b ;" eval
+        ] with-string-writer empty?
+    ] with-variable
+] unit-test
index b1cb3f8a66de2c09401911edeb53c0bac709a5ab..aa8ef6cdb7051ef6cee63012278dee56f2a58e6f 100755 (executable)
@@ -7,10 +7,6 @@ classes classes.private slots.deprecated slots.private slots
 compiler.units math.private accessors assocs ;
 IN: classes.tuple
 
-M: tuple delegate 2 slot ;
-
-M: tuple set-delegate 2 set-slot ;
-
 M: tuple class 1 slot 2 slot { word } declare ;
 
 ERROR: no-tuple-class class ;
@@ -44,7 +40,7 @@ PRIVATE>
     >r copy-tuple-slots r>
     layout-class prefix ;
 
-: tuple-slots ( tuple -- array )
+: tuple-slots ( tuple -- seq )
     prepare-tuple>array drop copy-tuple-slots ;
 
 : slots>tuple ( tuple class -- array )
@@ -52,11 +48,15 @@ PRIVATE>
         [ tuple-size ] [ [ set-array-nth ] curry ] bi 2each
     ] keep ;
 
-: >tuple ( tuple -- array )
+: >tuple ( tuple -- seq )
     unclip slots>tuple ;
 
 : slot-names ( class -- seq )
-    "slot-names" word-prop ;
+    "slot-names" word-prop
+    [ dup array? [ second ] when ] map ;
+
+: all-slot-names ( class -- slots )
+    superclasses [ slot-names ] map concat \ class prefix ;
 
 <PRIVATE
 
@@ -107,7 +107,7 @@ PRIVATE>
     over superclass-size 2 + simple-slots ;
 
 : define-tuple-slots ( class -- )
-    dup dup slot-names generate-tuple-slots
+    dup dup "slot-names" word-prop generate-tuple-slots
     [ "slots" set-word-prop ]
     [ define-accessors ] ! new
     [ define-slots ] ! old
@@ -122,9 +122,6 @@ PRIVATE>
 : define-tuple-layout ( class -- )
     dup make-tuple-layout "layout" set-word-prop ;
 
-: all-slot-names ( class -- slots )
-    superclasses [ slot-names ] map concat \ class prefix ;
-
 : compute-slot-permutation ( class old-slot-names -- permutation )
     >r all-slot-names r> [ index ] curry map ;
 
@@ -177,7 +174,7 @@ M: tuple-class update-class
         2drop
         [
             [ update-tuples-after ]
-            [ changed-word ]
+            [ changed-definition ]
             [ redefined ]
             tri
         ] each-subclass
@@ -228,9 +225,10 @@ M: tuple equal?
 
 M: tuple hashcode*
     [
-        dup tuple-size -rot 0 -rot [
-            swapd array-nth hashcode* bitxor
-        ] 2curry reduce
+        [ class hashcode ] [ tuple-size ] [ ] tri
+        >r rot r> [
+            swapd array-nth hashcode* sequence-hashcode-step
+        ] 2curry each
     ] recursive-hashcode ;
 
 ! Deprecated
index 237f32c3e0c591bfa9e70fd55660399d50d0fde4..91726b669741d327a365f6f05d952ae1eddb9260 100755 (executable)
@@ -11,7 +11,9 @@ ARTICLE: "unions" "Union classes"
 { $subsection members }
 "The set of union classes is a class:"
 { $subsection union-class }
-{ $subsection union-class? } ;
+{ $subsection union-class? } 
+"Unions are used to define behavior shared between a fixed set of classes."
+{ $see-also "mixins" "tuple-subclassing" } ;
 
 ABOUT: "unions"
 
index f497fd20e52812fa1b6b4472a24159c109bb3db5..54c62c44fa83f16579d7657806c4e3ad6edd2530 100755 (executable)
@@ -64,9 +64,9 @@ HELP: alist>quot
 { $notes "This word is used to implement compile-time behavior for " { $link cond } ", and it is also used by the generic word system. Note that unlike " { $link cond } ", the constructed quotation performs the tests starting from the end and not the beginning." } ;
 
 HELP: cond
-{ $values { "assoc" "a sequence of quotation pairs" } }
+{ $values { "assoc" "a sequence of quotation pairs and an optional quotation" } }
 { $description
-    "Calls the second quotation in the first pair whose first quotation yields a true value."
+    "Calls the second quotation in the first pair whose first quotation yields a true value. A single quotation will always yield a true value."
     $nl
     "The following two phrases are equivalent:"
     { $code "{ { [ X ] [ Y ] } { [ Z ] [ T ] } } cond" }
@@ -78,7 +78,7 @@ HELP: cond
         "{"
         "    { [ dup 0 > ] [ \"positive\" ] }"
         "    { [ dup 0 < ] [ \"negative\" ] }"
-        "    { [ dup zero? ] [ \"zero\" ] }"
+        "    [ \"zero\" ]"
         "} cond"
     }
 } ;
@@ -88,9 +88,9 @@ HELP: no-cond
 { $error-description "Thrown by " { $link cond } " if none of the test quotations yield a true value. Some uses of " { $link cond } " include a default case where the test quotation is " { $snippet "[ t ]" } "; such a " { $link cond } " form will never throw this error." } ;
 
 HELP: case
-{ $values { "obj" object } { "assoc" "a sequence of object/quotation pairs, with an optional quotation at the end" } }
+{ $values { "obj" object } { "assoc" "a sequence of object/word,quotation pairs, with an optional quotation at the end" } }
 { $description
-    "Compares " { $snippet "obj" } " against the first element of every pair. If some pair matches, removes " { $snippet "obj" } " from the stack and calls the second element of that pair, which must be a quotation."
+    "Compares " { $snippet "obj" } " against the first element of every pair, first evaluating the first element if it is a word. If some pair matches, removes " { $snippet "obj" } " from the stack and calls the second element of that pair, which must be a quotation."
     $nl
     "If there is no case matching " { $snippet "obj" } ", the default case is taken. If the last element of " { $snippet "cases" } " is a quotation, the quotation is called with " { $snippet "obj" } " on the stack. Otherwise, a " { $link no-cond } " error is rasied."
     $nl
index 8abc53e43fc850f1441ca89372cbb58dcad68942..b612669b717dbb3cffd52b35b17bbf8726d28d8f 100755 (executable)
@@ -1,7 +1,54 @@
-IN: combinators.tests
 USING: alien strings kernel math tools.test io prettyprint
-namespaces combinators words ;
+namespaces combinators words classes sequences ;
+IN: combinators.tests
+
+! Compiled
+: cond-test-1 ( obj -- str )
+    {
+        { [ dup 2 mod 0 = ] [ drop "even" ] }
+        { [ dup 2 mod 1 = ] [ drop "odd" ] }
+    } cond ;
+
+\ cond-test-1 must-infer
+
+[ "even" ] [ 2 cond-test-1 ] unit-test
+[ "odd" ] [ 3 cond-test-1 ] unit-test
+
+: cond-test-2 ( obj -- str )
+    {
+        { [ dup t = ] [ drop "true" ] }
+        { [ dup f = ] [ drop "false" ] }
+        [ drop "something else" ]
+    } cond ;
+
+\ cond-test-2 must-infer
+
+[ "true" ] [ t cond-test-2 ] unit-test
+[ "false" ] [ f cond-test-2 ] unit-test
+[ "something else" ] [ "ohio" cond-test-2 ] unit-test
+
+: cond-test-3 ( obj -- str )
+    {
+        [ drop "something else" ]
+        { [ dup t = ] [ drop "true" ] }
+        { [ dup f = ] [ drop "false" ] }
+    } cond ;
+
+\ cond-test-3 must-infer
+
+[ "something else" ] [ t cond-test-3 ] unit-test
+[ "something else" ] [ f cond-test-3 ] unit-test
+[ "something else" ] [ "ohio" cond-test-3 ] unit-test
+
+: cond-test-4 ( -- )
+    {
+    } cond ;
+
+\ cond-test-4 must-infer
+
+[ cond-test-4 ] [ class \ no-cond = ] must-fail-with
 
+! Interpreted
 [ "even" ] [
     2 {
         { [ dup 2 mod 0 = ] [ drop "even" ] }
@@ -21,11 +68,66 @@ namespaces combinators words ;
         { [ dup string? ] [ drop "string" ] }
         { [ dup float? ] [ drop "float" ] }
         { [ dup alien? ] [ drop "alien" ] }
-        { [ t ] [ drop "neither" ] }
+        [ drop "neither" ]
+    } cond
+] unit-test
+
+[ "neither" ] [
+    3 {
+        { [ dup string? ] [ drop "string" ] }
+        { [ dup float? ] [ drop "float" ] }
+        { [ dup alien? ] [ drop "alien" ] }
+        [ drop "neither" ]
+    } cond
+] unit-test
+
+[ "neither" ] [
+    3 {
+        { [ dup string? ] [ drop "string" ] }
+        { [ dup float? ] [ drop "float" ] }
+        { [ dup alien? ] [ drop "alien" ] }
+        [ drop "neither" ]
+    } cond
+] unit-test
+
+[ "early" ] [
+    2 {
+        { [ dup 2 mod 1 = ] [ drop "odd" ] }
+        [ drop "early" ]
+        { [ dup 2 mod 0 = ] [ drop "even" ] }
     } cond
 ] unit-test
 
-: case-test-1
+[ "really early" ] [
+    2 {
+       [ drop "really early" ]
+        { [ dup 2 mod 1 = ] [ drop "odd" ] }
+        { [ dup 2 mod 0 = ] [ drop "even" ] }
+    } cond
+] unit-test
+
+[ { } cond ] [ class \ no-cond = ] must-fail-with
+[ "early" ] [
+    2 {
+        { [ dup 2 mod 1 = ] [ drop "odd" ] }
+        [ drop "early" ]
+        { [ dup 2 mod 0 = ] [ drop "even" ] }
+    } cond
+] unit-test
+
+[ "really early" ] [
+    2 {
+        [ drop "really early" ]
+        { [ dup 2 mod 1 = ] [ drop "odd" ] }
+        { [ dup 2 mod 0 = ] [ drop "even" ] }
+    } cond
+] unit-test
+
+[ { } cond ] [ class \ no-cond = ] must-fail-with
+
+! Compiled
+: case-test-1 ( obj -- obj' )
     {
         { 1 [ "one" ] }
         { 2 [ "two" ] }
@@ -33,6 +135,8 @@ namespaces combinators words ;
         { 4 [ "four" ] }
     } case ;
 
+\ case-test-1 must-infer
+
 [ "two" ] [ 2 case-test-1 ] unit-test
 
 ! Interpreted
@@ -40,7 +144,7 @@ namespaces combinators words ;
 
 [ "x" case-test-1 ] must-fail
 
-: case-test-2
+: case-test-2 ( obj -- obj' )
     {
         { 1 [ "one" ] }
         { 2 [ "two" ] }
@@ -49,12 +153,14 @@ namespaces combinators words ;
         [ sq ]
     } case ;
 
+\ case-test-2 must-infer
+
 [ 25 ] [ 5 case-test-2 ] unit-test
 
 ! Interpreted
 [ 25 ] [ 5 \ case-test-2 word-def call ] unit-test
 
-: case-test-3
+: case-test-3 ( obj -- obj' )
     {
         { 1 [ "one" ] }
         { 2 [ "two" ] }
@@ -65,8 +171,122 @@ namespaces combinators words ;
         [ sq ]
     } case ;
 
+\ case-test-3 must-infer
+
 [ "an array" ] [ { 1 2 3 } case-test-3 ] unit-test
 
+: case-const-1 1 ;
+: case-const-2 2 ; inline
+
+! Compiled
+: case-test-4 ( obj -- str )
+    {
+        { case-const-1 [ "uno" ] }
+        { case-const-2 [ "dos" ] }
+        { 3 [ "tres" ] } 
+        { 4 [ "cuatro" ] } 
+        { 5 [ "cinco" ] } 
+        [ drop "demasiado" ]
+    } case ;
+
+\ case-test-4 must-infer
+
+[ "uno" ] [ 1 case-test-4 ] unit-test
+[ "dos" ] [ 2 case-test-4 ] unit-test
+[ "tres" ] [ 3 case-test-4 ] unit-test
+[ "demasiado" ] [ 100 case-test-4 ] unit-test
+
+: case-test-5 ( obj -- )
+    {
+        { case-const-1 [ "uno" print ] }
+        { case-const-2 [ "dos" print ] }
+        { 3 [ "tres" print ] } 
+        { 4 [ "cuatro" print ] } 
+        { 5 [ "cinco" print ] } 
+        [ drop "demasiado" print ]
+    } case ;
+
+\ case-test-5 must-infer
+
+[ ] [ 1 case-test-5 ] unit-test
+
+! Interpreted
+[ "uno" ] [
+    1 {
+        { case-const-1 [ "uno" ] }
+        { case-const-2 [ "dos" ] }
+        { 3 [ "tres" ] } 
+        { 4 [ "cuatro" ] } 
+        { 5 [ "cinco" ] } 
+        [ drop "demasiado" ]
+    } case
+] unit-test
+
+[ "dos" ] [
+    2 {
+        { case-const-1 [ "uno" ] }
+        { case-const-2 [ "dos" ] }
+        { 3 [ "tres" ] } 
+        { 4 [ "cuatro" ] } 
+        { 5 [ "cinco" ] } 
+        [ drop "demasiado" ]
+    } case
+] unit-test
+
+[ "tres" ] [
+    3 {
+        { case-const-1 [ "uno" ] }
+        { case-const-2 [ "dos" ] }
+        { 3 [ "tres" ] } 
+        { 4 [ "cuatro" ] } 
+        { 5 [ "cinco" ] } 
+        [ drop "demasiado" ]
+    } case
+] unit-test
+
+[ "demasiado" ] [
+    100 {
+        { case-const-1 [ "uno" ] }
+        { case-const-2 [ "dos" ] }
+        { 3 [ "tres" ] } 
+        { 4 [ "cuatro" ] } 
+        { 5 [ "cinco" ] } 
+        [ drop "demasiado" ]
+    } case
+] unit-test
+
+: do-not-call "do not call" throw ;
+
+: test-case-6
+    {
+        { \ do-not-call [ "do-not-call" ] }
+        { 3 [ "three" ] }
+    } case ;
+
+[ "three" ] [ 3 test-case-6 ] unit-test
+[ "do-not-call" ] [ \ do-not-call test-case-6 ] unit-test
+
+[ "three" ] [
+    3 {
+        { \ do-not-call [ "do-not-call" ] }
+        { 3 [ "three" ] }
+    } case
+] unit-test
+
+[ "do-not-call" ] [
+    [ do-not-call ] first {
+        { \ do-not-call [ "do-not-call" ] }
+        { 3 [ "three" ] }
+    } case
+] unit-test
+
+[ "do-not-call" ] [
+    \ do-not-call {
+        { \ do-not-call [ "do-not-call" ] }
+        { 3 [ "three" ] }
+    } case
+] unit-test
+
 ! Interpreted
 [ "a hashtable" ] [ H{ } \ case-test-3 word-def call ] unit-test
 
index 139c6d8fdf294c96701ccbab406504f23f0f5282..11ad8d60e7f6f9ee8199ca735783f39afa7412eb 100755 (executable)
@@ -3,7 +3,7 @@
 IN: combinators
 USING: arrays sequences sequences.private math.private
 kernel kernel.private math assocs quotations vectors
-hashtables sorting ;
+hashtables sorting words ;
 
 : cleave ( x seq -- )
     [ call ] with each ;
@@ -34,13 +34,24 @@ hashtables sorting ;
 ERROR: no-cond ;
 
 : cond ( assoc -- )
-    [ first call ] find nip dup [ second call ] [ no-cond ] if ;
+    [ dup callable? [ drop t ] [ first call ] if ] find nip
+    [ dup callable? [ call ] [ second call ] if ]
+    [ no-cond ] if* ;
 
 ERROR: no-case ;
+: case-find ( obj assoc -- obj' )
+    [
+        dup array? [
+            dupd first dup word? [
+                execute
+            ] [
+                dup wrapper? [ wrapped ] when
+            ] if =
+        ] [ quotation? ] if
+    ] find nip ;
 
 : case ( obj assoc -- )
-    [ dup array? [ dupd first = ] [ quotation? ] if ] find nip
-    {
+    case-find {
         { [ dup array? ] [ nip second call ] }
         { [ dup quotation? ] [ call ] }
         { [ dup not ] [ no-case ] }
@@ -59,6 +70,10 @@ ERROR: no-case ;
 M: sequence hashcode*
     [ sequence-hashcode ] recursive-hashcode ;
 
+M: reversed hashcode* [ sequence-hashcode ] recursive-hashcode ;
+
+M: slice hashcode* [ sequence-hashcode ] recursive-hashcode ;
+
 M: hashtable hashcode*
     [
         dup assoc-size 1 number=
@@ -69,11 +84,14 @@ M: hashtable hashcode*
     [ rot \ if 3array append [ ] like ] assoc-each ;
 
 : cond>quot ( assoc -- quot )
+    [ dup callable? [ [ t ] swap 2array ] when ] map
     reverse [ no-cond ] swap alist>quot ;
 
 : linear-case-quot ( default assoc -- quot )
-    [ >r [ dupd = ] curry r> \ drop prefix ] assoc-map
-    alist>quot ;
+    [
+        [ 1quotation \ dup prefix \ = suffix ]
+        [ \ drop prefix ] bi*
+    ] assoc-map alist>quot ;
 
 : (distribute-buckets) ( buckets pair keys -- )
     dup t eq? [
@@ -131,7 +149,9 @@ M: hashtable hashcode*
     dup empty? [
         drop
     ] [
-        dup length 4 <= [
+        dup length 4 <=
+        over keys [ word? ] contains? or
+        [
             linear-case-quot
         ] [
             dup keys contiguous-range? [
index a0599f79a17d8eeb7ca3c09bfb069e2a4496d38e..6f75ca873d56c010ca36a6f1690b3e0f87a1a980 100755 (executable)
@@ -1,10 +1,10 @@
 ! Copyright (C) 2004, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel namespaces arrays sequences io inference.backend
-inference.state generator debugger math.parser prettyprint words
-compiler.units continuations vocabs assocs alien.compiler dlists
-optimizer definitions math compiler.errors threads graphs
-generic inference ;
+inference.state generator debugger words compiler.units
+continuations vocabs assocs alien.compiler dlists optimizer
+definitions math compiler.errors threads graphs generic
+inference ;
 IN: compiler
 
 : ripple-up ( word -- )
index 0d457a83102ed1c41780017d70a97eed73a5d68f..81ab750305f9527b891f212ec3921fac75b57f77 100755 (executable)
@@ -2,7 +2,7 @@ IN: compiler.tests
 USING: compiler.units kernel kernel.private memory math
 math.private tools.test math.floats.private ;
 
-[ 5.0 ] [ [ 5.0 ] compile-call data-gc data-gc data-gc ] unit-test
+[ 5.0 ] [ [ 5.0 ] compile-call gc gc gc ] unit-test
 [ 2.0 3.0 ] [ 3.0 [ 2.0 swap ] compile-call ] unit-test
 
 [ 1 2 3 4.0 ] [ [ 1 2 3 4.0 ] compile-call ] unit-test
index 13b7de698757b2beaa7bf691cd7cb458bdebeeda..dce2ec562a2dd25cc60c31cd2c2b262e7f71d212 100755 (executable)
@@ -48,7 +48,7 @@ IN: compiler.tests
 [ 4 1 3 ] [ 0 [ { [ bar 1 ] [ 3 1 ] } dispatch 3 ] compile-call ] unit-test
 [ 3 1 3 ] [ 1 [ { [ bar 1 ] [ 3 1 ] } dispatch 3 ] compile-call ] unit-test
 
-[ 2 3 ] [ 1 [ { [ code-gc 1 ] [ code-gc 2 ] } dispatch 3 ] compile-call ] unit-test
+[ 2 3 ] [ 1 [ { [ gc 1 ] [ gc 2 ] } dispatch 3 ] compile-call ] unit-test
 
 ! Labels
 
@@ -187,7 +187,7 @@ DEFER: countdown-b
             { [ dup string? ] [ drop "string" ] }
             { [ dup float? ] [ drop "float" ] }
             { [ dup alien? ] [ drop "alien" ] }
-            { [ t ] [ drop "neither" ] }
+            [ drop "neither" ]
         } cond
     ] compile-call
 ] unit-test
@@ -196,7 +196,7 @@ DEFER: countdown-b
     [
         3 {
             { [ dup fixnum? ] [ ] }
-            { [ t ] [ drop t ] }
+            [ drop t ]
         } cond
     ] compile-call
 ] unit-test
index bdbc98507825dbf439b5708b4d3050743c88f927..004d08834324aa79c0aa1ca96d159294cfc30020 100755 (executable)
@@ -2,9 +2,9 @@
 IN: compiler.tests
 USING: compiler generator generator.registers
 generator.registers.private tools.test namespaces sequences
-words kernel math effects definitions compiler.units ;
+words kernel math effects definitions compiler.units accessors ;
 
-: <int-vreg> ( n -- vreg ) T{ int-regs } <vreg> ;
+: <int-vreg> ( n -- vreg ) int-regs <vreg> ;
 
 [
     [ ] [ init-templates ] unit-test
@@ -15,18 +15,18 @@ words kernel math effects definitions compiler.units ;
     
     [ ] [ compute-free-vregs ] unit-test
     
-    [ f ] [ 0 <int-vreg> T{ int-regs } free-vregs member? ] unit-test
+    [ f ] [ 0 <int-vreg> int-regs free-vregs member? ] unit-test
     
     [ f ] [
         [
             copy-templates
             1 <int-vreg> phantom-push
             compute-free-vregs
-            1 <int-vreg> T{ int-regs } free-vregs member?
+            1 <int-vreg> int-regs free-vregs member?
         ] with-scope
     ] unit-test
     
-    [ t ] [ 1 <int-vreg> T{ int-regs } free-vregs member? ] unit-test
+    [ t ] [ 1 <int-vreg> int-regs free-vregs member? ] unit-test
 ] with-scope
 
 [
@@ -173,12 +173,12 @@ SYMBOL: template-chosen
     ] unit-test
 
     [ ] [
-        2 phantom-d get phantom-input
+        2 phantom-datastack get phantom-input
         [ { { f "a" } { f "b" } } lazy-load ] { } make drop
     ] unit-test
     
     [ t ] [
-        phantom-d get [ cached? ] all?
+        phantom-datastack get stack>> [ cached? ] all?
     ] unit-test
 
     ! >r
index 565c045e2a74c0ce50bfd4048cde87e3862c398f..845189ce2c589d284cb802280ae5f60f13800c04 100755 (executable)
@@ -202,3 +202,47 @@ TUPLE: my-tuple ;
         ] [ 2drop no-case ] if
     ] compile-call
 ] unit-test
+
+: float-spill-bug
+    {
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+        [ dup float+ ]
+    } cleave ;
+
+[ t ] [ \ float-spill-bug compiled? ] unit-test
index 5843575eeb71570a4e52f44ed8c84d7e7317288d..97cde6261cd87ecedcde5569a6e1123bdc3618de 100755 (executable)
@@ -22,11 +22,3 @@ TUPLE: color red green blue ;
 
 [ T{ color f f f f } ]
 [ [ color construct-empty ] compile-call ] unit-test
-
-[ T{ color "a" f "b" f } ] [
-    "a" "b"
-    [ { set-delegate set-color-green } color construct ]
-    compile-call
-] unit-test
-
-[ T{ color f f f f } ] [ [ { } color construct ] compile-call ] unit-test
index f87c1ec985ba1b8616bd1234e25297a593ff456d..a780e0a745963a1257b6a5e45f02a386898aebb5 100755 (executable)
@@ -56,12 +56,12 @@ GENERIC: definitions-changed ( assoc obj -- )
     [ drop word? ] assoc-subset
     [ drop word-vocabulary dup [ vocab ] when dup ] assoc-map ;
 
-: changed-definitions ( -- assoc )
+: updated-definitions ( -- assoc )
     H{ } clone
     dup forgotten-definitions get update
     dup new-definitions get first update
     dup new-definitions get second update
-    dup changed-words get update
+    dup changed-definitions get update
     dup dup changed-vocabs update ;
 
 : compile ( words -- )
@@ -73,7 +73,7 @@ SYMBOL: outdated-tuples
 SYMBOL: update-tuples-hook
 
 : call-recompile-hook ( -- )
-    changed-words get keys
+    changed-definitions get keys [ word? ] subset
     compiled-usages recompile-hook get call ;
 
 : call-update-tuples-hook ( -- )
@@ -83,11 +83,11 @@ SYMBOL: update-tuples-hook
     call-recompile-hook
     call-update-tuples-hook
     dup [ drop crossref? ] assoc-contains? modify-code-heap
-    changed-definitions notify-definition-observers ;
+    updated-definitions notify-definition-observers ;
 
 : with-compilation-unit ( quot -- )
     [
-        H{ } clone changed-words set
+        H{ } clone changed-definitions set
         H{ } clone forgotten-definitions set
         H{ } clone outdated-tuples set
         <definitions> new-definitions set
index ca7af930f2e62eed61e659178b057fec7dee5bdb..b1db09b6bcf28e4059c8a9112468383b9ae29f9c 100755 (executable)
@@ -1,6 +1,6 @@
 USING: help.markup help.syntax kernel kernel.private
 continuations.private parser vectors arrays namespaces
-assocs words quotations ;
+assocs words quotations io ;
 IN: continuations
 
 ARTICLE: "errors-restartable" "Restartable errors"
@@ -17,6 +17,25 @@ ARTICLE: "errors-post-mortem" "Post-mortem error inspection"
 { $subsection error-continuation }
 "Developer tools for inspecting these values are found in " { $link "debugger" } "." ;
 
+ARTICLE: "errors-anti-examples" "Common error handling pitfalls"
+"When used correctly, exception handling can lead to more robust code with less duplication of error handling logic. However, there are some pitfalls to keep in mind."
+{ $heading "Anti-pattern #1: Ignoring errors" }
+"The " { $link ignore-errors } " word should almost never be used. Ignoring errors does not make code more robust and in fact makes it much harder to debug if an intermittent error does show up when the code is run under previously unforseen circumstances. Never ignore unexpected errors; always report them to the user."
+{ $heading "Anti-pattern #2: Catching errors too early" }
+"A less severe form of the previous anti-pattern is code that makes overly zealous use of " { $link recover } ". It is almost always a mistake to catch an error, log a message, and keep going. The only exception is network servers and other long-running processes that must remain running even if individual tasks fail. In these cases, place the " { $link recover } " as high up in the call stack as possible."
+$nl
+"In most other cases, " { $link cleanup } " should be used instead to handle an error and rethrow it automatically."
+{ $heading "Anti-pattern #3: Dropping and rethrowing" }
+"Do not use " { $link recover } " to handle an error by dropping it and throwing a new error. By losing the original error message, you signal to the user that something failed without leaving any indication of what actually went wrong. Either wrap the error in a new error containing additional information, or rethrow the original error. A more subtle form of this is using  " { $link throw } " instead of " { $link rethrow } ". The " { $link throw } " word should only be used when throwing new errors, and never when rethrowing errors that have been caught."
+{ $heading "Anti-pattern #4: Logging and rethrowing" }
+"If you are going to rethrow an error, do not log a message. If you do so, the user will see two log messages for the same error, which will clutter logs without adding any useful information."
+{ $heading "Anti-pattern #5: Leaking external resources" }
+"Words which create objects corresponding to external resources should always be used with " { $link with-disposal } ". The following code is wrong:"
+{ $code
+    "<external-resource> ... do stuff ... dispose"
+}
+"The reason being that if " { $snippet "do stuff" } " throws an error, the resource will not be disposed of. The most important case where this can occur is with I/O streams, and the correct solution is to always use " { $link with-stream } "; see " { $link "stdio" } " for details." ;
+
 ARTICLE: "errors" "Error handling"
 "Support for handling exceptional situations such as bad user input, implementation bugs, and input/output errors is provided by a set of words built using continuations."
 $nl
@@ -27,10 +46,13 @@ $nl
 { $subsection cleanup }
 { $subsection recover }
 { $subsection ignore-errors }
+"Syntax sugar for defining errors:"
+{ $subsection POSTPONE: ERROR: }
 "Unhandled errors are reported in the listener and can be debugged using various tools. See " { $link "debugger" } "."
 { $subsection "errors-restartable" }
 { $subsection "debugger" }
 { $subsection "errors-post-mortem" }
+{ $subsection "errors-anti-examples" }
 "When Factor encouters a critical error, it calls the following word:"
 { $subsection die } ;
 
@@ -61,15 +83,18 @@ $nl
 "Another two words resume continuations:"
 { $subsection continue }
 { $subsection continue-with }
-"Continuations serve as the building block for a number of higher-level abstractions."
-{ $subsection "errors" }
+"Continuations serve as the building block for a number of higher-level abstractions, such as " { $link "errors" } " and " { $link "threads" } "."
 { $subsection "continuations.private" } ;
 
 ABOUT: "continuations"
 
 HELP: dispose
 { $values { "object" "a disposable object" } }
-{ $contract "Releases operating system resources associated with a disposable object. No further operations can be performed on a disposable object after this call. Disposable objects include streams, memory mapped files, and so on." }
+{ $contract "Releases operating system resources associated with a disposable object. Disposable objects include streams, memory mapped files, and so on."
+$nl
+"No further operations can be performed on a disposable object after this call."
+$nl
+"Disposing an object which has already been disposed should have no effect, and in particular it should not fail with an error." }
 { $notes "You must close disposable objects after you are finished working with them, to avoid leaking operating system resources. A convenient way to automate this is by using the " { $link with-disposal } " word." } ;
 
 HELP: with-disposal
index d5ede6008674ce9c1531b58ff1ee5077efd2923e..8b396763e108e71839d93d2c905ce938f9dab52b 100755 (executable)
@@ -46,8 +46,8 @@ IN: continuations.tests
 ! Weird PowerPC bug.
 [ ] [
     [ "4" throw ] ignore-errors
-    data-gc
-    data-gc
+    gc
+    gc
 ] unit-test
 
 [ f ] [ { } kernel-error? ] unit-test
index a2c296e8cea456dd10cd21ab94c49dd4d48bc29d..cf67280ccaa63620a5713c0d41616adfda701af4 100755 (executable)
@@ -141,14 +141,9 @@ GENERIC: dispose ( object -- )
 : with-disposal ( object quot -- )
     over [ dispose ] curry [ ] cleanup ; inline
 
-TUPLE: condition restarts continuation ;
+TUPLE: condition error restarts continuation ;
 
-: <condition> ( error restarts cc -- condition )
-    {
-        set-delegate
-        set-condition-restarts
-        set-condition-continuation
-    } condition construct ;
+C: <condition> condition ( error restarts cc -- condition )
 
 : throw-restarts ( error restarts -- restart )
     [ <condition> throw ] callcc1 2nip ;
@@ -161,15 +156,14 @@ TUPLE: restart name obj continuation ;
 C: <restart> restart
 
 : restart ( restart -- )
-    dup restart-obj swap restart-continuation continue-with ;
+    [ obj>> ] [ continuation>> ] bi continue-with ;
 
 M: object compute-restarts drop { } ;
 
-M: tuple compute-restarts delegate compute-restarts ;
-
 M: condition compute-restarts
-    [ delegate compute-restarts ] keep
-    [ condition-restarts ] keep
-    condition-continuation
-    [ <restart> ] curry { } assoc>map
-    append ;
+    [ error>> compute-restarts ]
+    [
+        [ restarts>> ]
+        [ condition-continuation [ <restart> ] curry ] bi
+        { } assoc>map
+    ] bi append ;
index 4670cf86d2632b6a8905422c217a0bac928159c7..7ea8849d3073ff392c44cb9371ba3df368122b70 100755 (executable)
@@ -6,7 +6,7 @@ byte-arrays bit-arrays float-arrays combinators words ;
 IN: cpu.architecture
 
 ! A pseudo-register class for parameters spilled on the stack
-TUPLE: stack-params ;
+SINGLETON: stack-params
 
 ! Return values of this class go here
 GENERIC: return-reg ( register-class -- reg )
index a1a4bd380925e46b6a3636b227d302de1be3c1a5..09ffead0298782004e7c67fa46bc70f22825ea7a 100755 (executable)
@@ -146,11 +146,19 @@ M: int-regs %save-param-reg drop 1 rot local@ STW ;
 
 M: int-regs %load-param-reg drop 1 rot local@ LWZ ;
 
-: STF float-regs-size 4 = [ STFS ] [ STFD ] if ;
+GENERIC: STF ( src dst off reg-class -- )
+
+M: single-float-regs STF drop STFS ;
+
+M: double-float-regs STF drop STFD ;
 
 M: float-regs %save-param-reg >r 1 rot local@ r> STF ;
 
-: LF float-regs-size 4 = [ LFS ] [ LFD ] if ;
+GENERIC: LF ( dst src off reg-class -- )
+
+M: single-float-regs LF drop LFS ;
+
+M: double-float-regs LF drop LFD ;
 
 M: float-regs %load-param-reg >r 1 rot local@ r> LF ;
 
index 4d447b38fcd939bf32093a0992062e0b7446e505..cc3fceff230ba2601c946b1cbc9d1a9526bdc740 100755 (executable)
@@ -155,7 +155,7 @@ M: x86.32 %box ( n reg-class func -- )
     #! integer, push [ESP+n]:[ESP+n+4] on the stack; we are
     #! boxing a parameter being passed to a callback from C.
     [
-        T{ int-regs } box@
+        int-regs box@
         EDX over stack@ MOV
         EAX swap cell - stack@ MOV 
     ] when*
@@ -246,9 +246,8 @@ M: x86.32 %cleanup ( alien-node -- )
         } {
             [ dup return>> large-struct? ]
             [ drop EAX PUSH ]
-        } {
-            [ t ] [ drop ]
         }
+        [ drop ]
     } cond ;
 
 M: x86.32 %unwind ( n -- ) %epilogue-later RET ;
index d3ccffe00e386df537aeabf128eed384e486a1e4..811387675a5c6e74e7fa37162f5c18e5ac035ac3 100755 (executable)
@@ -65,7 +65,7 @@ M: x86.64 %unbox ( n reg-class func -- )
     over [ [ return-reg ] keep %save-param-reg ] [ 2drop ] if ;
 
 M: x86.64 %unbox-long-long ( n func -- )
-    T{ int-regs } swap %unbox ;
+    int-regs swap %unbox ;
 
 M: x86.64 %unbox-struct-1 ( -- )
     #! Alien must be in RDI.
@@ -103,7 +103,7 @@ M: x86.64 %box ( n reg-class func -- )
     f %alien-invoke ;
 
 M: x86.64 %box-long-long ( n func -- )
-    T{ int-regs } swap %box ;
+    int-regs swap %box ;
 
 M: x86.64 struct-small-enough? ( size -- ? ) 2 cells <= ;
 
@@ -170,7 +170,7 @@ USE: cpu.x86.intrinsics
 
 ! The ABI for passing structs by value is pretty messed up
 << "void*" c-type clone "__stack_value" define-primitive-type
-T{ stack-params } "__stack_value" c-type set-c-type-reg-class >>
+stack-params "__stack_value" c-type set-c-type-reg-class >>
 
 : struct-types&offset ( struct-type -- pairs )
     struct-type-fields [
@@ -192,7 +192,7 @@ M: struct-type flatten-value-type ( type -- seq )
     ] [
         struct-types&offset split-struct [
             [ c-type c-type-reg-class ] map
-            T{ int-regs } swap member?
+            int-regs swap member?
             "void*" "double" ? c-type ,
         ] each
     ] if ;
index 6c9a4dc05fe490ef1441227de455e957150b3887..25bb3c6e078b4ade65cba05830bc08e43a2ba347 100755 (executable)
@@ -1,4 +1,4 @@
-! Copyright (C) 2005, 2007 Slava Pestov.
+! Copyright (C) 2005, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien alien.c-types alien.compiler arrays
 cpu.x86.assembler cpu.architecture kernel kernel.private math
@@ -22,7 +22,11 @@ M: rs-loc v>operand rs-loc-n rs-reg reg-stack ;
 M: int-regs %save-param-reg drop >r stack@ r> MOV ;
 M: int-regs %load-param-reg drop swap stack@ MOV ;
 
-: MOVSS/D float-regs-size 4 = [ MOVSS ] [ MOVSD ] if ;
+GENERIC: MOVSS/D ( dst src reg-class -- )
+
+M: single-float-regs MOVSS/D drop MOVSS ;
+
+M: double-float-regs MOVSS/D drop MOVSD ;
 
 M: float-regs %save-param-reg >r >r stack@ r> r> MOVSS/D ;
 M: float-regs %load-param-reg >r swap stack@ r> MOVSS/D ;
index a3ab256ea1936b198a00968d9894e7cc1dd0d9f5..450aa8f9800c79d8a685e9eb1021f68f8ffed405 100755 (executable)
@@ -189,7 +189,7 @@ UNION: operand register indirect ;
     {
         { [ dup register-128? ] [ drop operand-64? ] }
         { [ dup not ] [ drop operand-64? ] }
-        { [ t ] [ nip operand-64? ] }
+        [ nip operand-64? ]
     } cond and ;
 
 : rex.r
index 033ae0680ca4bbd3281874e26c1a6c3ed4f7bebc..dea1904e921d5f00665313c5bdf2c07064373942 100755 (executable)
@@ -4,9 +4,9 @@ USING: arrays definitions generic hashtables inspector io kernel
 math namespaces prettyprint sequences assocs sequences.private
 strings io.styles vectors words system splitting math.parser
 classes.tuple continuations continuations.private combinators
-generic.math io.streams.duplex classes compiler.units
-generic.standard vocabs threads threads.private init
-kernel.private libc io.encodings ;
+generic.math io.streams.duplex classes.builtin classes
+compiler.units generic.standard vocabs threads threads.private
+init kernel.private libc io.encodings accessors ;
 IN: debugger
 
 GENERIC: error. ( error -- )
@@ -160,7 +160,7 @@ PREDICATE: kernel-error < array
     {
         { [ dup empty? ] [ drop f ] }
         { [ dup first "kernel-error" = not ] [ drop f ] }
-        { [ t ] [ second 0 15 between? ] }
+        [ second 0 15 between? ]
     } cond ;
 
 : kernel-errors
@@ -202,6 +202,12 @@ M: no-method error.
 M: no-math-method summary
     drop "No suitable arithmetic method" ;
 
+M: no-next-method summary
+    drop "Executing call-next-method from least-specific method" ;
+
+M: inconsistent-next-method summary
+    drop "Executing call-next-method with inconsistent parameters" ;
+
 M: stream-closed-twice summary
     drop "Attempt to perform I/O on closed stream" ;
 
@@ -223,9 +229,11 @@ M: slice-error error.
 
 M: bounds-error summary drop "Sequence index out of bounds" ;
 
-M: condition error. delegate error. ;
+M: condition error. error>> error. ;
+
+M: condition summary error>> summary ;
 
-M: condition error-help drop f ;
+M: condition error-help error>> error-help ;
 
 M: assert summary drop "Assertion failed" ;
 
index d855a14be99f419e120c9823d47d24370e61a83f..d43c61ff7009387356273b4b6818bb165f1d077f 100755 (executable)
@@ -12,8 +12,6 @@ $nl
 { $subsection forget }
 "Definitions can answer a sequence of definitions they directly depend on:"
 { $subsection uses }
-"When a definition is changed, all definitions which depend on it are notified via a hook:"
-{ $subsection redefined* }
 "Definitions must implement a few operations used for printing them in source form:"
 { $subsection synopsis* }
 { $subsection definer }
@@ -108,11 +106,6 @@ HELP: usage
 { $description "Outputs a sequence of definitions that directly call the given definition." }
 { $notes "The sequence might include the definition itself, if it is a recursive word." } ;
 
-HELP: redefined*
-{ $values { "defspec" "a definition specifier" } }
-{ $contract "Updates the definition to cope with a callee being redefined." }
-$low-level-note ;
-
 HELP: unxref
 { $values { "defspec" "a definition specifier" } }
 { $description "Remove edges leaving the vertex which represents the definition from the " { $link crossref } " graph." }
index 3dc28139ea9d05ad6d042f7982af126ac0206eac..b20d81ec7ca6ed74d372d40539e622ec90023951 100755 (executable)
@@ -2,26 +2,6 @@ IN: definitions.tests
 USING: tools.test generic kernel definitions sequences
 compiler.units words ;
 
-TUPLE: combination-1 ;
-
-M: combination-1 perform-combination drop [ ] define ;
-
-M: combination-1 make-default-method 2drop [ "No method" throw ] ;
-
-SYMBOL: generic-1
-
-[
-    generic-1 T{ combination-1 } define-generic
-
-    object \ generic-1 create-method [ ] define
-] with-compilation-unit
-
-[ ] [
-    [
-        { combination-1 { object generic-1 } } forget-all
-    ] with-compilation-unit
-] unit-test
-
 GENERIC: some-generic ( a -- b )
 
 USE: arrays
index cec510990961f5bd86a2dd76577324be5cbece4a..459512b83a29ef9e5907425c13ec2926c058b20d 100755 (executable)
@@ -5,6 +5,13 @@ USING: kernel sequences namespaces assocs graphs ;
 
 ERROR: no-compilation-unit definition ;
 
+SYMBOL: changed-definitions
+
+: changed-definition ( defspec -- )
+    dup changed-definitions get
+    [ no-compilation-unit ] unless*
+    set-at ;
+
 GENERIC: where ( defspec -- loc )
 
 M: object where drop f ;
@@ -42,13 +49,6 @@ M: object uses drop f ;
 
 : usage ( defspec -- seq ) \ f or crossref get at keys ;
 
-GENERIC: redefined* ( defspec -- )
-
-M: object redefined* drop ;
-
-: redefined ( defspec -- )
-    [ crossref get at ] closure [ drop redefined* ] assoc-each ;
-
 : unxref ( defspec -- )
     dup uses crossref get remove-vertex ;
 
index 56134f3b54b4ddbc499720e71b29e078e6c0ef0c..b4ae2074557b84b45e75029ff57cf8db90ec34b5 100755 (executable)
@@ -126,7 +126,7 @@ PRIVATE>
     {
         { [ over front>> over eq? ] [ drop pop-front* ] }
         { [ over back>> over eq? ] [ drop pop-back* ] }
-        { [ t ] [ unlink-node dec-length ] }
+        [ unlink-node dec-length ]
     } cond ;
 
 : delete-node-if* ( dlist quot -- obj/f ? )
index aed4a64c6cd4c2efad730046d5b2c58a12bce98c..7da290992c2561c9413090da7d8d6efba2133246 100755 (executable)
@@ -20,7 +20,7 @@ TUPLE: effect in out terminated? ;
         { [ dup effect-terminated? ] [ f ] }
         { [ 2dup [ effect-in length ] bi@ > ] [ f ] }
         { [ 2dup [ effect-height ] bi@ = not ] [ f ] }
-        { [ t ] [ t ] }
+        [ t ]
     } cond 2nip ;
 
 GENERIC: (stack-picture) ( obj -- str )
index 5cc044246405306f7c39c8441d833f92ad5473ca..3a5a6571b729759d40ae5635dc3849218e17fef5 100755 (executable)
@@ -40,8 +40,8 @@ M: label fixup*
 
 M: word fixup*
     {
-        { %prologue-later [ dup [ %prologue ] if-stack-frame ] }
-        { %epilogue-later [ dup [ %epilogue ] if-stack-frame ] }
+        { %prologue-later [ dup [ %prologue ] if-stack-frame ] }
+        { %epilogue-later [ dup [ %epilogue ] if-stack-frame ] }
     } case ;
 
 SYMBOL: relocation-table
index 3514947e3d5a62a13dc475ea0986cf1aa2ae0d65..7858205384d158ef28a60396f2f2b026706c8b6f 100755 (executable)
@@ -16,7 +16,7 @@ SYMBOL: compiled
         { [ dup compiled get key? ] [ drop ] }
         { [ dup inlined-block? ] [ drop ] }
         { [ dup primitive? ] [ drop ] }
-        { [ t ] [ dup compile-queue get set-at ] }
+        [ dup compile-queue get set-at ]
     } cond ;
 
 : maybe-compile ( word -- )
index aac1b2cdc63b37db130ac20e2d99babd687f5593..8abd1cd3e038f89622fdd0e1d7a59b84af3222ef 100755 (executable)
@@ -3,7 +3,8 @@
 USING: arrays assocs classes classes.private classes.algebra
 combinators cpu.architecture generator.fixup hashtables kernel
 layouts math namespaces quotations sequences system vectors
-words effects alien byte-arrays bit-arrays float-arrays ;
+words effects alien byte-arrays bit-arrays float-arrays
+accessors ;
 IN: generator.registers
 
 SYMBOL: +input+
@@ -13,9 +14,11 @@ SYMBOL: +clobber+
 SYMBOL: known-tag
 
 ! Register classes
-TUPLE: int-regs ;
-
-TUPLE: float-regs size ;
+SINGLETON: int-regs
+SINGLETON: single-float-regs
+SINGLETON: double-float-regs
+UNION: float-regs single-float-regs double-float-regs ;
+UNION: reg-class int-regs float-regs ;
 
 <PRIVATE
 
@@ -48,13 +51,13 @@ M: value minimal-ds-loc* drop ;
 M: value lazy-store 2drop ;
 
 ! A scratch register for computations
-TUPLE: vreg n ;
+TUPLE: vreg n reg-class ;
 
-: <vreg> ( n reg-class -- vreg )
-    { set-vreg-n set-delegate } vreg construct ;
+C: <vreg> vreg ( n reg-class -- vreg )
 
-M: vreg v>operand dup vreg-n swap vregs nth ;
+M: vreg v>operand [ n>> ] [ reg-class>> ] bi vregs nth ;
 M: vreg live-vregs* , ;
+M: vreg move-spec reg-class>> move-spec ;
 
 INSTANCE: vreg value
 
@@ -62,9 +65,9 @@ M: float-regs move-spec drop float ;
 M: float-regs operand-class* drop float ;
 
 ! Temporary register for stack shuffling
-TUPLE: temp-reg ;
+TUPLE: temp-reg reg-class>> ;
 
-: temp-reg T{ temp-reg T{ int-regs } } ;
+: temp-reg T{ temp-reg f int-regs } ;
 
 M: temp-reg move-spec drop f ;
 
@@ -73,7 +76,7 @@ INSTANCE: temp-reg value
 ! A data stack location.
 TUPLE: ds-loc n class ;
 
-: <ds-loc> { set-ds-loc-n } ds-loc construct ;
+: <ds-loc> f ds-loc construct-boa ;
 
 M: ds-loc minimal-ds-loc* ds-loc-n min ;
 M: ds-loc operand-class* ds-loc-class ;
@@ -84,8 +87,7 @@ M: ds-loc live-loc?
 ! A retain stack location.
 TUPLE: rs-loc n class ;
 
-: <rs-loc> { set-rs-loc-n } rs-loc construct ;
-
+: <rs-loc> f rs-loc construct-boa ;
 M: rs-loc operand-class* rs-loc-class ;
 M: rs-loc set-operand-class set-rs-loc-class ;
 M: rs-loc live-loc?
@@ -126,7 +128,7 @@ INSTANCE: cached value
 TUPLE: tagged vreg class ;
 
 : <tagged> ( vreg -- tagged )
-    { set-tagged-vreg } tagged construct ;
+    f tagged construct-boa ;
 
 M: tagged v>operand tagged-vreg v>operand ;
 M: tagged set-operand-class set-tagged-class ;
@@ -193,7 +195,7 @@ INSTANCE: constant value
         { [ dup byte-array class< ] [ drop %unbox-byte-array ] }
         { [ dup bit-array class< ] [ drop %unbox-byte-array ] }
         { [ dup float-array class< ] [ drop %unbox-byte-array ] }
-        { [ t ] [ drop %unbox-any-c-ptr ] }
+        [ drop %unbox-any-c-ptr ]
     } cond ; inline
 
 : %move-via-temp ( dst src -- )
@@ -228,48 +230,44 @@ INSTANCE: constant value
     } case ;
 
 ! A compile-time stack
-TUPLE: phantom-stack height ;
+TUPLE: phantom-stack height stack ;
 
-GENERIC: finalize-height ( stack -- )
+M: phantom-stack clone
+    call-next-method [ clone ] change-stack ;
 
-SYMBOL: phantom-d
-SYMBOL: phantom-r
+GENERIC: finalize-height ( stack -- )
 
-: <phantom-stack> ( class -- stack )
-    >r
-    V{ } clone 0
-    { set-delegate set-phantom-stack-height }
-    phantom-stack construct
-    r> construct-delegate ;
+: construct-phantom-stack ( class -- stack )
+    >r 0 V{ } clone r> construct-boa ; inline
 
 : (loc)
     #! Utility for methods on <loc>
-    phantom-stack-height - ;
+    height>> - ;
 
 : (finalize-height) ( stack word -- )
     #! We consolidate multiple stack height changes until the
     #! last moment, and we emit the final height changing
     #! instruction here.
-    swap [
-        phantom-stack-height
-        dup zero? [ 2drop ] [ swap execute ] if
-        0
-    ] keep set-phantom-stack-height ; inline
+    [
+        over zero? [ 2drop ] [ execute ] if 0
+    ] curry change-height drop ; inline
 
 GENERIC: <loc> ( n stack -- loc )
 
-TUPLE: phantom-datastack ;
+TUPLE: phantom-datastack < phantom-stack ;
 
-: <phantom-datastack> phantom-datastack <phantom-stack> ;
+: <phantom-datastack> ( -- stack )
+    phantom-datastack construct-phantom-stack ;
 
 M: phantom-datastack <loc> (loc) <ds-loc> ;
 
 M: phantom-datastack finalize-height
     \ %inc-d (finalize-height) ;
 
-TUPLE: phantom-retainstack ;
+TUPLE: phantom-retainstack < phantom-stack ;
 
-: <phantom-retainstack> phantom-retainstack <phantom-stack> ;
+: <phantom-retainstack> ( -- stack )
+    phantom-retainstack construct-phantom-stack ;
 
 M: phantom-retainstack <loc> (loc) <rs-loc> ;
 
@@ -281,34 +279,33 @@ M: phantom-retainstack finalize-height
     >r <reversed> r> [ <loc> ] curry map ;
 
 : phantom-locs* ( phantom -- locs )
-    dup length swap phantom-locs ;
+    [ stack>> length ] keep phantom-locs ;
+
+: phantoms ( -- phantom phantom )
+    phantom-datastack get phantom-retainstack get ;
 
 : (each-loc) ( phantom quot -- )
-    >r dup phantom-locs* swap r> 2each ; inline
+    >r [ phantom-locs* ] [ stack>> ] bi r> 2each ; inline
 
 : each-loc ( quot -- )
-    >r phantom-d get r> phantom-r get over
-    >r >r (each-loc) r> r> (each-loc) ; inline
+    phantoms 2array swap [ (each-loc) ] curry each ; inline
 
 : adjust-phantom ( n phantom -- )
-    [ phantom-stack-height + ] keep set-phantom-stack-height ;
+    swap [ + ] curry change-height drop ;
 
-GENERIC: cut-phantom ( n phantom -- seq )
-
-M: phantom-stack cut-phantom
-    [ delegate swap cut* swap ] keep set-delegate ;
+: cut-phantom ( n phantom -- seq )
+    swap [ cut* swap ] curry change-stack drop ;
 
 : phantom-append ( seq stack -- )
-    over length over adjust-phantom push-all ;
+    over length over adjust-phantom stack>> push-all ;
 
 : add-locs ( n phantom -- )
-    2dup length <= [
+    2dup stack>> length <= [
         2drop
     ] [
         [ phantom-locs ] keep
-        [ length head-slice* ] keep
-        [ append >vector ] keep
-        delegate set-delegate
+        [ stack>> length head-slice* ] keep
+        [ append >vector ] change-stack drop
     ] if ;
 
 : phantom-input ( n phantom -- seq )
@@ -316,18 +313,16 @@ M: phantom-stack cut-phantom
     2dup cut-phantom
     >r >r neg r> adjust-phantom r> ;
 
-: phantoms ( -- phantom phantom ) phantom-d get phantom-r get ;
-
 : each-phantom ( quot -- ) phantoms rot bi@ ; inline
 
 : finalize-heights ( -- ) [ finalize-height ] each-phantom ;
 
 : live-vregs ( -- seq )
-    [ [ [ live-vregs* ] each ] each-phantom ] { } make ;
+    [ [ stack>> [ live-vregs* ] each ] each-phantom ] { } make ;
 
 : (live-locs) ( phantom -- seq )
     #! Discard locs which haven't moved
-    dup phantom-locs* swap 2array flip
+    [ phantom-locs* ] [ stack>> ] bi zip
     [ live-loc? ] assoc-subset
     values ;
 
@@ -340,15 +335,14 @@ SYMBOL: fresh-objects
 
 ! Computing free registers and initializing allocator
 : reg-spec>class ( spec -- class )
-    float eq?
-    T{ float-regs f 8 } T{ int-regs } ? ;
+    float eq? double-float-regs int-regs ? ;
 
 : free-vregs ( reg-class -- seq )
     #! Free vregs in a given register class
     \ free-vregs get at ;
 
 : alloc-vreg ( spec -- reg )
-    dup reg-spec>class free-vregs pop swap {
+    [ reg-spec>class free-vregs pop ] keep {
         { f [ <tagged> ] }
         { unboxed-alien [ <unboxed-alien> ] }
         { unboxed-byte-array [ <unboxed-byte-array> ] }
@@ -363,19 +357,19 @@ SYMBOL: fresh-objects
         { [ dup unboxed-c-ptr eq? ] [
             over { unboxed-byte-array unboxed-alien } member?
         ] }
-        { [ t ] [ f ] }
+        [ f ]
     } cond 2nip ;
 
 : allocation ( value spec -- reg-class )
     {
         { [ dup quotation? ] [ 2drop f ] }
         { [ 2dup compatible? ] [ 2drop f ] }
-        { [ t ] [ nip reg-spec>class ] }
+        [ nip reg-spec>class ]
     } cond ;
 
 : alloc-vreg-for ( value spec -- vreg )
-    swap operand-class swap alloc-vreg
-    dup tagged? [ tuck set-tagged-class ] [ nip ] if ;
+    alloc-vreg swap operand-class
+    over tagged? [ >>class ] [ drop ] if ;
 
 M: value (lazy-load)
     2dup allocation [
@@ -393,7 +387,7 @@ M: value (lazy-load)
 : compute-free-vregs ( -- )
     #! Create a new hashtable for thee free-vregs variable.
     live-vregs
-    { T{ int-regs } T{ float-regs f 8 } }
+    { int-regs double-float-regs }
     [ 2dup (compute-free-vregs) ] H{ } map>assoc
     \ free-vregs set
     drop ;
@@ -418,7 +412,7 @@ M: loc lazy-store
     #! When shuffling more values than can fit in registers, we
     #! need to find an area on the data stack which isn't in
     #! use.
-    dup phantom-stack-height neg [ minimal-ds-loc* ] reduce ;
+    [ stack>> ] [ height>> neg ] bi [ minimal-ds-loc* ] reduce ;
 
 : find-tmp-loc ( -- n )
     #! Find an area of the data stack which is not referenced
@@ -427,7 +421,7 @@ M: loc lazy-store
 
 : slow-shuffle-mapping ( locs tmp -- pairs )
     >r dup length r>
-    [ swap - <ds-loc> ] curry map 2array flip ;
+    [ swap - <ds-loc> ] curry map zip ;
 
 : slow-shuffle ( locs -- )
     #! We don't have enough free registers to load all shuffle
@@ -442,7 +436,7 @@ M: loc lazy-store
 : fast-shuffle? ( live-locs -- ? )
     #! Test if we have enough free registers to load all
     #! shuffle inputs at once.
-    T{ int-regs } free-vregs [ length ] bi@ <= ;
+    int-regs free-vregs [ length ] bi@ <= ;
 
 : finalize-locs ( -- )
     #! Perform any deferred stack shuffling.
@@ -462,13 +456,13 @@ M: loc lazy-store
     #! Kill register assignments but preserve constants and
     #! class information.
     dup phantom-locs*
-    over [
+    over stack>> [
         dup constant? [ nip ] [
             operand-class over set-operand-class
         ] if
     ] 2map
-    over delete-all
-    swap push-all ;
+    over stack>> delete-all
+    swap stack>> push-all ;
 
 : reset-phantoms ( -- )
     [ reset-phantom ] each-phantom ;
@@ -483,10 +477,11 @@ M: loc lazy-store
 
 ! Loading stacks to vregs
 : free-vregs? ( int# float# -- ? )
-    T{ float-regs f 8 } free-vregs length <=
-    >r T{ int-regs } free-vregs length <= r> and ;
+    double-float-regs free-vregs length <=
+    >r int-regs free-vregs length <= r> and ;
 
 : phantom&spec ( phantom spec -- phantom' spec' )
+    >r stack>> r>
     [ length f pad-left ] keep
     [ <reversed> ] bi@ ; inline
 
@@ -504,7 +499,7 @@ M: loc lazy-store
 : substitute-vregs ( values vregs -- )
     [ vreg-substitution ] 2map
     [ substitute-vreg? ] assoc-subset >hashtable
-    [ substitute-here ] curry each-phantom ;
+    [ >r stack>> r> substitute-here ] curry each-phantom ;
 
 : set-operand ( value var -- )
     >r dup constant? [ constant-value ] when r> set ;
@@ -516,14 +511,15 @@ M: loc lazy-store
     substitute-vregs ;
 
 : load-inputs ( -- )
-    +input+ get dup length phantom-d get phantom-input
-    swap lazy-load ;
+    +input+ get
+    [ length phantom-datastack get phantom-input ] keep
+    lazy-load ;
 
 : output-vregs ( -- seq seq )
     +output+ +clobber+ [ get [ get ] map ] bi@ ;
 
 : clash? ( seq -- ? )
-    phantoms append [
+    phantoms [ stack>> ] bi@ append [
         dup cached? [ cached-vreg ] when swap member?
     ] with contains? ;
 
@@ -534,22 +530,21 @@ M: loc lazy-store
 
 : count-input-vregs ( phantom spec -- )
     phantom&spec [
-        >r dup cached? [ cached-vreg ] when r> allocation
+        >r dup cached? [ cached-vreg ] when r> first allocation
     ] 2map count-vregs ;
 
 : count-scratch-regs ( spec -- )
     [ first reg-spec>class ] map count-vregs ;
 
 : guess-vregs ( dinput rinput scratch -- int# float# )
-    H{
-        { T{ int-regs } 0 }
-        { T{ float-regs 8 } 0 }
-    } clone [
+    [
+        0 int-regs set
+        0 double-float-regs set
         count-scratch-regs
-        phantom-r get swap count-input-vregs
-        phantom-d get swap count-input-vregs
-        T{ int-regs } get T{ float-regs 8 } get
-    ] bind ;
+        phantom-retainstack get swap count-input-vregs
+        phantom-datastack get swap count-input-vregs
+        int-regs get double-float-regs get
+    ] with-scope ;
 
 : alloc-scratch ( -- )
     +scratch+ get [ >r alloc-vreg r> set ] assoc-each ;
@@ -566,7 +561,7 @@ M: loc lazy-store
     outputs-clash? [ finalize-contents ] when ;
 
 : template-outputs ( -- )
-    +output+ get [ get ] map phantom-d get phantom-append ;
+    +output+ get [ get ] map phantom-datastack get phantom-append ;
 
 : value-matches? ( value spec -- ? )
     #! If the spec is a quotation and the value is a literal
@@ -581,12 +576,6 @@ M: loc lazy-store
         2drop t
     ] if ;
 
-: class-tags ( class -- tag/f )
-    class-types [
-        dup num-tags get >=
-        [ drop object tag-number ] when
-    ] map prune ;
-
 : class-tag ( class -- tag/f )
     class-tags dup length 1 = [ first ] [ drop f ] if ;
 
@@ -602,7 +591,7 @@ M: loc lazy-store
     >r >r operand-class 2 r> ?nth class-matches? r> and ;
 
 : template-matches? ( spec -- ? )
-    phantom-d get +input+ rot at
+    phantom-datastack get +input+ rot at
     [ spec-matches? ] phantom&spec-agree? ;
 
 : ensure-template-vregs ( -- )
@@ -611,14 +600,14 @@ M: loc lazy-store
     ] unless ;
 
 : clear-phantoms ( -- )
-    [ delete-all ] each-phantom ;
+    [ stack>> delete-all ] each-phantom ;
 
 PRIVATE>
 
 : set-operand-classes ( classes -- )
-    phantom-d get
+    phantom-datastack get
     over length over add-locs
-    [ set-operand-class ] 2reverse-each ;
+    stack>> [ set-operand-class ] 2reverse-each ;
 
 : end-basic-block ( -- )
     #! Commit all deferred stacking shuffling, and ensure the
@@ -627,7 +616,7 @@ PRIVATE>
     finalize-contents
     clear-phantoms
     finalize-heights
-    fresh-objects get dup empty? swap delete-all [ %gc ] unless ;
+    fresh-objects get [ empty? [ %gc ] unless ] [ delete-all ] bi ;
 
 : with-template ( quot hash -- )
     clone [
@@ -647,16 +636,16 @@ PRIVATE>
 : init-templates ( -- )
     #! Initialize register allocator.
     V{ } clone fresh-objects set
-    <phantom-datastack> phantom-d set
-    <phantom-retainstack> phantom-r set
+    <phantom-datastack> phantom-datastack set
+    <phantom-retainstack> phantom-retainstack set
     compute-free-vregs ;
 
 : copy-templates ( -- )
     #! Copies register allocator state, used when compiling
     #! branches.
     fresh-objects [ clone ] change
-    phantom-d [ clone ] change
-    phantom-r [ clone ] change
+    phantom-datastack [ clone ] change
+    phantom-retainstack [ clone ] change
     compute-free-vregs ;
 
 : find-template ( templates -- pair/f )
@@ -672,17 +661,17 @@ UNION: immediate fixnum POSTPONE: f ;
     operand-class immediate class< ;
 
 : phantom-push ( obj -- )
-    1 phantom-d get adjust-phantom
-    phantom-d get push ;
+    1 phantom-datastack get adjust-phantom
+    phantom-datastack get stack>> push ;
 
 : phantom-shuffle ( shuffle -- )
-    [ effect-in length phantom-d get phantom-input ] keep
-    shuffle* phantom-d get phantom-append ;
+    [ effect-in length phantom-datastack get phantom-input ] keep
+    shuffle* phantom-datastack get phantom-append ;
 
 : phantom->r ( n -- )
-    phantom-d get phantom-input
-    phantom-r get phantom-append ;
+    phantom-datastack get phantom-input
+    phantom-retainstack get phantom-append ;
 
 : phantom-r> ( n -- )
-    phantom-r get phantom-input
-    phantom-d get phantom-append ;
+    phantom-retainstack get phantom-input
+    phantom-datastack get phantom-append ;
index 04252b6b3bcb63abe780a2371ac136c9ad359150..1024c377a8c18c5c4a47de2f741dcd7c2372ddd1 100755 (executable)
@@ -37,6 +37,8 @@ $nl
 { $subsection create-method }
 "Method definitions can be looked up:"
 { $subsection method }
+"Finding the most specific method for an object:"
+{ $subsection effective-method }
 "A generic word contains methods; the list of methods specializing on a class can also be obtained:"
 { $subsection implementors }
 "Low-level word which rebuilds the generic word after methods are added or removed, or the method combination is changed:"
@@ -64,6 +66,19 @@ $nl
 "The combination quotation passed to " { $link define-generic } " has stack effect " { $snippet "( word -- quot )" } ". It's job is to call various introspection words, including at least obtaining the set of methods defined on the generic word, then combining these methods in some way to produce a quotation."
 { $see-also "generic-introspection" } ;
 
+ARTICLE: "call-next-method" "Calling less-specific methods"
+"If a generic word is called with an object and multiple methods specialize on classes that this object is an instance of, usually the most specific method is called (" { $link "method-order" } ")."
+$nl
+"Less-specific methods can be called directly:"
+{ $subsection POSTPONE: call-next-method }
+"A lower-level word which the above expands into:"
+{ $subsection (call-next-method) }
+"To look up the next applicable method reflectively:"
+{ $subsection next-method }
+"Errors thrown by improper calls to " { $link POSTPONE: call-next-method } ":"
+{ $subsection inconsistent-next-method }
+{ $subsection no-next-method } ;
+
 ARTICLE: "generic" "Generic words and methods"
 "A " { $emphasis "generic word" } " is composed of zero or more " { $emphasis "methods" } " together with a " { $emphasis "method combination" } ". A method " { $emphasis "specializes" } " on a class; when a generic word executed, the method combination chooses the most appropriate method and calls its definition."
 $nl
@@ -81,6 +96,7 @@ $nl
 { $subsection POSTPONE: M: }
 "Generic words must declare their stack effect in order to compile. See " { $link "effect-declaration" } "."
 { $subsection "method-order" }
+{ $subsection "call-next-method" }
 { $subsection "generic-introspection" }
 { $subsection "method-combination" }
 "Generic words specialize behavior based on the class of an object; sometimes behavior needs to be specialized on the object's " { $emphasis "structure" } "; this is known as " { $emphasis "pattern matching" } " and is implemented in the " { $vocab-link "match" } " vocabulary." ;
@@ -147,3 +163,8 @@ HELP: forget-methods
 { $description "Remove all method definitions which specialize on the class." } ;
 
 { sort-classes order } related-words
+
+HELP: (call-next-method)
+{ $values { "class" class } { "generic" generic } }
+{ $description "Low-level word implementing " { $link POSTPONE: call-next-method } "." }
+{ $notes "In most cases, " { $link POSTPONE: call-next-method } " should be used instead." } ;
index 524835f461897a9d8c6b45451643ec77fd4be146..bbd7186a113a78f68dbe75455d08130c1a8d8b36 100755 (executable)
@@ -123,17 +123,6 @@ M: integer wii drop 6 ;
 
 [ 3 ] [ T{ first-one } wii ] unit-test
 
-! Hooks
-SYMBOL: my-var
-HOOK: my-hook my-var ( -- x )
-
-M: integer my-hook "an integer" ;
-M: string my-hook "a string" ;
-
-[ "an integer" ] [ 3 my-var set my-hook ] unit-test
-[ "a string" ] [ my-hook my-var set my-hook ] unit-test
-[ 1.0 my-var set my-hook ] [ T{ no-method f 1.0 my-hook } = ] must-fail-with
-
 GENERIC: tag-and-f ( x -- x x )
 
 M: fixnum tag-and-f 1 ;
index 72948c54731e4a74a3baf8721206a214be7c82b6..cd08e8051204ec81c16204ca426be0ec038915fa 100755 (executable)
@@ -29,6 +29,8 @@ PREDICATE: method-spec < pair
 : order ( generic -- seq )
     "methods" word-prop keys sort-classes ;
 
+GENERIC: effective-method ( ... generic -- method )
+
 : next-method-class ( class generic -- class/f )
     order [ class< ] with subset reverse dup length 1 =
     [ drop f ] [ second ] if ;
@@ -36,7 +38,10 @@ PREDICATE: method-spec < pair
 : next-method ( class generic -- class/f )
     [ next-method-class ] keep method ;
 
-GENERIC: next-method-quot ( class generic -- quot )
+GENERIC: next-method-quot* ( class generic -- quot )
+
+: next-method-quot ( class generic -- quot )
+    dup "combination" word-prop next-method-quot* ;
 
 : (call-next-method) ( class generic -- )
     next-method-quot call ;
index 46208744f0bd89398c2d8736d7ccb8b16c6ce937..884ab8027ef637f1ddd23923eecc1ad900f26b7f 100755 (executable)
@@ -2,7 +2,8 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays generic hashtables kernel kernel.private
 math namespaces sequences words quotations layouts combinators
-sequences.private classes classes.algebra definitions ;
+sequences.private classes classes.builtin classes.algebra
+definitions ;
 IN: generic.math
 
 PREDICATE: math-class < class
@@ -18,7 +19,7 @@ PREDICATE: math-class < class
     {
         { [ dup null class< ] [ drop { -1 -1 } ] }
         { [ dup math-class? ] [ class-types last/first ] }
-        { [ t ] [ drop { 100 100 } ] }
+        [ drop { 100 100 } ]
     } cond ;
     
 : math-class-max ( class class -- class )
index bf8d4fb67a44adc6a196673c05b6ed14c7ab55be..1f0b80e016e2ab69dea116d83640fbc4e4ed8f60 100644 (file)
@@ -47,3 +47,5 @@ SYMBOL: (dispatch#)
     } case ;
 
 : picker ( -- quot ) \ (dispatch#) get (picker) ;
+
+GENERIC: extra-values ( generic -- n )
index ce7d5c6c217f57b1b1b87f67f075953400b0fe8e..5335074deaf68784cf142de1d7499361d37349f1 100644 (file)
@@ -18,7 +18,7 @@ C: <predicate-dispatch-engine> predicate-dispatch-engine
         { [ dup empty? ] [ drop [ "Unreachable" throw ] { } ] }
         { [ dup length 1 = ] [ first second { } ] }
         { [ dup keep-going? ] [ 1 tail-slice prune-redundant-predicates ] }
-        { [ t ] [ [ first second ] [ 1 tail-slice ] bi ] }
+        [ [ first second ] [ 1 tail-slice ] bi ]
     } cond ;
 
 : sort-methods ( assoc -- assoc' )
index 40e749f4731e0970ea0054b0824efe86e975a43e..69d73aa872d90a39400df46e43c62fbfe666a599 100644 (file)
@@ -66,7 +66,9 @@ PREDICATE: tuple-dispatch-engine-word < word
     "tuple-dispatch-engine" word-prop ;
 
 M: tuple-dispatch-engine-word stack-effect
-    "tuple-dispatch-generic" word-prop stack-effect ;
+    "tuple-dispatch-generic" word-prop
+    [ extra-values ] [ stack-effect clone ] bi
+    [ length + ] change-in ;
 
 M: tuple-dispatch-engine-word crossref?
     drop t ;
index a6a65bb62f3717534e3f9ea9d90947dee277e0f3..1d98dec87c7370e00cf26a5a39fad1fad2c21fb4 100644 (file)
@@ -1,4 +1,5 @@
-USING: generic help.markup help.syntax sequences ;
+USING: generic help.markup help.syntax sequences math
+math.parser ;
 IN: generic.standard
 
 HELP: no-method
@@ -10,7 +11,7 @@ HELP: standard-combination
 { $class-description
     "Performs standard method combination."
     $nl
-    "Generic words using the standard method combination dispatch on the class of the object at the given stack position, where 0 is the top of the stack, 1 is the object underneath, and 2 is the next one under that. If no suitable method is defined on the class of the dispatch object, the generic word is called on the dispatch object's delegate. If the delegate is " { $link f } ", an exception is thrown."
+    "Generic words using the standard method combination dispatch on the class of the object at the given stack position, where 0 is the top of the stack, 1 is the object underneath, and 2 is the next one under that. A " { $link no-method } " error is thrown if no suitable method is defined on the class."
 }
 { $examples
     "A generic word for append strings and characters to a sequence, dispatching on the object underneath the top of the stack:"
@@ -31,3 +32,38 @@ HELP: define-simple-generic
 { $description "Defines a generic word with the " { $link standard-combination } " method combination and a dispatch position of 0." } ;
 
 { standard-combination hook-combination } related-words
+
+HELP: no-next-method
+{ $error-description "Thrown by " { $link POSTPONE: call-next-method } " if the current method is already the least specific method." }
+{ $examples
+    "The following code throws this error:"
+    { $code
+        "GENERIC: error-test ( object -- )"
+        ""
+        "M: number error-test 3 + call-next-method ;"
+        ""
+        "M: integer error-test recip call-next-method ;"
+        ""
+        "123 error-test"
+    }
+    "This results in the method on " { $link integer } " being called, which then calls the method on " { $link number } ". The latter then calls " { $link POSTPONE: call-next-method } ", however there is no method less specific than the method on " { $link number } " and so an error is thrown."
+} ;
+
+HELP: inconsistent-next-method
+{ $error-description "Thrown by " { $link POSTPONE: call-next-method } " if the values on the stack are not compatible with the current method." }
+{ $examples
+    "The following code throws this error:"
+    { $code
+        "GENERIC: error-test ( object -- )"
+        ""
+        "M: string error-test print ;"
+        ""
+        "M: integer error-test number>string call-next-method ;"
+        ""
+        "123 error-test"
+    }
+    "This results in the method on " { $link integer } " being called, which then passes a string to " { $link POSTPONE: call-next-method } ". However, this fails because the string is not compatible with the current method."
+    $nl
+    "This usually indicates programmer error; if the intention above was to call the string method on the result of " { $link number>string } ", the code should be rewritten as follows:"
+    { $code "M: integer error-test number>string error-test ;" }
+} ;
index 2f58770b1a5e7aad6a835372fb3d521bc1a7f47f..a906acd3240b78966dce66879e9f0716bc6f9309 100644 (file)
@@ -1,7 +1,8 @@
 IN: generic.standard.tests
 USING: tools.test math math.functions math.constants
 generic.standard strings sequences arrays kernel accessors
-words float-arrays byte-arrays bit-arrays parser namespaces ;
+words float-arrays byte-arrays bit-arrays parser namespaces
+quotations inference vectors growable ;
 
 GENERIC: lo-tag-test
 
@@ -194,7 +195,7 @@ M: ceo salary
 [ 102000 ] [ executive construct-boa salary ] unit-test
 
 [ ceo construct-boa salary ]
-[ T{ inconsistent-next-method f ceo salary } = ] must-fail-with
+[ T{ inconsistent-next-method f ceo salary } = ] must-fail-with
 
 [ intern construct-boa salary ]
 [ T{ no-next-method f intern salary } = ] must-fail-with
@@ -233,3 +234,37 @@ M: c funky* "c" , call-next-method ;
     T{ a } funky
     { { "a" "x" "z" } { "a" "y" "z" } } member?
 ] unit-test
+
+! Hooks
+SYMBOL: my-var
+HOOK: my-hook my-var ( -- x )
+
+M: integer my-hook "an integer" ;
+M: string my-hook "a string" ;
+
+[ "an integer" ] [ 3 my-var set my-hook ] unit-test
+[ "a string" ] [ my-hook my-var set my-hook ] unit-test
+[ 1.0 my-var set my-hook ] [ T{ no-method f 1.0 my-hook } = ] must-fail-with
+
+HOOK: my-tuple-hook my-var ( -- x )
+
+M: sequence my-tuple-hook my-hook ;
+
+[ f ] [
+    \ my-tuple-hook [ "engines" word-prop ] keep prefix
+    [ 1quotation infer ] map all-equal?
+] unit-test
+
+HOOK: call-next-hooker my-var ( -- x )
+
+M: sequence call-next-hooker "sequence" ;
+
+M: array call-next-hooker call-next-method "array " prepend ;
+
+M: vector call-next-hooker call-next-method "vector " prepend ;
+
+M: growable call-next-hooker call-next-method "growable " prepend ;
+
+[ "vector growable sequence" ] [
+    V{ } my-var [ call-next-hooker ] with-variable
+] unit-test
index c36e5f19212b454d4a5f9f78c6d310d618b0b29d..98194e7ef3026fa29a92b77acfb79f0b8c7fe283 100644 (file)
@@ -67,7 +67,9 @@ ERROR: no-method object generic ;
         drop generic get "default-method" word-prop 1quotation
     ] unless ;
 
-GENERIC: mangle-method ( method generic -- quot )
+: mangle-method ( method generic -- quot )
+    [ 1quotation ] [ extra-values \ drop <repetition> ] bi*
+    prepend [ ] like ;
 
 : single-combination ( word -- quot )
     [
@@ -91,6 +93,26 @@ GENERIC: mangle-method ( method generic -- quot )
         } cleave
     ] with-scope ;
 
+ERROR: inconsistent-next-method class generic ;
+
+ERROR: no-next-method class generic ;
+
+: single-next-method-quot ( class generic -- quot )
+    [
+        [ drop [ instance? ] curry % ]
+        [
+            2dup next-method
+            [ 2nip 1quotation ]
+            [ [ no-next-method ] 2curry ] if* ,
+        ]
+        [ [ inconsistent-next-method ] 2curry , ]
+        2tri
+        \ if ,
+    ] [ ] make ;
+
+: single-effective-method ( obj word -- method )
+    [ order [ instance? ] with find-last nip ] keep method ;
+
 TUPLE: standard-combination # ;
 
 C: <standard-combination> standard-combination
@@ -107,8 +129,7 @@ PREDICATE: simple-generic < standard-generic
 : with-standard ( combination quot -- quot' )
     >r #>> (dispatch#) r> with-variable ; inline
 
-M: standard-generic mangle-method
-    drop 1quotation ;
+M: standard-generic extra-values drop 0 ;
 
 M: standard-combination make-default-method
     [ empty-method ] with-standard ;
@@ -118,25 +139,13 @@ M: standard-combination perform-combination
 
 M: standard-combination dispatch# #>> ;
 
-ERROR: inconsistent-next-method object class generic ;
-
-ERROR: no-next-method class generic ;
-
-M: standard-generic next-method-quot
+M: standard-combination next-method-quot*
     [
-        [
-            [ [ instance? ] curry ]
-            [ dispatch# (picker) ] bi* prepend %
-        ]
-        [
-            2dup next-method
-            [ 2nip 1quotation ]
-            [ [ no-next-method ] 2curry ] if* ,
-        ]
-        [ [ inconsistent-next-method ] 2curry , ]
-        2tri
-        \ if ,
-    ] [ ] make ;
+        single-next-method-quot picker prepend
+    ] with-standard ;
+
+M: standard-generic effective-method
+    [ dispatch# (picker) call ] keep single-effective-method ;
 
 TUPLE: hook-combination var ;
 
@@ -152,8 +161,11 @@ PREDICATE: hook-generic < generic
 
 M: hook-combination dispatch# drop 0 ;
 
-M: hook-generic mangle-method
-    drop 1quotation [ drop ] prepend ;
+M: hook-generic extra-values drop 1 ;
+
+M: hook-generic effective-method
+    [ "combination" word-prop var>> get ] keep
+    single-effective-method ;
 
 M: hook-combination make-default-method
     [ error-method ] with-hook ;
@@ -161,6 +173,9 @@ M: hook-combination make-default-method
 M: hook-combination perform-combination
     [ drop ] [ [ single-combination ] with-hook ] 2bi define ;
 
+M: hook-combination next-method-quot*
+    [ single-next-method-quot ] with-hook ;
+
 M: simple-generic definer drop \ GENERIC: f ;
 
 M: standard-generic definer drop \ GENERIC# f ;
index 77560c7444b0657869bdd6a1b882f9929a288323..b22d8818c1c2ce4df0d7925a1edd0091f4cffc76 100755 (executable)
@@ -2,7 +2,8 @@
 ! See http://factorcode.org/license.txt for BSD license.
 
 USING: arrays kernel math namespaces tools.test
-heaps heaps.private math.parser random assocs sequences sorting ;
+heaps heaps.private math.parser random assocs sequences sorting
+accessors ;
 IN: heaps.tests
 
 [ <min-heap> heap-pop ] must-fail
@@ -47,7 +48,7 @@ IN: heaps.tests
 : test-entry-indices ( n -- ? )
     random-alist
     <min-heap> [ heap-push-all ] keep
-    heap-data dup length swap [ entry-index ] map sequence= ;
+    data>> dup length swap [ entry-index ] map sequence= ;
 
 14 [
     [ t ] swap [ 2^ test-entry-indices ] curry unit-test
@@ -63,9 +64,9 @@ IN: heaps.tests
     [
         random-alist
         <min-heap> [ heap-push-all ] keep
-        dup heap-data clone swap
+        dup data>> clone swap
     ] keep 3 /i [ 2dup >r delete-random r> heap-delete ] times
-    heap-data
+    data>>
     [ [ entry-key ] map ] bi@
     [ natural-sort ] bi@ ;
 
index 34a4dc0d49766870d42601c5648e799b84d3c45a..783d662e43421c5cb35140fca0f87ba226bbc415 100755 (executable)
@@ -17,10 +17,10 @@ GENERIC: heap-size ( heap -- n )
 
 <PRIVATE
 
-: heap-data delegate ; inline
+TUPLE: heap data ;
 
 : <heap> ( class -- heap )
-    >r V{ } clone r> construct-delegate ; inline
+    >r V{ } clone r> construct-boa ; inline
 
 TUPLE: entry value key heap index ;
 
@@ -28,11 +28,11 @@ TUPLE: entry value key heap index ;
 
 PRIVATE>
 
-TUPLE: min-heap ;
+TUPLE: min-heap < heap ;
 
 : <min-heap> ( -- min-heap ) min-heap <heap> ;
 
-TUPLE: max-heap ;
+TUPLE: max-heap < heap ;
 
 : <max-heap> ( -- max-heap ) max-heap <heap> ;
 
@@ -40,10 +40,10 @@ INSTANCE: min-heap priority-queue
 INSTANCE: max-heap priority-queue
 
 M: priority-queue heap-empty? ( heap -- ? )
-    heap-data empty? ;
+    data>> empty? ;
 
 M: priority-queue heap-size ( heap -- n )
-    heap-data length ;
+    data>> length ;
 
 <PRIVATE
 
@@ -54,7 +54,7 @@ M: priority-queue heap-size ( heap -- n )
 : up ( n -- m ) 1- 2/ ; inline
 
 : data-nth ( n heap -- entry )
-    heap-data nth-unsafe ; inline
+    data>> nth-unsafe ; inline
 
 : up-value ( n heap -- entry )
     >r up r> data-nth ; inline
@@ -67,24 +67,24 @@ M: priority-queue heap-size ( heap -- n )
 
 : data-set-nth ( entry n heap -- )
     >r [ swap set-entry-index ] 2keep r>
-    heap-data set-nth-unsafe ;
+    data>> set-nth-unsafe ;
 
 : data-push ( entry heap -- n )
     dup heap-size [
-        swap 2dup heap-data ensure 2drop data-set-nth
+        swap 2dup data>> ensure 2drop data-set-nth
     ] keep ; inline
 
 : data-pop ( heap -- entry )
-    heap-data pop ; inline
+    data>> pop ; inline
 
 : data-pop* ( heap -- )
-    heap-data pop* ; inline
+    data>> pop* ; inline
 
 : data-peek ( heap -- entry )
-    heap-data peek ; inline
+    data>> peek ; inline
 
 : data-first ( heap -- entry )
-    heap-data first ; inline
+    data>> first ; inline
 
 : data-exchange ( m n heap -- )
     [ tuck data-nth >r data-nth r> ] 3keep
index 1d742e144a138ff890798525aadf160d6b06d053..0125f04efad796ff4d124fe62a20c31484f62f39 100755 (executable)
@@ -1,10 +1,11 @@
 USING: help.syntax help.markup words effects inference.dataflow
-inference.state inference.backend kernel sequences
+inference.state kernel sequences
 kernel.private combinators sequences.private ;
+IN: inference.backend
 
 HELP: literal-expected
 { $error-description "Thrown when inference encounters a " { $link call } " or " { $link if } " being applied to a value which is not known to be a literal. Such a form can have an arbitrary stack effect, and does not compile." }
-{ $notes "This error will be thrown when compiling any combinator, such as " { $link each } ". However, words calling combinators can compile of the combinator is declared " { $link POSTPONE: inline } " and the quotation being passed in is a literal." } ;
+{ $notes "This error will be thrown when compiling any combinator, such as " { $link each } ". However, words calling combinators can compile if the combinator is declared " { $link POSTPONE: inline } " and the quotation being passed in is a literal." } ;
 
 HELP: too-many->r
 { $error-description "Thrown if inference notices a quotation pushing elements on the retain stack without popping them at the end." }
index 61412ccf9f6b6c20d0a218a9c422c2c3e51c6142..1945ed1a380c19841b324516e3b6af4b68c34a0c 100755 (executable)
@@ -4,7 +4,7 @@ USING: inference.dataflow inference.state arrays generic io
 io.streams.string kernel math namespaces parser prettyprint
 sequences strings vectors words quotations effects classes
 continuations debugger assocs combinators compiler.errors
-generic.standard.engines.tuple ;
+generic.standard.engines.tuple accessors ;
 IN: inference.backend
 
 : recursive-label ( word -- label/f )
@@ -32,18 +32,16 @@ M: word inline?
 : recursive-quotation? ( quot -- ? )
     local-recursive-state [ first eq? ] with contains? ;
 
-TUPLE: inference-error rstate type ;
+TUPLE: inference-error error type rstate ;
 
-M: inference-error compiler-error-type
-    inference-error-type ;
+M: inference-error compiler-error-type type>> ;
+
+M: inference-error error-help error>> error-help ;
 
 : (inference-error) ( ... class type -- * )
     >r construct-boa r>
-    recursive-state get {
-        set-delegate
-        set-inference-error-type
-        set-inference-error-rstate
-    } \ inference-error construct throw ; inline
+    recursive-state get
+    \ inference-error construct-boa throw ; inline
 
 : inference-error ( ... class -- * )
     +error+ (inference-error) ; inline
@@ -253,7 +251,7 @@ TUPLE: cannot-unify-specials ;
         { [ dup [ curried? ] all? ] [ unify-curries ] }
         { [ dup [ composed? ] all? ] [ unify-composed ] }
         { [ dup [ special? ] contains? ] [ cannot-unify-specials ] }
-        { [ t ] [ drop <computed> ] }
+        [ drop <computed> ]
     } cond ;
 
 : unify-stacks ( seq -- stack )
@@ -363,7 +361,7 @@ TUPLE: effect-error word effect ;
     \ effect-error inference-error ;
 
 : check-effect ( word effect -- )
-    dup pick "declared-effect" word-prop effect<=
+    dup pick stack-effect effect<=
     [ 2drop ] [ effect-error ] if ;
 
 : finish-word ( word -- )
@@ -397,7 +395,7 @@ TUPLE: effect-error word effect ;
         { [ dup "infer" word-prop ] [ custom-infer ] }
         { [ dup "no-effect" word-prop ] [ no-effect ] }
         { [ dup "inferred-effect" word-prop ] [ cached-infer ] }
-        { [ t ] [ dup infer-word make-call-node ] }
+        [ dup infer-word make-call-node ]
     } cond ;
 
 TUPLE: recursive-declare-error word ;
index 01c0a9c5f4d71b2a58cb00e9635ec0d0b20d016f..a4b7ad1888f90ca74308f6d6d776b0285f0b0201 100755 (executable)
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays generic assocs kernel math namespaces parser
 sequences words vectors math.intervals effects classes
-inference.state ;
+inference.state accessors combinators ;
 IN: inference.dataflow
 
 ! Computed value
@@ -39,12 +39,12 @@ M: node hashcode* drop node hashcode* ;
 GENERIC: flatten-curry ( value -- )
 
 M: curried flatten-curry
-    dup curried-obj flatten-curry
-    curried-quot flatten-curry ;
+    [ obj>> flatten-curry ]
+    [ quot>> flatten-curry ] bi ;
 
 M: composed flatten-curry
-    dup composed-quot1 flatten-curry
-    composed-quot2 flatten-curry ;
+    [ quot1>> flatten-curry ]
+    [ quot2>> flatten-curry ] bi ;
 
 M: object flatten-curry , ;
 
@@ -57,31 +57,27 @@ M: object flatten-curry , ;
     meta-d get clone flatten-curries ;
 
 : modify-values ( node quot -- )
-    [ swap [ node-in-d swap call ] keep set-node-in-d ] 2keep
-    [ swap [ node-in-r swap call ] keep set-node-in-r ] 2keep
-    [ swap [ node-out-d swap call ] keep set-node-out-d ] 2keep
-    swap [ node-out-r swap call ] keep set-node-out-r ; inline
+    {
+        [ change-in-d ]
+        [ change-in-r ]
+        [ change-out-d ]
+        [ change-out-r ]
+    } cleave drop ; inline
 
 : node-shuffle ( node -- shuffle )
-    dup node-in-d swap node-out-d <effect> ;
-
-: make-node ( slots class -- node )
-    >r node construct r> construct-delegate ; inline
-
-: empty-node ( class -- node )
-    { } swap make-node ; inline
+    [ in-d>> ] [ out-d>> ] bi <effect> ;
 
 : param-node ( param class -- node )
-    { set-node-param } swap make-node ; inline
+    construct-empty swap >>param ; inline
 
 : in-node ( seq class -- node )
-    { set-node-in-d } swap make-node ; inline
+    construct-empty swap >>in-d ; inline
 
 : all-in-node ( class -- node )
     flatten-meta-d swap in-node ; inline
 
 : out-node ( seq class -- node )
-    { set-node-out-d } swap make-node ; inline
+    construct-empty swap >>out-d ; inline
 
 : all-out-node ( class -- node )
     flatten-meta-d swap out-node ; inline
@@ -94,81 +90,81 @@ M: object flatten-curry , ;
 
 : node-child node-children first ;
 
-TUPLE: #label word loop? ;
+TUPLE: #label < node word loop? ;
 
 : #label ( word label -- node )
-    \ #label param-node [ set-#label-word ] keep ;
+    \ #label param-node swap >>word ;
 
 PREDICATE: #loop < #label #label-loop? ;
 
-TUPLE: #entry ;
+TUPLE: #entry < node ;
 
 : #entry ( -- node ) \ #entry all-out-node ;
 
-TUPLE: #call ;
+TUPLE: #call < node ;
 
 : #call ( word -- node ) \ #call param-node ;
 
-TUPLE: #call-label ;
+TUPLE: #call-label < node ;
 
 : #call-label ( label -- node ) \ #call-label param-node ;
 
-TUPLE: #push ;
+TUPLE: #push < node ;
 
-: #push ( -- node ) \ #push empty-node ;
+: #push ( -- node ) \ #push construct-empty ;
 
-TUPLE: #shuffle ;
+TUPLE: #shuffle < node ;
 
-: #shuffle ( -- node ) \ #shuffle empty-node ;
+: #shuffle ( -- node ) \ #shuffle construct-empty ;
 
-TUPLE: #>r ;
+TUPLE: #>r < node ;
 
-: #>r ( -- node ) \ #>r empty-node ;
+: #>r ( -- node ) \ #>r construct-empty ;
 
-TUPLE: #r> ;
+TUPLE: #r> < node ;
 
-: #r> ( -- node ) \ #r> empty-node ;
+: #r> ( -- node ) \ #r> construct-empty ;
 
-TUPLE: #values ;
+TUPLE: #values < node ;
 
 : #values ( -- node ) \ #values all-in-node ;
 
-TUPLE: #return ;
+TUPLE: #return < node ;
 
 : #return ( label -- node )
-    \ #return all-in-node [ set-node-param ] keep ;
+    \ #return all-in-node swap >>param ;
+
+TUPLE: #branch < node ;
 
-TUPLE: #if ;
+TUPLE: #if < #branch ;
 
 : #if ( -- node ) peek-d 1array \ #if in-node ;
 
-TUPLE: #dispatch ;
+TUPLE: #dispatch < #branch ;
 
 : #dispatch ( -- node ) peek-d 1array \ #dispatch in-node ;
 
-TUPLE: #merge ;
+TUPLE: #merge < node ;
 
 : #merge ( -- node ) \ #merge all-out-node ;
 
-TUPLE: #terminate ;
+TUPLE: #terminate < node ;
 
-: #terminate ( -- node ) \ #terminate empty-node ;
+: #terminate ( -- node ) \ #terminate construct-empty ;
 
-TUPLE: #declare ;
+TUPLE: #declare < node ;
 
 : #declare ( classes -- node ) \ #declare param-node ;
 
-UNION: #branch #if #dispatch ;
-
 : node-inputs ( d-count r-count node -- )
     tuck
-    >r r-tail flatten-curries r> set-node-in-r
-    >r d-tail flatten-curries r> set-node-in-d ;
+    [ swap d-tail flatten-curries >>in-d drop ]
+    [ swap r-tail flatten-curries >>in-r drop ] 2bi* ;
 
 : node-outputs ( d-count r-count node -- )
     tuck
-    >r r-tail flatten-curries r> set-node-out-r
-    >r d-tail flatten-curries r> set-node-out-d ;
+    [ swap d-tail flatten-curries >>out-d drop ]
+    [ swap r-tail flatten-curries >>out-r drop ] 2bi* ;
 
 : node, ( node -- )
     dataflow-graph get [
@@ -178,17 +174,15 @@ UNION: #branch #if #dispatch ;
     ] if ;
 
 : node-values ( node -- values )
-    dup node-in-d
-    over node-out-d
-    pick node-in-r
-    roll node-out-r 4array concat ;
+    { [ in-d>> ] [ out-d>> ] [ in-r>> ] [ out-r>> ] } cleave
+    4array concat ;
 
 : last-node ( node -- last )
-    dup node-successor [ last-node ] [ ] ?if ;
+    dup successor>> [ last-node ] [ ] ?if ;
 
 : penultimate-node ( node -- penultimate )
-    dup node-successor dup [
-        dup node-successor
+    dup successor>> dup [
+        dup successor>>
         [ nip penultimate-node ] [ drop ] if
     ] [
         2drop f
@@ -202,7 +196,7 @@ UNION: #branch #if #dispatch ;
         2dup 2slip rot [
             2drop t
         ] [
-            >r dup node-children swap node-successor suffix r>
+            >r [ children>> ] [ successor>> ] bi suffix r>
             [ node-exists? ] curry contains?
         ] if
     ] [
@@ -213,13 +207,13 @@ GENERIC: calls-label* ( label node -- ? )
 
 M: node calls-label* 2drop f ;
 
-M: #call-label calls-label* node-param eq? ;
+M: #call-label calls-label* param>> eq? ;
 
 : calls-label? ( label node -- ? )
     [ calls-label* ] with node-exists? ;
 
 : recursive-label? ( node -- ? )
-    dup node-param swap calls-label? ;
+    [ param>> ] keep calls-label? ;
 
 SYMBOL: node-stack
 
@@ -227,7 +221,7 @@ SYMBOL: node-stack
 : node> node-stack get pop ;
 : node@ node-stack get peek ;
 
-: iterate-next ( -- node ) node@ node-successor ;
+: iterate-next ( -- node ) node@ successor>> ;
 
 : iterate-nodes ( node quot -- )
     over [
@@ -255,54 +249,55 @@ SYMBOL: node-stack
         ] iterate-nodes drop
     ] with-node-iterator ; inline
 
-: change-children ( node quot -- )
+: map-children ( node quot -- )
     over [
-        >r dup node-children dup r>
-        [ map swap set-node-children ] curry
-        [ 2drop ] if
+        over children>> [
+            [ map ] curry change-children drop
+        ] [
+            2drop
+        ] if
     ] [
         2drop
     ] if ; inline
 
 : (transform-nodes) ( prev node quot -- )
     dup >r call dup [
-        dup rot set-node-successor
-        dup node-successor r> (transform-nodes)
+        >>successor
+        successor>> dup successor>>
+        r> (transform-nodes)
     ] [
-        r> drop f swap set-node-successor drop
+        r> 2drop f >>successor drop
     ] if ; inline
 
 : transform-nodes ( node quot -- new-node )
     over [
-        [ call dup dup node-successor ] keep (transform-nodes)
+        [ call dup dup successor>> ] keep (transform-nodes)
     ] [ drop ] if ; inline
 
 : node-literal? ( node value -- ? )
-    dup value? >r swap node-literals key? r> or ;
+    dup value? >r swap literals>> key? r> or ;
 
 : node-literal ( node value -- obj )
     dup value?
-    [ nip value-literal ] [ swap node-literals at ] if ;
+    [ nip value-literal ] [ swap literals>> at ] if ;
 
 : node-interval ( node value -- interval )
-    swap node-intervals at ;
+    swap intervals>> at ;
 
 : node-class ( node value -- class )
-    swap node-classes at object or ;
+    swap classes>> at object or ;
 
 : node-input-classes ( node -- seq )
-    dup node-in-d [ node-class ] with map ;
+    dup in-d>> [ node-class ] with map ;
 
 : node-input-intervals ( node -- seq )
-    dup node-in-d [ node-interval ] with map ;
+    dup in-d>> [ node-interval ] with map ;
 
 : node-class-first ( node -- class )
-    dup node-in-d first node-class ;
+    dup in-d>> first node-class ;
 
 : active-children ( node -- seq )
-    node-children
-    [ last-node ] map
-    [ #terminate? not ] subset ;
+    children>> [ last-node ] map [ #terminate? not ] subset ;
 
 DEFER: #tail?
 
@@ -317,5 +312,5 @@ UNION: #tail
     #! We don't consider calls which do non-local exits to be
     #! tail calls, because this gives better error traces.
     node-stack get [
-        node-successor dup #tail? swap #terminate? not and
+        successor>> [ #tail? ] [ #terminate? not ] bi and
     ] all? ;
index 4d57ac5883663959a36bc213298b7ffc44aa988b..f565420cacdaecc91d313344f4a84d36ddec6d1d 100644 (file)
@@ -1,15 +1,15 @@
-! Copyright (C) 2006, 2007 Slava Pestov.
+! Copyright (C) 2006, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 IN: inference.errors
 USING: inference.backend inference.dataflow kernel generic
 sequences prettyprint io words arrays inspector effects debugger
-assocs ;
+assocs accessors ;
 
 M: inference-error error.
-    dup inference-error-rstate
+    dup rstate>>
     keys [ dup value? [ value-literal ] when ] map
     dup empty? [ "Word: " write dup peek . ] unless
-    swap delegate error. "Nesting: " write . ;
+    swap error>> error. "Nesting: " write . ;
 
 M: inference-error error-help drop f ;
 
index 68e5920a3dfa55bd053535ebd17fa3dadd9f24a4..e32c94ed371263df9655a1a95b0293cd5205ce35 100755 (executable)
@@ -79,6 +79,18 @@ ARTICLE: "dataflow-graphs" "Inspecting the dataflow graph"
 "The " { $vocab-link "optimizer.debugger" } " tool prints the dataflow graph in human readable form."
 $nl ;
 
+ARTICLE: "inference-errors" "Inference errors"
+"Main wrapper for all inference errors:"
+{ $subsection inference-error }
+"Specific inference errors:"
+{ $subsection no-effect }
+{ $subsection literal-expected }
+{ $subsection too-many->r }
+{ $subsection too-many-r> }
+{ $subsection unbalanced-branches-error }
+{ $subsection effect-error }
+{ $subsection recursive-declare-error } ;
+
 ARTICLE: "inference" "Stack effect inference"
 "The stack effect inference tool is used to check correctness of code before it is run. It is also used by the compiler to build a dataflow graph on which optimizations can be performed. Only words for which a stack effect can be inferred will compile."
 $nl
@@ -93,7 +105,8 @@ $nl
 { $subsection "inference-combinators" }
 { $subsection "inference-branches" }
 { $subsection "inference-recursive" } 
-{ $subsection "inference-limitations" } 
+{ $subsection "inference-limitations" }
+{ $subsection "inference-errors" }
 { $subsection "dataflow-graphs" }
 { $subsection "compiler-transforms" } ;
 
@@ -105,16 +118,7 @@ HELP: inference-error
 { $error-description
     "Thrown by " { $link infer } " and " { $link dataflow } " when the stack effect of a quotation cannot be inferred."
     $nl
-    "This error always delegates to one of the following classes of errors, which indicate the specific issue preventing a stack effect from being inferred:"
-    { $list
-        { $link no-effect }
-        { $link literal-expected }
-        { $link too-many->r }
-        { $link too-many-r> }
-        { $link unbalanced-branches-error }
-        { $link effect-error }
-        { $link recursive-declare-error }
-    }
+    "The " { $snippet "error" } " slot contains one of several possible " { $link "inference-errors" } "."
 } ;
 
 
index 84014512aaf1e5be04b8e2e2fb058029f7c19ff8..f688f60e56da08cc4da4d6f8bb50eac5a8c4b7f9 100755 (executable)
@@ -8,6 +8,9 @@ classes.predicate debugger threads.private io.streams.string
 io.timeouts io.thread sequences.private ;
 IN: inference.tests
 
+[ ] [ [ 1 ] dataflow [ ] transform-nodes drop ] unit-test
+[ ] [ [ 1 2 3 ] dataflow [ ] transform-nodes drop ] unit-test
+
 { 0 2 } [ 2 "Hello" ] must-infer-as
 { 1 2 } [ dup ] must-infer-as
 
@@ -542,3 +545,5 @@ ERROR: custom-error ;
 : missing->r-check >r ;
 
 [ [ missing->r-check ] infer ] must-fail
+
+{ 1 0 } [ [ ] map-children ] must-infer-as
index 5092b86a4d45661b5dc3b168fa256a618965549d..453e2460b0362529e5f7ba7746f2931100d7248d 100755 (executable)
@@ -358,9 +358,7 @@ M: object infer-call
 
 \ (directory) { string } { array } <effect> set-primitive-effect
 
-\ data-gc { } { } <effect> set-primitive-effect
-
-\ code-gc { } { } <effect> set-primitive-effect
+\ gc { } { } <effect> set-primitive-effect
 
 \ gc-time { } { integer } <effect> set-primitive-effect
 
@@ -375,7 +373,7 @@ set-primitive-effect
 \ data-room { } { integer array } <effect> set-primitive-effect
 \ data-room make-flushable
 
-\ code-room { } { integer integer } <effect> set-primitive-effect
+\ code-room { } { integer integer integer integer } <effect> set-primitive-effect
 \ code-room  make-flushable
 
 \ os-env { string } { object } <effect> set-primitive-effect
@@ -589,6 +587,10 @@ set-primitive-effect
 
 \ (os-envs) { } { array } <effect> set-primitive-effect
 
+\ set-os-env { string string } { } <effect> set-primitive-effect
+
+\ unset-os-env { string } { } <effect> set-primitive-effect
+
 \ (set-os-envs) { array } { } <effect> set-primitive-effect
 
 \ do-primitive [ \ do-primitive no-effect ] "infer" set-word-prop
@@ -596,3 +598,5 @@ set-primitive-effect
 \ dll-valid? { object } { object } <effect> set-primitive-effect
 
 \ modify-code-heap { array object } { } <effect> set-primitive-effect
+
+\ unimplemented { } { } <effect> set-primitive-effect
index e98860f25dffed7382c91ad7b291c605ba985dce..7a22107f196862115b5317aef157ea0c20cd4709 100644 (file)
@@ -33,7 +33,7 @@ TUPLE: utf8 ;
         { [ dup -5 shift BIN: 110 number= ] [ double ] }
         { [ dup -4 shift BIN: 1110 number= ] [ triple ] }
         { [ dup -3 shift BIN: 11110 number= ] [ quad ] }
-        { [ t ] [ drop replacement-char ] }
+        [ drop replacement-char ]
     } cond ;
 
 : decode-utf8 ( stream -- char/f )
@@ -59,12 +59,12 @@ M: utf8 decode-char
             2dup -6 shift encoded
             encoded
         ] }
-        { [ t ] [
+        [
             2dup -18 shift BIN: 11110000 bitor swap stream-write1
             2dup -12 shift encoded
             2dup -6 shift encoded
             encoded
-        ] }
+        ]
     } cond ;
 
 M: utf8 encode-char
index 85e17ded46a3c15e009a0ba11403c9ec1050ce4f..0d49e344a86ff9ab8a0651abc98ae58a34278471 100755 (executable)
@@ -7,12 +7,15 @@ ARTICLE: "file-streams" "Reading and writing files"
 { $subsection <file-reader> }
 { $subsection <file-writer> }
 { $subsection <file-appender> }
+"Reading and writing the entire contents of a file; this is only recommended for smaller files:"
+{ $subsection file-contents }
+{ $subsection set-file-contents }
+{ $subsection file-lines }
+{ $subsection set-file-lines }
 "Utility combinators:"
 { $subsection with-file-reader }
 { $subsection with-file-writer }
-{ $subsection with-file-appender }
-{ $subsection file-contents }
-{ $subsection file-lines } ;
+{ $subsection with-file-appender } ;
 
 ARTICLE: "pathnames" "Pathname manipulation"
 "Pathname manipulation:"
@@ -27,15 +30,22 @@ ARTICLE: "pathnames" "Pathname manipulation"
 { $subsection pathname }
 { $subsection <pathname> } ;
 
+ARTICLE: "symbolic-links" "Symbolic links"
+"Reading and creating links:"
+{ $subsection read-link }
+{ $subsection make-link }
+"Copying links:"
+{ $subsection copy-link }
+"Not all operating systems support symbolic links."
+{ $see-also link-info } ;
+
 ARTICLE: "directories" "Directories"
 "Current directory:"
-{ $subsection with-directory }
 { $subsection current-directory }
+{ $subsection set-current-directory }
+{ $subsection with-directory }
 "Home directory:"
 { $subsection home }
-"Current system directory:"
-{ $subsection cwd }
-{ $subsection cd }
 "Directory listing:"
 { $subsection directory }
 { $subsection directory* }
@@ -43,18 +53,26 @@ ARTICLE: "directories" "Directories"
 { $subsection make-directory }
 { $subsection make-directories } ;
 
-! ARTICLE: "file-types" "File Types"
-
-!   { $table { +directory+ "" } }
-
-! ;
-
-ARTICLE: "fs-meta" "File meta-data"
-
+ARTICLE: "file-types" "File Types"
+"Platform-independent types:"
+{ $subsection +regular-file+ }
+{ $subsection +directory+ }
+"Platform-specific types:"
+{ $subsection +character-device+ }
+{ $subsection +block-device+ }
+{ $subsection +fifo+ }
+{ $subsection +symbolic-link+ }
+{ $subsection +socket+ }
+{ $subsection +unknown+ } ;
+
+ARTICLE: "fs-meta" "File metadata"
+"Querying file-system metadata:"
 { $subsection file-info }
 { $subsection link-info }
 { $subsection exists? }
-{ $subsection directory? } ;
+{ $subsection directory? }
+"File types:"
+{ $subsection "file-types" } ;
 
 ARTICLE: "delete-move-copy" "Deleting, moving, copying files"
 "Operations for deleting and copying files come in two forms:"
@@ -94,8 +112,7 @@ ARTICLE: "io.files" "Basic file operations"
 { $subsection "file-streams" }
 { $subsection "fs-meta" }
 { $subsection "directories" }
-{ $subsection "delete-move-copy" }
-{ $see-also "os" } ;
+{ $subsection "delete-move-copy" } ;
 
 ABOUT: "io.files"
 
@@ -123,38 +140,39 @@ HELP: file-name
 ! need a $class-description file-info
 
 HELP: file-info
+{ $values { "path" "a pathname string" } { "info" file-info } }
+{ $description "Queries the file system for metadata. If " { $snippet "path" } " refers to a symbolic link, it is followed. See the article " { $link "file-types" } " for a list of metadata symbols." }
+{ $errors "Throws an error if the file does not exist." } ;
 
-  { $values { "path" "a pathname string" }
-            { "info" file-info } }
-  { $description "Queries the file system for meta data. "
-                 "If path refers to a symbolic link, it is followed."
-                 "If the file does not exist, an exception is thrown." }
+HELP: link-info
+{ $values { "path" "a pathname string" } { "info" "a file-info tuple" } }
+{ $description "Queries the file system for metadata. If path refers to a symbolic link, information about the symbolic link itself is returned. If the file does not exist, an exception is thrown." } ;
 
-  { $class-description "File meta data" }
+{ file-info link-info } related-words
 
-  { $table 
-           { "type" { "One of the following:"
-                      { $list { $link +regular-file+ }
-                              { $link +directory+ }
-                              { $link +symbolic-link+ } } } }
+HELP: +regular-file+
+{ $description "A regular file. This type exists on all platforms. See " { $link "file-streams" } " for words operating on files." } ;
 
-           { "size"     "Size of the file in bytes" }
-           { "modified" "Last modification timestamp." } }
+HELP: +directory+
+{ $description "A directory. This type exists on all platforms. See " { $link "directories" } " for words operating on directories." } ;
 
-  ;
+HELP: +symbolic-link+
+{ $description "A symbolic link file.  This type is currently implemented on Unix platforms only. See " { $link "symbolic-links" } " for words operating on symbolic links." } ;
 
-! need a see also to link-info
+HELP: +character-device+
+{ $description "A Unix character device file. This type exists on unix platforms only." } ;
 
-HELP: link-info
-  { $values { "path" "a pathname string" }
-            { "info" "a file-info tuple" } }
-  { $description "Queries the file system for meta data. "
-                 "If path refers to a symbolic link, information about "
-                 "the symbolic link itself is returned."
-                 "If the file does not exist, an exception is thrown." } ;
-! need a see also to file-info
+HELP: +block-device+
+{ $description "A Unix block device file. This type exists on unix platforms only." } ;
 
-{ file-info link-info } related-words
+HELP: +fifo+
+{ $description "A Unix fifo file. This type exists on unix platforms only." } ;
+
+HELP: +socket+
+{ $description "A Unix socket file. This type exists on unix platforms only." } ;
+
+HELP: +unknown+
+{ $description "A unknown file type." } ;
 
 HELP: <file-reader>
 { $values { "path" "a pathname string" } { "encoding" "an encoding descriptor" { "stream" "an input stream" } }
@@ -187,29 +205,44 @@ HELP: with-file-appender
 { $description "Opens a file for appending using the given encoding and calls the quotation using " { $link with-stream } "." }
 { $errors "Throws an error if the file cannot be opened for writing." } ;
 
+HELP: set-file-lines
+{ $values { "seq" "an array of strings" } { "path" "a pathname string" } { "encoding" "an encoding descriptor" } }
+{ $description "Sets the contents of a file to the strings with the given encoding." }
+{ $errors "Throws an error if the file cannot be opened for writing." } ;
+
 HELP: file-lines
 { $values { "path" "a pathname string" } { "encoding" "an encoding descriptor" } { "seq" "an array of strings" } }
 { $description "Opens the file at the given path using the given encoding, and returns a list of the lines in that file." }
+{ $errors "Throws an error if the file cannot be opened for reading." } ;
+
+HELP: set-file-contents
+{ $values { "str" "a string" } { "path" "a pathname string" } { "encoding" "an encoding descriptor" } }
+{ $description "Sets the contents of a file to a string with the given encoding." }
 { $errors "Throws an error if the file cannot be opened for writing." } ;
 
 HELP: file-contents
 { $values { "path" "a pathname string" } { "encoding" "an encoding descriptor" } { "str" "a string" } }
 { $description "Opens the file at the given path using the given encoding, and the contents of that file as a string." }
-{ $errors "Throws an error if the file cannot be opened for writing." } ;
+{ $errors "Throws an error if the file cannot be opened for reading." } ;
+
+{ set-file-lines file-lines set-file-contents file-contents } related-words
 
 HELP: cwd
 { $values { "path" "a pathname string" } }
 { $description "Outputs the current working directory of the Factor process." }
 { $errors "Windows CE has no concept of ``current directory'', so this word throws an error there." }
-{ $warning "Modifying the current directory through system calls is unsafe.  Use the " { $link with-directory } " word instead." } ;
+{ $notes "User code should use " { $link with-directory } " or " { $link set-current-directory } " instead." } ;
 
 HELP: cd
 { $values { "path" "a pathname string" } }
 { $description "Changes the current working directory of the Factor process." }
 { $errors "Windows CE has no concept of ``current directory'', so this word throws an error there." }
-{ $warning "Modifying the current directory through system calls is unsafe.  Use the " { $link with-directory } " word instead." } ;
+{ $notes "User code should use " { $link with-directory } " or " { $link set-current-directory } " instead." } ;
+
+{ cd cwd current-directory set-current-directory with-directory } related-words
 
-{ cd cwd current-directory with-directory } related-words
+HELP: current-directory
+{ $description "A variable holding the current directory. Words that use the filesystem do so in relation to this variable.  On startup, an init hook sets this word to the directory from which Factor was run." } ;
 
 HELP: with-directory
 { $values { "path" "a pathname string" } { "quot" quotation } }
@@ -219,6 +252,26 @@ HELP: append-path
 { $values { "str1" "a string" } { "str2" "a string" } { "str" "a string" } }
 { $description "Concatenates two pathnames." } ;
 
+HELP: prepend-path
+{ $values { "str1" "a string" } { "str2" "a string" } { "str" "a string" } }
+{ $description "Concatenates two pathnames." } ;
+
+{ append-path prepend-path } related-words
+
+HELP: absolute-path?
+{ $values { "path" "a pathname string" } { "?" "a boolean" } }
+{ $description "Tests if a pathname is absolute. Examples of absolute pathnames are " { $snippet "/foo/bar" } " on Unix and " { $snippet "c:\\foo\\bar" } " on Windows." } ;
+
+HELP: windows-absolute-path?
+{ $values { "path" "a pathname string" } { "?" "a boolean" } }
+{ $description "Tests if a pathname is absolute on Windows. Examples of absolute pathnames on Windows are " { $snippet "c:\\foo\\bar" } " and " { $snippet "\\\\?\\c:\\foo\\bar" } " for absolute Unicode pathnames." } ;
+
+HELP: root-directory?
+{ $values { "path" "a pathname string" } { "?" "a boolean" } }
+{ $description "Tests if a pathname is a root directory. Examples of root directory pathnames are " { $snippet "/" } " on Unix and " { $snippet "c:\\" } " on Windows." } ;
+
+{ absolute-path? windows-absolute-path? root-directory? } related-words
+
 HELP: exists?
 { $values { "path" "a pathname string" } { "?" "a boolean" } }
 { $description "Tests if the file named by " { $snippet "path" } " exists." } ;
@@ -264,6 +317,20 @@ HELP: <pathname> ( str -- pathname )
 { $values { "str" "a pathname string" } { "pathname" pathname } }
 { $description "Creates a new " { $link pathname } "." } ;
 
+HELP: make-link
+{ $values { "target" "a path to the symbolic link's target" } { "symlink" "a path to new symbolic link" } }
+{ $description "Creates a symbolic link." } ;
+
+HELP: read-link
+{ $values { "symlink" "a path to an existing symbolic link" } { "path" "the path pointed to by the symbolic link" } }
+{ $description "Reads the symbolic link and returns its target path." } ;
+
+HELP: copy-link
+{ $values { "target" "a path to an existing symlink" } { "symlink" "a path to a new symbolic link" } }
+{ $description "Copies a symbolic link without following the link." } ;
+
+{ make-link read-link copy-link } related-words
+
 HELP: home
 { $values { "dir" string } }
 { $description "Outputs the user's home directory." } ;
index b4a7d444337949d5970e106fbfee51d20874ce9f..5efbb9496dc95e2276a697608ab33588f3dabf1b 100755 (executable)
@@ -1,7 +1,7 @@
 IN: io.files.tests
-USING: tools.test io.files io threads kernel continuations
-io.encodings.ascii io.files.unique sequences strings accessors
-io.encodings.utf8 ;
+USING: tools.test io.files io.files.private io threads kernel
+continuations io.encodings.ascii io.files.unique sequences
+strings accessors io.encodings.utf8 ;
 
 [ ] [ "blahblah" temp-file dup exists? [ delete-directory ] [ drop ] if ] unit-test
 [ ] [ "blahblah" temp-file make-directory ] unit-test
index 08ec78492a164769f8e6d6b99ec5ad11a17ed30f..061e6386dade88cb13f46e5956198b0db8d58554 100755 (executable)
@@ -95,7 +95,7 @@ ERROR: no-parent-directory path ;
             1 tail left-trim-separators append-path-empty
         ] }
         { [ dup head..? ] [ drop no-parent-directory ] }
-        { [ t ] [ nip ] }
+        [ nip ]
     } cond ;
 
 PRIVATE>
@@ -105,7 +105,7 @@ PRIVATE>
         { [ dup "\\\\?\\" head? ] [ t ] }
         { [ dup length 2 < ] [ f ] }
         { [ dup second CHAR: : = ] [ t ] }
-        { [ t ] [ f ] }
+        [ f ]
     } cond ;
 
 : absolute-path? ( path -- ? )
@@ -114,7 +114,7 @@ PRIVATE>
         { [ dup "resource:" head? ] [ t ] }
         { [ os windows? ] [ windows-absolute-path? ] }
         { [ dup first path-separator? ] [ t ] }
-        { [ t ] [ f ] }
+        [ f ]
     } cond nip ;
 
 : append-path ( str1 str2 -- str )
@@ -130,10 +130,10 @@ PRIVATE>
         { [ over absolute-path? over first path-separator? and ] [
             >r 2 head r> append
         ] }
-        { [ t ] [
+        [
             >r right-trim-separators "/" r>
             left-trim-separators 3append
-        ] }
+        ]
     } cond ;
 
 : prepend-path ( str1 str2 -- str )
@@ -153,19 +153,19 @@ HOOK: file-info io-backend ( path -- info )
 ! Symlinks
 HOOK: link-info io-backend ( path -- info )
 
-HOOK: make-link io-backend ( path1 path2 -- )
+HOOK: make-link io-backend ( target symlink -- )
 
-HOOK: read-link io-backend ( path -- info )
+HOOK: read-link io-backend ( symlink -- path )
 
-: copy-link ( path1 path2 -- )
+: copy-link ( target symlink -- )
     >r read-link r> make-link ;
 
 SYMBOL: +regular-file+
 SYMBOL: +directory+
+SYMBOL: +symbolic-link+
 SYMBOL: +character-device+
 SYMBOL: +block-device+
 SYMBOL: +fifo+
-SYMBOL: +symbolic-link+
 SYMBOL: +socket+
 SYMBOL: +unknown+
 
@@ -205,12 +205,11 @@ SYMBOL: current-directory
 M: object normalize-path ( path -- path' )
     (normalize-path) ;
 
-: with-directory ( path quot -- )
-    >r (normalize-path) r>
-    current-directory swap with-variable ; inline
-
 : set-current-directory ( path -- )
-    normalize-path current-directory set ;
+    (normalize-path) current-directory set ;
+
+: with-directory ( path quot -- )
+    >r (normalize-path) current-directory r> with-variable ; inline
 
 ! Creating directories
 HOOK: make-directory io-backend ( path -- )
@@ -221,10 +220,10 @@ HOOK: make-directory io-backend ( path -- )
         { [ dup root-directory? ] [ ] }
         { [ dup empty? ] [ ] }
         { [ dup exists? ] [ ] }
-        { [ t ] [
+        [
             dup parent-directory make-directories
             dup make-directory
-        ] }
+        ]
     } cond drop ;
 
 ! Directory listings
@@ -323,9 +322,10 @@ C: <pathname> pathname
 M: pathname <=> [ pathname-string ] compare ;
 
 ! Home directory
-: home ( -- dir )
-    {
-        { [ os winnt? ] [ "USERPROFILE" os-env ] }
-        { [ os wince? ] [ "" resource-path ] }
-        { [ os unix? ] [ "HOME" os-env ] }
-    } cond ;
+HOOK: home os ( -- dir )
+
+M: winnt home "USERPROFILE" os-env ;
+
+M: wince home "" resource-path ;
+
+M: unix home "HOME" os-env ;
index fa82c54163dee16c796cd17cd7965c6b633da229..6a956c6694f641a1ab62da6a9935d0624cff3a62 100755 (executable)
@@ -10,7 +10,7 @@ ARTICLE: "io.streams.duplex" "Duplex streams"
 ABOUT: "io.streams.duplex"
 
 HELP: duplex-stream
-{ $class-description "A bidirectional stream delegating to a pair of streams, sending input to one delegate and output to another." } ;
+{ $class-description "A bidirectional stream wrapping an input and output stream." } ;
 
 HELP: <duplex-stream>
 { $values { "in" "an input stream" } { "out" "an output stream" } { "stream" " a duplex stream" } }
index e32c90a2fc8212d282fa363d981f05b13ad9497a..6b8953f86ede8b0eaa18bfc21c4b1441f816688e 100755 (executable)
@@ -1,30 +1,59 @@
 ! Copyright (C) 2006, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-IN: io.streams.nested
 USING: arrays generic assocs kernel namespaces strings
-quotations io continuations ;
+quotations io continuations accessors sequences ;
+IN: io.streams.nested
+
+TUPLE: filter-writer stream ;
+
+M: filter-writer stream-format
+    stream>> stream-format ;
+
+M: filter-writer stream-write
+    stream>> stream-write ;
+
+M: filter-writer stream-write1
+    stream>> stream-write1 ;
+
+M: filter-writer make-span-stream
+    stream>> make-span-stream ;
+
+M: filter-writer make-block-stream
+    stream>> make-block-stream ;
 
-TUPLE: ignore-close-stream ;
+M: filter-writer make-cell-stream
+    stream>> make-cell-stream ;
 
-: <ignore-close-stream> ignore-close-stream construct-delegate ;
+M: filter-writer stream-flush
+    stream>> stream-flush ;
+
+M: filter-writer stream-nl
+    stream>> stream-nl ;
+
+M: filter-writer stream-write-table
+    stream>> stream-write-table ;
+
+M: filter-writer dispose
+    stream>> dispose ;
+
+TUPLE: ignore-close-stream < filter-writer ;
 
 M: ignore-close-stream dispose drop ;
 
-TUPLE: style-stream style ;
+C: <ignore-close-stream> ignore-close-stream
 
-: do-nested-style ( style stream -- style delegate )
-    [ style-stream-style swap union ] keep
-    delegate ; inline
+TUPLE: style-stream < filter-writer style ;
 
-: <style-stream> ( style delegate -- stream )
-    { set-style-stream-style set-delegate }
-    style-stream construct ;
+: do-nested-style ( style style-stream -- style stream )
+    [ style>> swap union ] [ stream>> ] bi ; inline
+
+C: <style-stream> style-stream
 
 M: style-stream stream-format
     do-nested-style stream-format ;
 
 M: style-stream stream-write
-    dup style-stream-style swap delegate stream-format ;
+    [ style>> ] [ stream>> ] bi stream-format ;
 
 M: style-stream stream-write1
     >r 1string r> stream-write ;
@@ -33,15 +62,13 @@ M: style-stream make-span-stream
     do-nested-style make-span-stream ;
 
 M: style-stream make-block-stream
-    [ do-nested-style make-block-stream ] keep
-    style-stream-style swap <style-stream> ;
+    [ do-nested-style make-block-stream ] [ style>> ] bi
+    <style-stream> ;
 
 M: style-stream make-cell-stream
-    [ do-nested-style make-cell-stream ] keep
-    style-stream-style swap <style-stream> ;
-
-TUPLE: block-stream ;
-
-: <block-stream> block-stream construct-delegate ;
+    [ do-nested-style make-cell-stream ] [ style>> ] bi
+    <style-stream> ;
 
-M: block-stream dispose drop ;
+M: style-stream stream-write-table
+    [ [ [ stream>> ] map ] map ] [ ] [ stream>> ] tri*
+    stream-write-table ;
index 4898a58fb1d7eb822e1fcb459c2c7226ce746570..47bff681cd525537c76875ada31beca11fdbf22a 100644 (file)
@@ -12,7 +12,7 @@ M: plain-writer stream-format
     nip stream-write ;
 
 M: plain-writer make-span-stream
-    <style-stream> <ignore-close-stream> ;
+    swap <style-stream> <ignore-close-stream> ;
 
 M: plain-writer make-block-stream
     nip <ignore-close-stream> ;
index 91ac2446088983f597ebc0bda880b485203e2a22..5b09baa56d06e10f37a5543272b9cb45156d4010 100644 (file)
@@ -13,7 +13,7 @@ ABOUT: "io.streams.string"
 
 HELP: <string-writer>
 { $values { "stream" "an output stream" } }
-{ $description "Creates an output stream that collects text into a delegate string buffer. The contents of the buffer can be recovered by executing " { $link >string } ", and indeed all other sequence operations are permitted by virtue of the delegation." } ;
+{ $description "Creates an output stream that collects text into a string buffer. The contents of the buffer can be obtained by executing " { $link >string } "." } ;
 
 HELP: with-string-writer
 { $values { "quot" quotation } { "str" string } }
index 53618d46286d6dbd38e6eedde321153da37c8b2f..4578e2a93fef465045d012d1742021030de3139a 100755 (executable)
@@ -217,9 +217,7 @@ $nl
 { $example "\\ f class ." "word" }
 "On the other hand, " { $link t } " is just a word, and there is no class which it is a unique instance of."
 { $example "t \\ t eq? ." "t" }
-"Many words which search collections confuse the case of no element being present with an element being found equal to " { $link f } ". If this distinction is imporant, there is usually an alternative word which can be used; for example, compare " { $link at } " with " { $link at* } "."
-$nl
-"A tuple cannot delegate to " { $link f } " at all, since a delegate of " { $link f } " actually denotes that no delegate is set. See " { $link set-delegate } "." ;
+"Many words which search collections confuse the case of no element being present with an element being found equal to " { $link f } ". If this distinction is imporant, there is usually an alternative word which can be used; for example, compare " { $link at } " with " { $link at* } "." ;
 
 ARTICLE: "conditionals" "Conditionals and logic"
 "The basic conditionals:"
@@ -276,9 +274,11 @@ ARTICLE: "dataflow" "Data and control flow"
 { $subsection "apply-combinators" }
 { $subsection "slip-keep-combinators" }
 { $subsection "conditionals" }
+{ $subsection "compositional-combinators" }
 { $subsection "combinators" }
 "Advanced topics:"
 { $subsection "implementing-combinators" }
+{ $subsection "errors" }
 { $subsection "continuations" } ;
 
 ABOUT: "dataflow"
@@ -341,6 +341,9 @@ HELP: set-callstack ( cs -- )
 HELP: clear
 { $description "Clears the data stack." } ;
 
+HELP: build
+{ $description "The current build number. Factor increments this number whenever a new boot image is created." } ;
+
 HELP: hashcode*
 { $values { "depth" integer } { "obj" object } { "code" fixnum } }
 { $contract "Outputs the hashcode of an object. The hashcode operation must satisfy the following properties:"
@@ -393,7 +396,7 @@ HELP: identity-tuple
 HELP: <=>
 { $values { "obj1" object } { "obj2" object } { "n" real } }
 { $contract
-    "Compares two objects using an intrinsic partial order, for example, the natural order for real numbers and lexicographic order for strings."
+    "Compares two objects using an intrinsic total order, for example, the natural order for real numbers and lexicographic order for strings."
     $nl
     "The output value is one of the following:"
     { $list
@@ -846,11 +849,15 @@ HELP: with
     { $example "USING: kernel math prettyprint sequences ;" "2 { 1 2 3 } [ - ] with map ." "{ 1 0 -1 }" }
 } ;
 
-HELP: compose
-{ $values { "quot1" callable } { "quot2" callable } { "curry" curry } }
+HELP: compose ( quot1 quot2 -- compose )
+{ $values { "quot1" callable } { "quot2" callable } { "compose" compose } }
 { $description "Quotation composition. Outputs a " { $link callable } " which calls " { $snippet "quot1" } " followed by " { $snippet "quot2" } "." }
 { $notes
-    "The following two lines are equivalent:"
+    "The two quotations must leave the retain stack in the same state on exit as it was on entry, so the following code is not allowed:"
+    { $code
+        "[ 3 >r ] [ r> . ] compose"
+    }
+    "Except for this restriction, the following two lines are equivalent:"
     { $code
         "compose call"
         "append call"
@@ -862,7 +869,15 @@ HELP: 3compose
 { $values { "quot1" callable } { "quot2" callable } { "quot3" callable } { "curry" curry } }
 { $description "Quotation composition. Outputs a " { $link callable } " which calls " { $snippet "quot1" } ", " { $snippet "quot2" } " and then " { $snippet "quot3" } "." }
 { $notes
-    "The following two lines are equivalent:"
+    "The three quotations must leave the retain stack in the same state on exit as it was on entry, so for example, the following code is not allowed:"
+    { $code
+        "[ >r ] swap [ r> ] 3compose"
+    }
+    "The correct way to achieve the effect of the above is the following:"
+    { $code
+        "[ dip ] curry"
+    }
+    "Excepting the retain stack restriction, the following two lines are equivalent:"
     { $code
         "3compose call"
         "3append call"
index 3c40984d7ae6ae411ab234c829f0e70f5e23fcc6..4b129ad59d2596c322239414acbe63aa719ef84b 100755 (executable)
@@ -108,3 +108,12 @@ IN: kernel.tests
     H{ } values swap >r dup length swap r> 0 -roll (loop) ;
 
 [ loop ] must-fail
+
+! Discovered on Windows
+: total-failure-1 "" [ ] map unimplemented ;
+
+[ total-failure-1 ] must-fail
+
+: total-failure-2 [ ] (call) unimplemented ;
+
+[ total-failure-2 ] must-fail
index 1935c89431aa5b619457053c0685bc6e17c4261c..b54d0a7879a8abfe7140a9eaf1bcd6c916d199ee 100755 (executable)
@@ -118,6 +118,8 @@ GENERIC: hashcode* ( depth obj -- code )
 
 M: object hashcode* 2drop 0 ;
 
+M: f hashcode* 2drop 31337 ;
+
 : hashcode ( obj -- code ) 3 swap hashcode* ; inline
 
 GENERIC: equal? ( obj1 obj2 -- ? )
@@ -194,12 +196,8 @@ M: callstack clone (clone) ;
 PRIVATE>
 
 ! Deprecated
-GENERIC: delegate ( obj -- delegate )
-
 M: object delegate drop f ;
 
-GENERIC: set-delegate ( delegate tuple -- )
-
 GENERIC# get-slots 1 ( tuple slots -- ... )
 
 GENERIC# set-slots 1 ( ... tuple slots -- )
index 089465177b8e723ab6e520da36324a5a411b13a8..a54df30c50dfc91cb7958d4f70392cd24435c5af 100755 (executable)
@@ -1,6 +1,6 @@
 USING: generic help.markup help.syntax kernel math
 memory namespaces sequences kernel.private classes
-sequences.private ;
+classes.builtin sequences.private ;
 IN: layouts
 
 HELP: tag-bits
index bf262b77a26be3d0e8b19dbfba122b944da28710..ddb29bb7686ddfa10ae5731b37b763027304f0c7 100755 (executable)
@@ -3,7 +3,7 @@
 USING: arrays hashtables io kernel math math.parser memory
 namespaces parser sequences strings io.styles
 io.streams.duplex vectors words generic system combinators
-continuations debugger definitions compiler.units ;
+continuations debugger definitions compiler.units accessors ;
 IN: listener
 
 SYMBOL: quit-flag
@@ -19,7 +19,7 @@ GENERIC: stream-read-quot ( stream -- quot/f )
 
 : read-quot-step ( lines -- quot/f )
     [ parse-lines-interactive ] [
-        dup delegate unexpected-eof?
+        dup error>> unexpected-eof?
         [ 2drop f ] [ rethrow ] if
     ] recover ;
 
index cc51060f634b9d1436091a76ff59aab854d5c565..4ca1a8637c2eb3fe33b60e9b4ad0106f42151819 100755 (executable)
@@ -103,7 +103,7 @@ C: <interval> interval
             2drop over second over second and
             [ <interval> ] [ 2drop f ] if
         ] }
-        { [ t ] [ 2drop <interval> ] }
+        [ 2drop <interval> ]
     } cond ;
 
 : interval-intersect ( i1 i2 -- i3 )
@@ -202,7 +202,7 @@ SYMBOL: incomparable
         { [ 2dup interval-intersect not ] [ (interval<) ] }
         { [ 2dup left-endpoint-< ] [ f ] }
         { [ 2dup right-endpoint-< ] [ f ] }
-        { [ t ] [ incomparable ] }
+        [ incomparable ]
     } cond 2nip ;
 
 : left-endpoint-<= ( i1 i2 -- ? )
@@ -215,7 +215,7 @@ SYMBOL: incomparable
     {
         { [ 2dup interval-intersect not ] [ (interval<) ] }
         { [ 2dup right-endpoint-<= ] [ t ] }
-        { [ t ] [ incomparable ] }
+        [ incomparable ]
     } cond 2nip ;
 
 : interval> ( i1 i2 -- ? )
index 6ec1c5790ffd2be0e1c96e7ea54123b561518b66..5533c0009001dd6276ead0576fee81e4719f51ec 100755 (executable)
@@ -83,6 +83,29 @@ HELP: >=
 { $values { "x" real } { "y" real } { "?" "a boolean" } }
 { $description "Tests if " { $snippet "x" } " is greater than or equal to " { $snippet "y" } "." } ;
 
+HELP: before?
+{ $values { "obj1" "an object" } { "obj2" "an object" } { "?" "a boolean" } }
+{ $description "Tests if " { $snippet "obj1" } " comes before " { $snippet "obj2" } " using an intrinsic total order." }
+{ $notes "Implemented using " { $link <=> } "." } ;
+
+HELP: after?
+{ $values { "obj1" "an object" } { "obj2" "an object" } { "?" "a boolean" } }
+{ $description "Tests if " { $snippet "obj1" } " comes after " { $snippet "obj2" } " using an intrinsic total order." }
+{ $notes "Implemented using " { $link <=> } "." } ;
+
+HELP: before=?
+{ $values { "obj1" "an object" } { "obj2" "an object" } { "?" "a boolean" } }
+{ $description "Tests if " { $snippet "obj1" } " comes before or equals " { $snippet "obj2" } " using an intrinsic total order." }
+{ $notes "Implemented using " { $link <=> } "." } ;
+
+HELP: after=?
+{ $values { "obj1" "an object" } { "obj2" "an object" } { "?" "a boolean" } }
+{ $description "Tests if " { $snippet "obj1" } " comes after or equals " { $snippet "obj2" } " using an intrinsic total order." }
+{ $notes "Implemented using " { $link <=> } "." } ;
+
+{ before? after? before=? after=? } related-words
+
+
 HELP: +
 { $values { "x" number } { "y" number } { "z" number } }
 { $description
index 68c4768c871acff256b2f7b7e1a261a0874c8cbc..1a1a080564ab1637cbd92e13fde0e0069631ed62 100755 (executable)
@@ -62,7 +62,7 @@ SYMBOL: negative?
     {
         { [ dup empty? ] [ drop f ] }
         { [ f over memq? ] [ drop f ] }
-        { [ t ] [ radix get [ < ] curry all? ] }
+        [ radix get [ < ] curry all? ]
     } cond ;
 
 : string>integer ( str -- n/f )
@@ -77,7 +77,7 @@ PRIVATE>
         {
             { [ CHAR: / over member? ] [ string>ratio ] }
             { [ CHAR: . over member? ] [ string>float ] }
-            { [ t ] [ string>integer ] }
+            [ string>integer ]
         } cond
         r> [ dup [ neg ] when ] when
     ] with-radix ;
@@ -134,10 +134,8 @@ M: ratio >base
         } {
             [ CHAR: . over member? ]
             [ ]
-        } {
-            [ t ]
-            [ ".0" append ]
         }
+        [ ".0" append ]
     } cond ;
 
 M: float >base
@@ -145,7 +143,7 @@ M: float >base
         { [ dup 1.0/0.0 = ] [ drop "1.0/0.0" ] }
         { [ dup -1.0/0.0 = ] [ drop "-1.0/0.0" ] }
         { [ dup fp-nan? ] [ drop "0.0/0.0" ] }
-        { [ t ] [ float>string fix-float ] }
+        [ float>string fix-float ]
     } cond ;
 
 : number>string ( n -- str ) 10 >base ;
index e29844dc89f4c110d6ccc9137f45cf3fd184386a..75876a3c8f1f816697b088a48095a5b481fe06ac 100755 (executable)
@@ -37,12 +37,9 @@ HELP: instances
 { $description "Outputs a sequence of all objects in the heap which satisfy the quotation." }
 { $notes "This word relies on " { $link each-object } ", so in particular the garbage collector is switched off while it runs and the given quotation must not allocate too much memory." } ;
 
-HELP: data-gc ( -- )
+HELP: gc ( -- )
 { $description "Performs a full garbage collection." } ;
 
-HELP: code-gc ( -- )
-{ $description "Collects all generations up to and including tenured space, and also collects the code heap." } ;
-
 HELP: gc-time ( -- n )
 { $values { "n" "a timestamp in milliseconds" } }
 { $description "Outputs the total time spent in garbage collection during this Factor session." } ;
index 8808b30c59bc9ae3a14c8f50caa7ca08788d825a..2b5b1333c01f3f7a40fca7816ba6ae3084eaa837 100755 (executable)
@@ -1,7 +1,15 @@
 USING: generic kernel kernel.private math memory prettyprint
-sequences tools.test words namespaces layouts classes ;
+sequences tools.test words namespaces layouts classes
+classes.builtin arrays quotations ;
 IN: memory.tests
 
+! Code GC wasn't kicking in when needed
+: leak-step 800000 f <array> 1quotation call drop ;
+
+: leak-loop 100 [ leak-step ] times ;
+
+[ ] [ leak-loop ] unit-test
+
 TUPLE: testing x y z ;
 
 [ save-image-and-exit ] must-fail
index a13e1331faac94357fa11cd6efaeb5aeafefb73c..61cdbdad24ffefd20686762038c2a4ae455139d6 100755 (executable)
@@ -42,7 +42,7 @@ M: mirror delete-at ( key mirror -- )
 M: mirror >alist ( mirror -- alist )
     >mirror<
     [ [ slot-spec-offset slot ] with map ] keep
-    [ slot-spec-name ] map swap 2array flip ;
+    [ slot-spec-name ] map swap zip ;
 
 M: mirror assoc-size mirror-slots length ;
 
index 1703bea5d444c4ec8b3d4e8795366e3a267c3622..e6b7533756b4d53d9aeeb59975497c43dc67628f 100755 (executable)
@@ -51,7 +51,7 @@ GENERIC: optimize-node* ( node -- node/t changed? )
 DEFER: optimize-nodes
 
 : optimize-children ( node -- )
-    [ optimize-nodes ] change-children ;
+    [ optimize-nodes ] map-children ;
 
 : optimize-node ( node -- node )
     dup [
index d7638fa66dee93a703f2046c979d25e8034fc96c..ce77cdd43a77d8094263becf6ff4aa53c7fdb9b9 100755 (executable)
@@ -9,23 +9,23 @@ optimizer ;
             { [ over #label? not ] [ 2drop f ] }
             { [ over #label-word over eq? not ] [ 2drop f ] }
             { [ over #label-loop? not ] [ 2drop f ] }
-            { [ t ] [ 2drop t ] }
+            [ 2drop t ]
         } cond
     ] curry node-exists? ;
 
 : label-is-not-loop? ( node word -- ? )
     [
         {
-            { [ over #label? not ] [ 2drop f ] }
-            { [ over #label-word over eq? not ] [ 2drop f ] }
-            { [ over #label-loop? ] [ 2drop f ] }
-            { [ t ] [ 2drop t ] }
-        } cond
+            { [ over #label? not ] [ f ] }
+            { [ over #label-word over eq? not ] [ f ] }
+            { [ over #label-loop? ] [ f ] }
+            [ t ]
+        } cond 2nip
     ] curry node-exists? ;
 
 : loop-test-1 ( a -- )
     dup [ 1+ loop-test-1 ] [ drop ] if ; inline
-
+                          
 [ t ] [
     [ loop-test-1 ] dataflow dup detect-loops
     \ loop-test-1 label-is-loop?
index 11228c879a5795d46863415223caf51c925bd4d8..f9f8901c41f6673b2d953939ed2efbb2dd9c6e9f 100755 (executable)
@@ -156,7 +156,7 @@ SYMBOL: potential-loops
             { [ dup null class< ] [ drop f f ] }
             { [ dup \ f class-not class< ] [ drop t t ] }
             { [ dup \ f class< ] [ drop f t ] }
-            { [ t ] [ drop f f ] }
+            [ drop f f ]
         } cond
     ] if ;
 
index df5c1e0aa46ecea949c5975bd2a6a46ffc9b33ca..54fca38ee22bbbb8b25a008fe589ab8ffd8bb8f0 100755 (executable)
@@ -100,7 +100,7 @@ M: #r> kill-node* [ node-in-r empty? ] prune-if ;
     dup [
         dup [ dead-literals get swap remove-all ] modify-values
         dup kill-node* dup t eq? [
-            drop dup [ kill-nodes ] change-children
+            drop dup [ kill-nodes ] map-children
         ] [
             nip kill-node
         ] if
index 9d41d6eae1ef1e1975391b61848cda8af22d36f8..8447d1be5fe0bc1126ddbbaf8f30d870ba8847e5 100755 (executable)
@@ -36,7 +36,7 @@ DEFER: (flat-length)
         ! not inline
         { [ dup inline? not ] [ drop 1 ] }
         ! inline
-        { [ t ] [ dup dup set word-def (flat-length) ] }
+        [ dup dup set word-def (flat-length) ]
     } cond ;
 
 : (flat-length) ( seq -- n )
@@ -45,7 +45,7 @@ DEFER: (flat-length)
             { [ dup quotation? ] [ (flat-length) 1+ ] }
             { [ dup array? ] [ (flat-length) ] }
             { [ dup word? ] [ word-flat-length ] }
-            { [ t ] [ drop 1 ] }
+            [ drop 1 ]
         } cond
     ] map sum ;
 
@@ -94,7 +94,7 @@ DEFER: (flat-length)
     dup node-param {
         { [ dup standard-generic? ] [ inline-standard-method ] }
         { [ dup math-generic? ] [ inline-math-method ] }
-        { [ t ] [ 2drop t ] }
+        [ 2drop t ]
     } cond ;
 
 ! Resolve type checks at compile time where possible
@@ -217,5 +217,5 @@ M: #call optimize-node*
         { [ dup optimize-predicate? ] [ optimize-predicate ] }
         { [ dup optimistic-inline? ] [ optimistic-inline ] }
         { [ dup method-body-inline? ] [ optimistic-inline ] }
-        { [ t ] [ inline-method ] }
+        [ inline-method ]
     } cond dup not ;
index aa081e8e2cee4654c024d329017effdea72980d9..c8d7a0a0a05e1eb1da82fc75d6dfb7925bc86e0a 100755 (executable)
@@ -140,12 +140,6 @@ GENERIC: void-generic ( obj -- * )
 [ breakage ] must-fail
 
 ! regression
-: test-0 ( n -- ) dup 0 = [ drop ] [ 1- test-0 ] if ; inline
-: test-1 ( n -- ) t [ test-0 ] [ delegate dup [ test-1 ] [ drop ] if ] if ; inline
-: test-2 ( -- ) 5 test-1 ;
-
-[ f ] [ f test-2 ] unit-test
-
 : branch-fold-regression-0 ( m -- n )
     t [ ] [ 1+ branch-fold-regression-0 ] if ; inline
 
@@ -376,4 +370,7 @@ HINTS: recursive-inline-hang-2 array ;
 
 HINTS: recursive-inline-hang-3 array ;
 
+! Regression
+USE: sequences.private
 
+[ ] [ { (3append) } compile ] unit-test
index 0e7e80193855fb0659d820484cf04337bc256b47..5beb2555f0412fe52697036a882c41d38a87f28d 100755 (executable)
@@ -19,7 +19,7 @@ SYMBOL: @
         { [ dup @ eq? ] [ drop match-@ ] }
         { [ dup class? ] [ match-class ] }
         { [ over value? not ] [ 2drop f ] }
-        { [ t ] [ swap value-literal = ] }
+        [ swap value-literal = ]
     } cond ;
 
 : node-match? ( node values pattern -- ? )
index d115d0a1c6d8dd9064713fb5c1ebe3d1ac1d2cc7..b33a9e8fc27440a19553063209fc8ac06ea4a138 100755 (executable)
@@ -57,7 +57,7 @@ IN: optimizer.specializers
             [ dup "specializer" word-prop ]\r
             [ "specializer" word-prop specialize-quot ]\r
         }\r
-        { [ t ] [ drop ] }\r
+        [ drop ]\r
     } cond ;\r
 \r
 : specialized-length ( specializer -- n )\r
index cc4e2c0a4206863bff21ed8823a668b85dfc5f69..e7984f7ec3e05156f50a2792867d912f7d0e6190 100755 (executable)
@@ -1,7 +1,7 @@
 USING: help.markup help.syntax kernel sequences words
 math strings vectors quotations generic effects classes
 vocabs.loader definitions io vocabs source-files
-quotations namespaces compiler.units ;
+quotations namespaces compiler.units assocs ;
 IN: parser
 
 ARTICLE: "vocabulary-search-shadow" "Shadowing word names"
@@ -153,6 +153,8 @@ ARTICLE: "parser-files" "Parsing source files"
 { $subsection parse-file }
 { $subsection bootstrap-file }
 "The parser cross-references source files and definitions. This allows it to keep track of removed definitions, and prevent forward references and accidental redefinitions."
+$nl
+"While the above words are useful for one-off experiments, real programs should be written to use the vocabulary system instead; see " { $link "vocabs.loader" } "."
 { $see-also "source-files" } ;
 
 ARTICLE: "parser-usage" "Reflective parser usage"
@@ -161,6 +163,13 @@ ARTICLE: "parser-usage" "Reflective parser usage"
 "The parser can also parse from a stream:"
 { $subsection parse-stream } ;
 
+ARTICLE: "top-level-forms" "Top level forms"
+"Any code outside of a definition is known as a " { $emphasis "top-level form" } "; top-level forms are run after the entire source file has been parsed, regardless of their position in the file."
+$nl
+"Top-level forms do not have access to the " { $link in } " and " { $link use } " variables that were set at parse time, nor do they run inside " { $link with-compilation-unit } "; so meta-programming might require extra work in a top-level form compared with a parsing word."
+$nl
+"Also, top-level forms run in a new dynamic scope, so using " { $link set } " to store values is almost always wrong, since the values will be lost after the top-level form completes. To save values computed by a top-level form, either use " { $link set-global } " or define a new word with the value." ;
+
 ARTICLE: "parser" "The parser"
 "This parser is a general facility for reading textual representations of objects and definitions. The parser is implemented in the " { $vocab-link "parser" } " and " { $vocab-link "syntax" } " vocabularies."
 $nl
@@ -168,6 +177,7 @@ $nl
 { $subsection "vocabulary-search" }
 { $subsection "parser-files" }
 { $subsection "parser-usage" }
+{ $subsection "top-level-forms" }
 "The parser can be extended."
 { $subsection "parsing-words" }
 { $subsection "parser-lexer" }
@@ -284,10 +294,6 @@ HELP: use
 HELP: in
 { $var-description "A variable holding the name of the current vocabulary for new definitions." } ;
 
-HELP: shadow-warnings
-{ $values { "vocab" "an assoc mapping strings to words" } { "vocabs" "a sequence of assocs" } }
-{ $description "Tests if any keys in " { $snippet "vocab" } " shadow keys in the elements of " { $snippet "vocabs" } ", and if so, prints a warning message. These warning messages can be disabled by setting " { $link parser-notes } " to " { $link f } "." } ;
-
 HELP: (use+)
 { $values { "vocab" "an assoc mapping strings to words" } }
 { $description "Adds an assoc at the front of the search path." }
@@ -445,17 +451,9 @@ HELP: eval
 { $description "Parses Factor source code from a string, and calls the resulting quotation." }
 { $errors "Throws an error if the input is malformed, or if the evaluation itself throws an error." } ;
 
-HELP: outside-usages
-{ $values { "seq" "a sequence of definitions" } { "usages" "an association list mapping definitions to sequences of definitions" } }
-{ $description "Outputs an association list mapping elements of " { $snippet "seq" } " to lists of usages which exclude the definitions in " { $snippet "seq" } " themselves." } ;
-
 HELP: filter-moved
-{ $values { "assoc" "an assoc where the keys are definitions" } { "newassoc" "an assoc where the keys are definitions" } }
-{ $description "Removes all definitions from the assoc which are no longer present in the current " { $link file } "." } ;
-
-HELP: smudged-usage
-{ $values { "usages" "a sequence of definitions which reference removed definitions" } { "referenced" "a sequence of definitions removed from this source file which are still referenced elsewhere" } { "removed" "a sequence of definitions removed from this source file" } }
-{ $description "Collects information about changed word definitioins after parsing." } ;
+{ $values { "assoc1" assoc } { "assoc2" assoc } { "seq" "an seqence of definitions" } }
+{ $description "Removes all definitions from " { $snippet "assoc2" } " which are in " { $snippet "assoc1" } " or are are no longer present in the current " { $link file } "." } ;
 
 HELP: forget-smudged
 { $description "Forgets removed definitions and prints a warning message if any of them are still referenced from other source files." } ;
index 6bd4abb7e106727a0d9b20dd2af8104e7f0bbfc7..ab193e1c0248e3a1096a27b6ccc6085f5392b08a 100755 (executable)
@@ -2,7 +2,7 @@ USING: arrays math parser tools.test kernel generic words
 io.streams.string namespaces classes effects source-files
 assocs sequences strings io.files definitions continuations
 sorting classes.tuple compiler.units debugger vocabs
-vocabs.loader ;
+vocabs.loader accessors ;
 IN: parser.tests
 
 [
@@ -297,12 +297,12 @@ IN: parser.tests
     [
         "IN: parser.tests TUPLE: another-pred-test ; GENERIC: another-pred-test?"
         <string-reader> "removing-the-predicate" parse-stream
-    ] [ [ redefine-error? ] is? ] must-fail-with
+    ] [ error>> error>> redefine-error? ] must-fail-with
 
     [
         "IN: parser.tests TUPLE: class-redef-test ; TUPLE: class-redef-test ;"
         <string-reader> "redefining-a-class-1" parse-stream
-    ] [ [ redefine-error? ] is? ] must-fail-with
+    ] [ error>> error>> redefine-error? ] must-fail-with
 
     [ ] [
         "IN: parser.tests TUPLE: class-redef-test ; SYMBOL: class-redef-test"
@@ -312,7 +312,7 @@ IN: parser.tests
     [
         "IN: parser.tests TUPLE: class-redef-test ; SYMBOL: class-redef-test : class-redef-test ;"
         <string-reader> "redefining-a-class-3" parse-stream drop
-    ] [ [ redefine-error? ] is? ] must-fail-with
+    ] [ error>> error>> redefine-error? ] must-fail-with
 
     [ ] [
         "IN: parser.tests TUPLE: class-fwd-test ;"
@@ -322,7 +322,7 @@ IN: parser.tests
     [
         "IN: parser.tests \\ class-fwd-test"
         <string-reader> "redefining-a-class-3" parse-stream drop
-    ] [ [ no-word-error? ] is? ] must-fail-with
+    ] [ error>> error>> no-word-error? ] must-fail-with
 
     [ ] [
         "IN: parser.tests TUPLE: class-fwd-test ; SYMBOL: class-fwd-test"
@@ -332,12 +332,12 @@ IN: parser.tests
     [
         "IN: parser.tests \\ class-fwd-test"
         <string-reader> "redefining-a-class-3" parse-stream drop
-    ] [ [ no-word-error? ] is? ] must-fail-with
+    ] [ error>> error>> no-word-error? ] must-fail-with
 
     [
         "IN: parser.tests : foo ; TUPLE: foo ;"
         <string-reader> "redefining-a-class-4" parse-stream drop
-    ] [ [ redefine-error? ] is? ] must-fail-with
+    ] [ error>> error>> redefine-error? ] must-fail-with
 
     [ ] [
         "IN: parser.tests : foo ( x y -- z ) 1 2 ; : bar ( a -- b ) ;" eval
@@ -348,47 +348,6 @@ IN: parser.tests
     ] must-fail
 ] with-file-vocabs
 
-[
-    << file get parsed >> file set
-
-    : ~a ;
-
-    DEFER: ~b
-
-    "IN: parser.tests : ~b ~a ;" <string-reader>
-    "smudgy" parse-stream drop
-
-    : ~c ;
-    : ~d ;
-
-    { H{ { ~a ~a } { ~b ~b } { ~c ~c } { ~d ~d } } H{ } } old-definitions set
-    
-    { H{ { ~b ~b } { ~d ~d } } H{ } } new-definitions set
-    
-    [ V{ ~b } { ~a } { ~a ~c } ] [
-        smudged-usage
-        natural-sort
-    ] unit-test
-] with-scope
-
-[
-    << file get parsed >> file set
-
-    GENERIC: ~e
-
-    : ~f ~e ;
-
-    : ~g ;
-
-    { H{ { ~e ~e } { ~f ~f } { ~g ~g } } H{ } } old-definitions set
-    
-    { H{ { ~g ~g } } H{ } } new-definitions set
-
-    [ V{ } { } { ~e ~f } ]
-    [ smudged-usage natural-sort ]
-    unit-test
-] with-scope
-
 [ ] [
     "IN: parser.tests USE: kernel PREDICATE: foo < object ( x -- y ) ;" eval
 ] unit-test
index 902bae29b573d0590bafb68736f33628496d5dc4..1e1d6a56068bd4305fdef8e3e928d53b58ecd7c0 100755 (executable)
@@ -1,12 +1,11 @@
 ! Copyright (C) 2005, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: arrays definitions generic assocs kernel math
-namespaces prettyprint sequences strings vectors words
-quotations inspector io.styles io combinators sorting
-splitting math.parser effects continuations debugger 
-io.files io.streams.string vocabs io.encodings.utf8
-source-files classes hashtables compiler.errors compiler.units
-accessors ;
+USING: arrays definitions generic assocs kernel math namespaces
+prettyprint sequences strings vectors words quotations inspector
+io.styles io combinators sorting splitting math.parser effects
+continuations debugger io.files io.streams.string vocabs
+io.encodings.utf8 source-files classes classes.tuple hashtables
+compiler.errors compiler.units accessors ;
 IN: parser
 
 TUPLE: lexer text line line-text line-length column ;
@@ -157,23 +156,33 @@ name>char-hook global [
         [ swap tail-slice (parse-string) ] "" make swap
     ] change-lexer-column ;
 
-TUPLE: parse-error file line col text ;
+TUPLE: parse-error file line column line-text error ;
 
 : <parse-error> ( msg -- error )
-    file get
-    lexer get [ line>> ] [ column>> ] [ line-text>> ] tri
-    parse-error construct-boa
-    [ set-delegate ] keep ;
+    \ parse-error construct-empty
+        file get >>file
+        lexer get line>> >>line
+        lexer get column>> >>column
+        lexer get line-text>> >>line-text
+        swap >>error ;
 
 : parse-dump ( error -- )
-    dup parse-error-file file.
-    dup parse-error-line number>string print
-    dup parse-error-text dup string? [ print ] [ drop ] if
-    parse-error-col 0 or CHAR: \s <string> write
+    {
+        [ file>> file. ]
+        [ line>> number>string print ]
+        [ line-text>> dup string? [ print ] [ drop ] if ]
+        [ column>> 0 or CHAR: \s <string> write ]
+    } cleave
     "^" print ;
 
 M: parse-error error.
-    dup parse-dump  delegate error. ;
+    [ parse-dump ] [ error>> error. ] bi ;
+
+M: parse-error summary
+    error>> summary ;
+
+M: parse-error compute-restarts
+    error>> compute-restarts ;
 
 SYMBOL: use
 SYMBOL: in
@@ -181,22 +190,8 @@ SYMBOL: in
 : word/vocab% ( word -- )
     "(" % dup word-vocabulary % " " % word-name % ")" % ;
 
-: shadow-warning ( new old -- )
-    2dup eq? [
-        2drop
-    ] [
-        [ word/vocab% " shadowed by " % word/vocab% ] "" make
-        note.
-    ] if ;
-
-: shadow-warnings ( vocab vocabs -- )
-    [
-        swapd assoc-stack dup
-        [ shadow-warning ] [ 2drop ] if
-    ] curry assoc-each ;
-
 : (use+) ( vocab -- )
-    vocab-words use get 2dup shadow-warnings push ;
+    vocab-words use get push ;
 
 : use+ ( vocab -- )
     load-vocab (use+) ;
@@ -289,13 +284,27 @@ M: no-word-error summary
 : CREATE-METHOD ( -- method )
     scan-word bootstrap-word scan-word create-method-in ;
 
+: shadowed-slots ( superclass slots -- shadowed )
+    >r all-slot-names r> seq-intersect ;
+
+: check-slot-shadowing ( class superclass slots -- )
+    shadowed-slots [
+        [
+            "Definition of slot ``" %
+            %
+            "'' in class ``" %
+            word-name %
+            "'' shadows a superclass slot" %
+        ] "" make note.
+    ] with each ;
+
 : parse-tuple-definition ( -- class superclass slots )
     CREATE-CLASS
     scan {
         { ";" [ tuple f ] }
         { "<" [ scan-word ";" parse-tokens ] }
         [ >r tuple ";" parse-tokens r> prefix ]
-    } case ;
+    } case 3dup check-slot-shadowing ;
 
 ERROR: staging-violation word ;
 
@@ -315,7 +324,7 @@ M: staging-violation summary
         { [ dup not ] [ drop unexpected-eof t ] }
         { [ dup delimiter? ] [ unexpected t ] }
         { [ dup parsing? ] [ nip execute-parsing t ] }
-        { [ t ] [ pick push drop t ] }
+        [ pick push drop t ]
     } cond ;
 
 : (parse-until) ( accum end -- accum )
@@ -409,6 +418,7 @@ SYMBOL: bootstrap-syntax
 SYMBOL: interactive-vocabs
 
 {
+    "accessors"
     "arrays"
     "assocs"
     "combinators"
@@ -464,19 +474,6 @@ SYMBOL: interactive-vocabs
         "Loading " write <pathname> . flush
     ] if ;
 
-: smudged-usage-warning ( usages removed -- )
-    parser-notes? [
-        "Warning: the following definitions were removed from sources," print
-        "but are still referenced from other definitions:" print
-        nl
-        dup sorted-definitions.
-        nl
-        "The following definitions need to be updated:" print
-        nl
-        over sorted-definitions.
-        nl
-    ] when 2drop ;
-
 : filter-moved ( assoc1 assoc2 -- seq )
     diff [
         drop where dup [ first ] when
@@ -491,32 +488,22 @@ SYMBOL: interactive-vocabs
     new-definitions old-definitions
     [ get second ] bi@ ;
 
-: smudged-usage ( -- usages referenced removed )
-    removed-definitions filter-moved [
-        outside-usages
-        [
-            empty? [ drop f ] [
-                {
-                    { [ dup pathname? ] [ f ] }
-                    { [ dup method-body? ] [ f ] }
-                    { [ t ] [ t ] }
-                } cond nip
-            ] if
-        ] assoc-subset
-        dup values concat prune swap keys
-    ] keep ;
+: forget-removed-definitions ( -- )
+    removed-definitions filter-moved forget-all ;
+
+: reset-removed-classes ( -- )
+    removed-classes
+    filter-moved [ class? ] subset [ reset-class ] each ;
 
 : fix-class-words ( -- )
     #! If a class word had a compound definition which was
     #! removed, it must go back to being a symbol.
     new-definitions get first2
-    filter-moved [ [ reset-generic ] [ define-symbol ] bi ] each
-    removed-classes
-    filter-moved [ class? ] subset [ reset-class ] each ;
+    filter-moved [ [ reset-generic ] [ define-symbol ] bi ] each ;
 
 : forget-smudged ( -- )
-    smudged-usage forget-all
-    over empty? [ 2dup smudged-usage-warning ] unless 2drop
+    forget-removed-definitions
+    reset-removed-classes
     fix-class-words ;
 
 : finish-parsing ( lines quot -- )
index f197ac7966a598eeae4ee5d79982ce902ddac863..1a2fd69949acb2a2b422346797b5a8f45ca67c70 100644 (file)
@@ -4,12 +4,6 @@ IN: prettyprint.config
 
 ABOUT: "prettyprint-variables"
 
-HELP: indent
-{ $var-description "The prettyprinter's current indent level." } ;
-
-HELP: pprinter-stack
-{ $var-description "A stack of " { $link block } " objects currently being constructed by the prettyprinter." } ;
-
 HELP: tab-size
 { $var-description "Prettyprinter tab size. Indent nesting is always a multiple of the tab size." } ;
 
index 7ea0f5c412c2f08c30ab7e04bcfa7541635b541b..2b294115beb6cce230d735065ecb16152efb7263 100755 (executable)
@@ -48,7 +48,7 @@ ARTICLE: "prettyprint-limitations" "Prettyprinter limitations"
 "On a final note, the " { $link short. } " and " { $link pprint-short } " words restrict the length and nesting of printed sequences, their output will very likely not be valid syntax. They are only intended for interactive use." ;
 
 ARTICLE: "prettyprint-section-protocol" "Prettyprinter section protocol"
-"Prettyprinter sections must delegate to an instance of " { $link section } ", and they must also obey a protocol."
+"Prettyprinter sections must subclass " { $link section } ", and they must also obey a protocol."
 $nl
 "Layout queries:"
 { $subsection section-fits? }
@@ -60,8 +60,8 @@ $nl
 { $subsection short-section }
 { $subsection long-section }
 "Utilities to use when implementing sections:"
-{ $subsection <section> }
-{ $subsection delegate>block }
+{ $subsection construct-section }
+{ $subsection construct-block }
 { $subsection add-section } ;
 
 ARTICLE: "prettyprint-sections" "Prettyprinter sections"
index 0f384b159d05e42057ad2c7e0f6a6013fb337116..e94670992c67c5c6b1354de70f4aa3e95e3dede0 100755 (executable)
@@ -333,3 +333,6 @@ PREDICATE: predicate-see-test < integer even? ;
 [ "USING: math ;\nIN: prettyprint.tests\nPREDICATE: predicate-see-test < integer even? ;\n" ] [
     [ \ predicate-see-test see ] with-string-writer
 ] unit-test
+
+[ ] [ \ compose see ] unit-test
+[ ] [ \ curry see ] unit-test
index fd7133053a5d3228a70126126839f2f35157c61c..e1a53696af86995699db913f34ad043b8f6f7911 100755 (executable)
@@ -5,9 +5,9 @@ USING: alien arrays generic generic.standard assocs io kernel
 math namespaces sequences strings io.styles io.streams.string
 vectors words prettyprint.backend prettyprint.sections
 prettyprint.config sorting splitting math.parser vocabs
-definitions effects classes.tuple io.files classes continuations
-hashtables classes.mixin classes.union classes.predicate
-classes.singleton combinators quotations ;
+definitions effects classes.builtin classes.tuple io.files
+classes continuations hashtables classes.mixin classes.union
+classes.predicate classes.singleton combinators quotations ;
 
 : make-pprint ( obj quot -- block in use )
     [
@@ -107,7 +107,7 @@ SYMBOL: ->
                 { [ dup word? not ] [ , ] }
                 { [ dup "break?" word-prop ] [ drop ] }
                 { [ dup "step-into?" word-prop ] [ remove-step-into ] }
-                { [ t ] [ , ] }
+                [ , ]
             } cond
         ] each
     ] [ ] make ;
index 9833a7e50ae6426c3bf17f4acde9ba7aa4538a5b..bb1752b72ef73c7a43e2c7aad0c889d52c01f0d8 100755 (executable)
@@ -1,22 +1,14 @@
 USING: prettyprint io kernel help.markup help.syntax
-prettyprint.sections prettyprint.config words hashtables math
+prettyprint.config words hashtables math
 strings definitions ;
+IN: prettyprint.sections
 
 HELP: position
 { $var-description "The prettyprinter's current character position." } ;
 
-HELP: last-newline
-{ $var-description "The character position of the last newline output by the prettyprinter." } ;
-
 HELP: recursion-check
 { $var-description "The current nesting of collections being output by the prettyprinter, used to detect circularity and prevent infinite recursion." } ;
 
-HELP: line-count
-{ $var-description "The number of lines output by the prettyprinter so far, used for line limiting (see " { $link line-limit } ")." } ;
-
-HELP: end-printing
-{ $var-description "A continuation captured by " { $link do-pprint } " that breaks out of the printer." } ;
-
 HELP: line-limit?
 { $values { "?" "a boolean" } }
 { $description "Tests if the line number limit has been reached, and thus if prettyprinting should stop." } ;
@@ -67,7 +59,7 @@ HELP: short-section?
 { $contract "Tests if a section should be output as a " { $link short-section } ". The default implementation calls " { $link section-fits? } " but this behavior can be cutomized." } ;
 
 HELP: section
-{ $class-description "A piece of prettyprinter output. Instances of this class are not used directly, instead one instantiates various classes which delegate to this class:"
+{ $class-description "A piece of prettyprinter output. Instances of this class are not used directly, instead one instantiates various subclasses of this class:"
 { $list
     { $link text }
     { $link line-break }
@@ -78,22 +70,18 @@ HELP: section
 }
 "Instances of this class have the following slots:"
 { $list
-    { { $link section-start } " - the start of the section, measured in characters from the beginning of the prettyprinted output" }
-    { { $link section-end } " - the end of the section, measured in characters from the beginning of the prettyprinted output" }
-    { { $link section-start-group? } " - see " { $link start-group } }
-    { { $link section-end } " - see " { $link end-group } }
-    { { $link section-style } " - character and/or paragraph styles to use when outputting this section. See " { $link "styles" } }
-    { { $link section-overhang } " - number of columns which must be left blank before the wrap margin for the prettyprinter to consider emitting this section as a " { $link short-section } ". Avoids lone hanging closing brackets" }
+    { { $snippet "start" } " - the start of the section, measured in characters from the beginning of the prettyprinted output" }
+    { { $snippet "end" } " - the end of the section, measured in characters from the beginning of the prettyprinted output" }
+    { { $snippet "start-group?" } " - see " { $link start-group } }
+    { { $snippet "end-group?" } " - see " { $link end-group } }
+    { { $snippet "style" } " - character and/or paragraph styles to use when outputting this section. See " { $link "styles" } }
+    { { $snippet "overhang" } " - number of columns which must be left blank before the wrap margin for the prettyprinter to consider emitting this section as a " { $link short-section } ". Avoids lone hanging closing brackets" }
 } } ;
 
-HELP: <section>
-{ $values { "style" hashtable } { "length" integer } { "section" section } }
+HELP: construct-section
+{ $values { "length" integer } { "class" "a subclass of " { $link section } } { "section" section } }
 { $description "Creates a new section with the given length starting from " { $link position } ", advancing " { $link position } "." } ;
 
-HELP: change-indent
-{ $values { "section" section } { "n" integer } }
-{ $description "If the section requests indentation, adds " { $snippet "n" } " to the indent level, otherwise does nothing." } ;
-
 HELP: <indent
 { $values { "section" section } }
 { $description "Increases indentation by the " { $link tab-size } " if requested by the section." } ;
index 9574d18eb17543b9b749e3871534cc18408a34ba..848947e624da55321f2baed19d920243fb3c7a19 100644 (file)
@@ -1,9 +1,9 @@
-! Copyright (C) 2003, 2007 Slava Pestov.
+! Copyright (C) 2003, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien arrays generic hashtables io kernel math assocs
 namespaces sequences strings io.styles vectors words
 prettyprint.config splitting classes continuations
-io.streams.nested ;
+io.streams.nested accessors ;
 IN: prettyprint.sections
 
 ! State
@@ -11,37 +11,38 @@ SYMBOL: position
 SYMBOL: recursion-check
 SYMBOL: pprinter-stack
 
-SYMBOL: last-newline
-SYMBOL: line-count
-SYMBOL: end-printing
-SYMBOL: indent
-
 ! We record vocabs of all words
 SYMBOL: pprinter-in
 SYMBOL: pprinter-use
 
+TUPLE: pprinter last-newline line-count end-printing indent ;
+
+: <pprinter> ( -- pprinter ) 0 1 f 0 pprinter construct-boa ;
+
 : record-vocab ( word -- )
     word-vocabulary [ dup pprinter-use get set-at ] when* ;
 
 ! Utility words
 : line-limit? ( -- ? )
-    line-limit get dup [ line-count get <= ] when ;
+    line-limit get dup [ pprinter get line-count>> <= ] when ;
 
-: do-indent ( -- ) indent get CHAR: \s <string> write ;
+: do-indent ( -- ) pprinter get indent>> CHAR: \s <string> write ;
 
 : fresh-line ( n -- )
-    dup last-newline get = [
+    dup pprinter get last-newline>> = [
         drop
     ] [
-        last-newline set
-        line-limit? [ "..." write end-printing get continue ] when
-        line-count inc
+        pprinter get (>>last-newline)
+        line-limit? [
+            "..." write pprinter get end-printing>> continue
+        ] when
+        pprinter get [ 1+ ] change-line-count drop
         nl do-indent
     ] if ;
 
 : text-fits? ( len -- ? )
     margin get dup zero?
-    [ 2drop t ] [ >r indent get + r> <= ] if ;
+    [ 2drop t ] [ >r pprinter get indent>> + r> <= ] if ;
 
 ! break only if position margin 2 / >
 SYMBOL: soft
@@ -70,17 +71,17 @@ start end
 start-group? end-group?
 style overhang ;
 
-: <section> ( style length -- section )
-    position [ dup rot + dup ] change 0 {
-        set-section-style
-        set-section-start
-        set-section-end
-        set-section-overhang
-    } section construct ;
+: construct-section ( length class -- section )
+    construct-empty
+        position get >>start
+        swap position [ + ] change
+        position get >>end
+        0 >>overhang ; inline
 
 M: section section-fits? ( section -- ? )
-    dup section-end last-newline get -
-    swap section-overhang + text-fits? ;
+    [ end>> pprinter get last-newline>> - ]
+    [ overhang>> ] bi
+    + text-fits? ;
 
 M: section indent-section? drop f ;
 
@@ -90,18 +91,20 @@ M: section newline-after? drop f ;
 
 M: object short-section? section-fits? ;
 
-: change-indent ( section n -- )
-    swap indent-section? [ indent +@ ] [ drop ] if ;
+: indent+ ( section n -- )
+    swap indent-section? [
+        pprinter get [ + ] change-indent drop
+    ] [ drop ] if ;
 
-: <indent ( section -- ) tab-size get change-indent ;
+: <indent ( section -- ) tab-size get indent+ ;
 
-: indent> ( section -- ) tab-size get neg change-indent ;
+: indent> ( section -- ) tab-size get neg indent+ ;
 
 : <fresh-line ( section -- )
-    section-start fresh-line ;
+    start>> fresh-line ;
 
 : fresh-line> ( section -- )
-    dup newline-after? [ section-end fresh-line ] [ drop ] if ;
+    dup newline-after? [ end>> fresh-line ] [ drop ] if ;
 
 : <long-section ( section -- )
     dup unindent-first-line?
@@ -110,67 +113,65 @@ M: object short-section? section-fits? ;
 : long-section> ( section -- )
     dup indent> fresh-line> ;
 
-: with-style* ( style quot -- )
-    swap stdio [ <style-stream> ] change
-    call stdio [ delegate ] change ; inline
-
 : pprint-section ( section -- )
     dup short-section? [
-        dup section-style [ short-section ] with-style*
+        dup section-style [ short-section ] with-style
     ] [
-        dup <long-section
-        dup section-style [ dup long-section ] with-style*
-        long-section>
+        [ <long-section ]
+        [ dup section-style [ long-section ] with-style ]
+        [ long-section> ]
+        tri
     ] if ;
 
 ! Break section
-TUPLE: line-break type ;
+TUPLE: line-break < section type ;
 
 : <line-break> ( type -- section )
-    H{ } 0 <section>
-    { set-line-break-type set-delegate }
-    \ line-break construct ;
+    0 \ line-break construct-section
+        swap >>type ;
 
 M: line-break short-section drop ;
 
 M: line-break long-section drop ;
 
 ! Block sections
-TUPLE: block sections ;
+TUPLE: block < section sections ;
 
-: <block> ( style -- block )
-    0 <section> V{ } clone
-    { set-delegate set-block-sections } block construct ;
+: construct-block ( style class -- block )
+    0 swap construct-section
+        V{ } clone >>sections
+        swap >>style ; inline
 
-: delegate>block ( obj -- ) H{ } <block> swap set-delegate ;
+: <block> ( style -- block )
+    block construct-block ;
 
 : pprinter-block ( -- block ) pprinter-stack get peek ;
 
 : add-section ( section -- )
-    pprinter-block block-sections push ;
+    pprinter-block sections>> push ;
 
 : last-section ( -- section )
-    pprinter-block block-sections
+    pprinter-block sections>>
     [ line-break? not ] find-last nip ;
 
 : start-group ( -- )
-    t last-section set-section-start-group? ;
+    last-section t >>start-group? drop ;
 
 : end-group ( -- )
-    t last-section set-section-end-group? ;
+    last-section t >>end-group? drop ;
 
 : advance ( section -- )
-    dup section-start last-newline get = not
-    swap short-section? and
-    [ bl ] when ;
+    [ start>> pprinter get last-newline>> = not ]
+    [ short-section? ] bi
+    and [ bl ] when ;
 
 : line-break ( type -- ) [ <line-break> add-section ] when* ;
 
 M: block section-fits? ( section -- ? )
-    line-limit? [ drop t ] [ delegate section-fits? ] if ;
+    line-limit? [ drop t ] [ call-next-method ] if ;
 
 : pprint-sections ( block advancer -- )
-    swap block-sections [ line-break? not ] subset
+    swap sections>> [ line-break? not ] subset
     unclip pprint-section [
         dup rot call pprint-section
     ] with each ; inline
@@ -179,28 +180,29 @@ M: block short-section ( block -- )
     [ advance ] pprint-sections ;
 
 : do-break ( break -- )
-    dup line-break-type hard eq?
-    over section-end last-newline get - margin get 2/ > or
-    [ <fresh-line ] [ drop ] if ;
+    [ ]
+    [ type>> hard eq? ]
+    [ end>> pprinter get last-newline>> - margin get 2/ > ] tri
+    or [ <fresh-line ] [ drop ] if ;
 
-: empty-block? ( block -- ? ) block-sections empty? ;
+: empty-block? ( block -- ? ) sections>> empty? ;
 
 : if-nonempty ( block quot -- )
     >r dup empty-block? [ drop ] r> if ; inline
 
 : (<block) pprinter-stack get push ;
 
-: <block H{ } <block> (<block) ;
+: <block f <block> (<block) ;
 
 : <object ( obj -- ) presented associate <block> (<block) ;
 
 ! Text section
-TUPLE: text string ;
+TUPLE: text < section string ;
 
 : <text> ( string style -- text )
-    over length 1+ <section>
-    { set-text-string set-delegate }
-    \ text construct ;
+    over length 1+ \ text construct-section
+        swap >>style
+        swap >>string ;
 
 M: text short-section text-string write ;
 
@@ -211,18 +213,18 @@ M: text long-section short-section ;
 : text ( string -- ) H{ } styled-text ;
 
 ! Inset section
-TUPLE: inset narrow? ;
+TUPLE: inset < block narrow? ;
 
 : <inset> ( narrow? -- block )
-    2 H{ } <block>
-    { set-inset-narrow? set-section-overhang set-delegate }
-    inset construct ;
+    H{ } inset construct-block
+        2 >>overhang
+        swap >>narrow? ;
 
 M: inset long-section
-    dup inset-narrow? [
+    dup narrow?>> [
         [ <fresh-line ] pprint-sections
     ] [
-        delegate long-section
+        call-next-method
     ] if ;
 
 M: inset indent-section? drop t ;
@@ -232,25 +234,26 @@ M: inset newline-after? drop t ;
 : <inset ( narrow? -- ) <inset> (<block) ;
 
 ! Flow section
-TUPLE: flow ;
+TUPLE: flow < block ;
 
 : <flow> ( -- block )
-    H{ } <block> flow construct-delegate ;
+    H{ } flow construct-block ;
 
 M: flow short-section? ( section -- ? )
     #! If we can make room for this entire block by inserting
     #! a newline, do it; otherwise, don't bother, print it as
     #! a short section
-    dup section-fits?
-    over section-end rot section-start - text-fits? not or ;
+    [ section-fits? ]
+    [ [ end>> ] [ start>> ] bi - text-fits? not ] bi
+    or ;
 
 : <flow ( -- ) <flow> (<block) ;
 
 ! Colon definition section
-TUPLE: colon ;
+TUPLE: colon < block ;
 
 : <colon> ( -- block )
-    H{ } <block> colon construct-delegate ;
+    H{ } colon construct-block ;
 
 M: colon long-section short-section ;
 
@@ -261,28 +264,23 @@ M: colon unindent-first-line? drop t ;
 : <colon ( -- ) <colon> (<block) ;
 
 : save-end-position ( block -- )
-    position get swap set-section-end ;
+    position get >>end drop ;
 
 : block> ( -- )
     pprinter-stack get pop
-    [ dup save-end-position add-section ] if-nonempty ;
-
-: with-section-state ( quot -- )
-    [
-        0 indent set
-        0 last-newline set
-        1 line-count set
-        call
-    ] with-scope ; inline
+    [ [ save-end-position ] [ add-section ] bi ] if-nonempty ;
 
 : do-pprint ( block -- )
-    [
+    <pprinter> pprinter [
         [
-            dup section-style [
-                [ end-printing set dup short-section ] callcc0
-            ] with-nesting drop
+            dup style>> [
+                [
+                    >r pprinter get (>>end-printing) r>
+                    short-section
+                ] curry callcc0
+            ] with-nesting
         ] if-nonempty
-    ] with-section-state ;
+    ] with-variable ;
 
 ! Long section layout algorithm
 : chop-break ( seq -- seq )
@@ -298,9 +296,9 @@ M: f section-start-group? drop t ;
 M: f section-end-group? drop f ;
 
 : split-before ( section -- )
-    dup section-start-group? prev get section-end-group? and
-    swap flow? prev get flow? not and
-    or split-groups ;
+    [ section-start-group? prev get section-end-group? and ]
+    [ flow? prev get flow? not and ]
+    bi or split-groups ;
 
 : split-after ( section -- )
     section-end-group? split-groups ;
@@ -315,19 +313,19 @@ M: f section-end-group? drop f ;
     ] { } make { t } split [ empty? not ] subset ;
 
 : break-group? ( seq -- ? )
-    dup first section-fits? swap peek section-fits? not and ;
+    [ first section-fits? ] [ peek section-fits? not ] bi and ;
 
 : ?break-group ( seq -- )
     dup break-group? [ first <fresh-line ] [ drop ] if ;
 
 M: block long-section ( block -- )
     [
-        block-sections chop-break group-flow [
+        sections>> chop-break group-flow [
             dup ?break-group [
                 dup line-break? [
                     do-break
                 ] [
-                    dup advance pprint-section
+                    [ advance ] [ pprint-section ] bi
                 ] if
             ] each
         ] each
diff --git a/core/refs/refs-tests.factor b/core/refs/refs-tests.factor
new file mode 100644 (file)
index 0000000..1d92185
--- /dev/null
@@ -0,0 +1,22 @@
+USING: refs tools.test kernel ;
+
+[ 3 ] [
+    H{ { "a" 3 } } "a" <value-ref> get-ref
+] unit-test
+
+[ 4 ] [
+    4 H{ { "a" 3 } } clone "a" <value-ref>
+    [ set-ref ] keep
+    get-ref
+] unit-test
+
+[ "a" ] [
+    H{ { "a" 3 } } "a" <key-ref> get-ref
+] unit-test
+
+[ H{ { "b" 3 } } ] [
+    "b" H{ { "a" 3 } } clone [
+        "a" <key-ref>
+        set-ref
+    ] keep
+] unit-test
index c52c5daf9e77d72116e137ca47788eec419cc4bc..81a2338b8ffb477ddc4e3c89b19affba181c26d2 100644 (file)
@@ -5,21 +5,18 @@ IN: refs
 
 TUPLE: ref assoc key ;
 
-: <ref> ( assoc key class -- tuple )
-    >r ref construct-boa r> construct-delegate ; inline
-
-: >ref< ( ref -- key assoc ) [ key>> ] [ assoc>> ] bi ;
+: >ref< [ key>> ] [ assoc>> ] bi ; inline
 
 : delete-ref ( ref -- ) >ref< delete-at ;
 GENERIC: get-ref ( ref -- obj )
 GENERIC: set-ref ( obj ref -- )
 
-TUPLE: key-ref ;
-: <key-ref> ( assoc key -- ref ) key-ref <ref> ;
-M: key-ref get-ref ref-key ;
+TUPLE: key-ref < ref ;
+C: <key-ref> key-ref ( assoc key -- ref )
+M: key-ref get-ref key>> ;
 M: key-ref set-ref >ref< rename-at ;
 
-TUPLE: value-ref ;
-: <value-ref> ( assoc key -- ref ) value-ref <ref> ;
+TUPLE: value-ref < ref ;
+C: <value-ref> value-ref ( assoc key -- ref )
 M: value-ref get-ref >ref< at ;
 M: value-ref set-ref >ref< set-at ;
index 3a30824084ff985c20ef3de4e3374a56d26fb427..281b27d540665992e0d3c3442d6476628ecb921c 100755 (executable)
@@ -1,6 +1,6 @@
 USING: arrays kernel math namespaces sequences kernel.private
 sequences.private strings sbufs tools.test vectors bit-arrays
-generic ;
+generic vocabs.loader ;
 IN: sequences.tests
 
 [ V{ 1 2 3 4 } ] [ 1 5 dup <slice> >vector ] unit-test
@@ -100,6 +100,16 @@ unit-test
 [ [ ] ] [ [ 1 2 3 ] 3 tail ] unit-test
 [ [ 3 ] ] [ [ 1 2 3 ] 2 tail ] unit-test
 
+[ "blah" ] [ "blahxx" 2 head* ] unit-test
+
+[ "xx" ] [ "blahxx" 2 tail* ] unit-test
+
+[ t ] [ "xxfoo" 2 head-slice "xxbar" 2 head-slice = ] unit-test
+[ t ] [ "xxfoo" 2 head-slice "xxbar" 2 head-slice [ hashcode ] bi@ = ] unit-test
+
+[ t ] [ "xxfoo" 2 head-slice SBUF" barxx" 2 tail-slice* = ] unit-test
+[ t ] [ "xxfoo" 2 head-slice SBUF" barxx" 2 tail-slice* [ hashcode ] bi@ = ] unit-test
+
 [ t ] [ [ 1 2 3 ] [ 1 2 3 ] sequence= ] unit-test
 [ t ] [ [ 1 2 3 ] { 1 2 3 } sequence= ] unit-test
 [ t ] [ { 1 2 3 } [ 1 2 3 ] sequence= ] unit-test
@@ -195,6 +205,12 @@ unit-test
 ! Pathological case
 [ "ihbye" ] [ "hi" <reversed> "bye" append ] unit-test
 
+[ t ] [ "hi" <reversed> SBUF" hi" <reversed> = ] unit-test
+
+[ t ] [ "hi" <reversed> SBUF" hi" <reversed> = ] unit-test
+
+[ t ] [ "hi" <reversed> SBUF" hi" <reversed> [ hashcode ] bi@ = ] unit-test
+
 [ -10 "hi" "bye" copy ] must-fail
 [ 10 "hi" "bye" copy ] must-fail
 
@@ -244,3 +260,5 @@ unit-test
 [ "asdf " ] [ " asdf " [ CHAR: \s = ] left-trim ] unit-test
 [ " asdf" ] [ " asdf " [ CHAR: \s = ] right-trim ] unit-test
 
+! Hardcore
+[ ] [ "sequences" reload ] unit-test
index 01a1cb9b6a22262564504fc050de5e4d81b99dc7..996aba8e6e1a6ae2bafac9992b62ba2e5e3f710e 100755 (executable)
@@ -172,7 +172,9 @@ TUPLE: reversed seq ;
 C: <reversed> reversed
 
 M: reversed virtual-seq reversed-seq ;
+
 M: reversed virtual@ reversed-seq [ length swap - 1- ] keep ;
+
 M: reversed length reversed-seq length ;
 
 INSTANCE: reversed virtual-sequence
@@ -198,7 +200,9 @@ ERROR: slice-error reason ;
     slice construct-boa ; inline
 
 M: slice virtual-seq slice-seq ;
+
 M: slice virtual@ [ slice-from + ] keep slice-seq ;
+
 M: slice length dup slice-to swap slice-from - ;
 
 : head-slice ( seq n -- slice ) (head) <slice> ;
@@ -466,6 +470,21 @@ M: sequence <=>
     2dup [ length ] bi@ number=
     [ mismatch not ] [ 2drop f ] if ; inline
 
+: sequence-hashcode-step ( oldhash newpart -- newhash )
+    swap [
+        dup -2 fixnum-shift-fast swap 5 fixnum-shift-fast
+        fixnum+fast fixnum+fast
+    ] keep fixnum-bitxor ; inline
+
+: sequence-hashcode ( n seq -- x )
+    0 -rot [
+        hashcode* >fixnum sequence-hashcode-step
+    ] with each ; inline
+
+M: reversed equal? over reversed? [ sequence= ] [ 2drop f ] if ;
+
+M: slice equal? over slice? [ sequence= ] [ 2drop f ] if ;
+
 : move ( to from seq -- )
     2over number=
     [ 3drop ] [ [ nth swap ] keep set-nth ] if ; inline
@@ -692,14 +711,3 @@ PRIVATE>
         dup [ length ] map infimum
         [ <column> dup like ] with map
     ] unless ;
-
-: sequence-hashcode-step ( oldhash newpart -- newhash )
-    swap [
-        dup -2 fixnum-shift-fast swap 5 fixnum-shift-fast
-        fixnum+fast fixnum+fast
-    ] keep fixnum-bitxor ; inline
-
-: sequence-hashcode ( n seq -- x )
-    0 -rot [
-        hashcode* >fixnum sequence-hashcode-step
-    ] with each ; inline
index 2b0d721f3e87c87ca424fa5c2a555bf3760d19b7..29facb31f286512429de8c2f8a5d36812f05a03f 100755 (executable)
@@ -1,7 +1,7 @@
 USING: help.markup help.syntax generic kernel.private parser
 words kernel quotations namespaces sequences words arrays
-effects generic.standard classes.tuple slots.private classes
-strings math ;
+effects generic.standard classes.tuple classes.builtin
+slots.private classes strings math ;
 IN: slots
 
 ARTICLE: "accessors" "Slot accessors"
index 8dea367b6b48be1351e2d6bb0c5a89b614ee4c23..b385fbf369522c65a2e37a126be1b7669452f156 100755 (executable)
@@ -4,7 +4,7 @@ USING: arrays definitions generic assocs kernel math namespaces
 prettyprint sequences strings vectors words quotations inspector
 io.styles io combinators sorting splitting math.parser effects
 continuations debugger io.files io.crc32 vocabs hashtables
-graphs compiler.units io.encodings.utf8 ;
+graphs compiler.units io.encodings.utf8 accessors ;
 IN: source-files
 
 SYMBOL: source-files
@@ -56,10 +56,14 @@ uses definitions ;
 M: pathname where pathname-string 1 2array ;
 
 : forget-source ( path -- )
-    dup source-file
-    dup unxref-source
-    source-file-definitions [ keys forget-all ] each
-    source-files get delete-at ;
+    [
+        source-file
+        [ unxref-source ]
+        [ definitions>> [ keys forget-all ] each ]
+        bi
+    ]
+    [ source-files get delete-at ]
+    bi ;
 
 M: pathname forget*
     pathname-string forget-source ;
@@ -78,9 +82,3 @@ SYMBOL: file
         source-file-definitions old-definitions set
         [ ] [ file get rollback-source-file ] cleanup
     ] with-scope ; inline
-
-: outside-usages ( seq -- usages )
-    dup [
-        over usage
-        [ dup pathname? not swap where and ] subset seq-diff
-    ] curry { } map>assoc ;
index b242e65de52fbd2536fa1ee80edb2a2b0db04db4..61e77ae9a5d3e426280b40ca8dafc2dffe105f93 100755 (executable)
@@ -1,6 +1,7 @@
 USING: generic help.syntax help.markup kernel math parser words
 effects classes generic.standard classes.tuple generic.math
-arrays io.files vocabs.loader io sequences assocs ;
+generic.standard arrays io.files vocabs.loader io sequences
+assocs ;
 IN: syntax
 
 ARTICLE: "parser-algorithm" "Parser algorithm"
@@ -332,8 +333,8 @@ HELP: C{
 { $description "Parses a complex number given in rectangular form as a pair of real numbers. Literal complex numbers are terminated by " { $link POSTPONE: } } "." }  ;
 
 HELP: T{
-{ $syntax "T{ class delegate slots... }" }
-{ $values { "class" "a tuple class word" } { "delegate" "a delegate" } { "slots" "list of objects" } }
+{ $syntax "T{ class slots... }" }
+{ $values { "class" "a tuple class word" } { "slots" "list of objects" } }
 { $description "Marks the beginning of a literal tuple. Literal tuples are terminated by " { $link POSTPONE: } } "."
 $nl
 "The class word must always be specified. If an insufficient number of values is given after the class word, the remaining slots of the tuple are set to " { $link f } ". If too many values are given, they are ignored." } ;
@@ -564,9 +565,17 @@ HELP: TUPLE:
 HELP: ERROR:
 { $syntax "ERROR: class slots... ;" }
 { $values { "class" "a new tuple class to define" } { "slots" "a list of slot names" } }
-{ $description "Defines a new tuple class.  Defines a new word " { $snippet "class?" } " that boa-constructs this tuple and throws it." } ;
-
-{ POSTPONE: ERROR: POSTPONE: TUPLE: } related-words
+{ $description "Defines a new tuple class whose class word throws a new instance of the error." }
+{ $notes
+    "The following two snippets are equivalent:"
+    { $code
+        "ERROR: invalid-values x y ;"
+        ""
+        "TUPLE: invalid-values x y ;"
+        ": invalid-values ( x y -- * )"
+        "    \\ invalid-values construct-boa throw ;"
+    }
+} ;
 
 HELP: C:
 { $syntax "C: constructor class" }
@@ -633,4 +642,18 @@ HELP: >>
 { $syntax ">>" }
 { $description "Marks the end of a parse time code block." } ;
 
+HELP: call-next-method
+{ $description "Calls the next applicable method. Only valid inside a method definition. The values at the top of the stack are passed on to the next method, and they must be compatible with that method's class specializer." }
+{ $notes "This is syntax sugar around " { $link (call-next-method) } ". The following two lines are equivalent:"
+    { $code
+        "M: my-class my-generic ... call-next-method ... ;"
+        "M: my-class my-generic ... \\ my-class \\ my-generic (call-next-method) ... ;"
+    }
+"In most cases, this word should be called with the original input values on the stack. Calling it with other values is usually a sign of poor design." }
+{ $errors
+    "Throws a " { $link no-next-method } " error if this is the least specific method, and throws an " { $link inconsistent-next-method } " error if the values at the top of the stack are not compatible with the current method's specializer."
+} ;
+
+{ POSTPONE: call-next-method (call-next-method) next-method } related-words
+
 { POSTPONE: << POSTPONE: >> } related-words
index 005672c1c62e46239d32bfb224decb33b8e01531..0c759265e9006e6a44cc1fed25799e3e2bf057cd 100755 (executable)
@@ -61,7 +61,7 @@ IN: bootstrap.syntax
         scan {
             { [ dup length 1 = ] [ first ] }
             { [ "\\" ?head ] [ next-escape drop ] }
-            { [ t ] [ name>char-hook get call ] }
+            [ name>char-hook get call ]
         } cond parsed
     ] define-syntax
 
index df112bd78674d19dec1d6e2dca3ebeec4805db12..d0b2cfb194193c00331c1f1db1c193391da75a28 100755 (executable)
@@ -7,9 +7,7 @@ ABOUT: "system"
 ARTICLE: "system" "System interface"
 { $subsection "cpu" }
 { $subsection "os" }
-"Reading environment variables:"
-{ $subsection os-env }
-{ $subsection os-envs }
+{ $subsection "environment-variables" }
 "Getting the path to the Factor VM and image:"
 { $subsection vm }
 { $subsection image }
@@ -19,7 +17,16 @@ ARTICLE: "system" "System interface"
 { $subsection exit }
 { $see-also "io.files" "io.mmap" "io.monitors" "network-streams" "io.launcher" } ;
 
-ARTICLE: "cpu" "Processor Detection"
+ARTICLE: "environment-variables" "Environment variables"
+"Reading environment variables:"
+{ $subsection os-env }
+{ $subsection os-envs }
+"Writing environment variables:"
+{ $subsection set-os-env }
+{ $subsection unset-os-env }
+{ $subsection set-os-envs } ;
+
+ARTICLE: "cpu" "Processor detection"
 "Processor detection:"
 { $subsection cpu }
 "Supported processors:"
@@ -30,7 +37,7 @@ ARTICLE: "cpu" "Processor Detection"
 "Processor families:"
 { $subsection x86 } ;
 
-ARTICLE: "os" "Operating System Detection"
+ARTICLE: "os" "Operating system detection"
 "Operating system detection:"
 { $subsection os }
 "Supported operating systems:"
@@ -98,7 +105,23 @@ HELP: set-os-envs
 }
 { $errors "Windows CE has no concept of environment variables, so this word throws an error there." } ;
 
-{ os-env os-envs set-os-envs } related-words
+HELP: set-os-env ( value key -- )
+{ $values { "value" string } { "key" string } }
+{ $description "Set an environment variable." }
+{ $notes
+    "Names and values of environment variables are operating system-specific."
+}
+{ $errors "Windows CE has no concept of environment variables, so this word throws an error there." } ;
+
+HELP: unset-os-env ( key -- )
+{ $values { "key" string } }
+{ $description "Unset an environment variable." }
+{ $notes
+    "Names and values of environment variables are operating system-specific."
+}
+{ $errors "Windows CE has no concept of environment variables, so this word throws an error there." } ;
+
+{ os-env os-envs set-os-env unset-os-env set-os-envs } related-words
 
 HELP: image
 { $values { "path" "a pathname string" } }
index 14e34ccb1787c9c9c0cb805355af449582eca3cb..d5a48080c25369ec1b6f2354a126c33dad228a7b 100755 (executable)
@@ -12,3 +12,10 @@ os unix? [
     [ ] [ "envs" get set-os-envs ] unit-test
     [ t ] [ os-envs "envs" get = ] unit-test
 ] when
+
+[ ] [ "factor-test-key-1" unset-os-env ] unit-test
+[ ] [ "ps3" "factor-test-key-1" set-os-env ] unit-test
+[ "ps3" ] [ "factor-test-key-1" os-env ] unit-test
+[ ] [ "factor-test-key-1" unset-os-env ] unit-test
+[ f ] [ "factor-test-key-1" os-env ] unit-test
+
index d7d7988893e06df8bc443488014fc8334eba7cf1..8623255cd23d6df44eb89779ebe87f5a478d94c8 100755 (executable)
@@ -4,7 +4,7 @@
 IN: threads
 USING: arrays hashtables heaps kernel kernel.private math
 namespaces sequences vectors continuations continuations.private
-dlists assocs system combinators init boxes ;
+dlists assocs system combinators init boxes accessors ;
 
 SYMBOL: initial-thread
 
@@ -18,11 +18,10 @@ mailbox variables sleep-entry ;
 
 ! Thread-local storage
 : tnamespace ( -- assoc )
-    self dup thread-variables
-    [ ] [ H{ } clone dup rot set-thread-variables ] ?if ;
+    self variables>> [ H{ } clone dup self (>>variables) ] unless* ;
 
 : tget ( key -- value )
-    self thread-variables at ;
+    self variables>> at ;
 
 : tset ( value key -- )
     tnamespace set-at ;
@@ -35,7 +34,7 @@ mailbox variables sleep-entry ;
 : thread ( id -- thread ) threads at ;
 
 : thread-registered? ( thread -- ? )
-    thread-id threads key? ;
+    id>> threads key? ;
 
 : check-unregistered
     dup thread-registered?
@@ -48,59 +47,58 @@ mailbox variables sleep-entry ;
 <PRIVATE
 
 : register-thread ( thread -- )
-    check-unregistered dup thread-id threads set-at ;
+    check-unregistered dup id>> threads set-at ;
 
 : unregister-thread ( thread -- )
-    check-registered thread-id threads delete-at ;
+    check-registered id>> threads delete-at ;
 
 : set-self ( thread -- ) 40 setenv ; inline
 
 PRIVATE>
 
 : <thread> ( quot name -- thread )
-    \ thread counter <box> [ ] {
-        set-thread-quot
-        set-thread-name
-        set-thread-id
-        set-thread-continuation
-        set-thread-exit-handler
-    } \ thread construct ;
+    \ thread construct-empty
+        swap >>name
+        swap >>quot
+        \ thread counter >>id
+        <box> >>continuation
+        [ ] >>exit-handler ;
 
 : run-queue 42 getenv ;
 
 : sleep-queue 43 getenv ;
 
 : resume ( thread -- )
-    f over set-thread-state
+    f >>state
     check-registered run-queue push-front ;
 
 : resume-now ( thread -- )
-    f over set-thread-state
+    f >>state
     check-registered run-queue push-back ;
 
 : resume-with ( obj thread -- )
-    f over set-thread-state
+    f >>state
     check-registered 2array run-queue push-front ;
 
 : sleep-time ( -- ms/f )
     {
         { [ run-queue dlist-empty? not ] [ 0 ] }
         { [ sleep-queue heap-empty? ] [ f ] }
-        { [ t ] [ sleep-queue heap-peek nip millis [-] ] }
+        [ sleep-queue heap-peek nip millis [-] ]
     } cond ;
 
 <PRIVATE
 
 : schedule-sleep ( thread ms -- )
     >r check-registered dup r> sleep-queue heap-push*
-    swap set-thread-sleep-entry ;
+    >>sleep-entry drop ;
 
 : expire-sleep? ( heap -- ? )
     dup heap-empty?
     [ drop f ] [ heap-peek nip millis <= ] if ;
 
 : expire-sleep ( thread -- )
-    f over set-thread-sleep-entry resume ;
+    f >>sleep-entry resume ;
 
 : expire-sleep-loop ( -- )
     sleep-queue
@@ -123,21 +121,21 @@ PRIVATE>
     ] [
         pop-back
         dup array? [ first2 ] [ f swap ] if dup set-self
-        f over set-thread-state
-        thread-continuation box>
+        f >>state
+        continuation>> box>
         continue-with
     ] if ;
 
 PRIVATE>
 
 : stop ( -- )
-    self dup thread-exit-handler call
+    self dup exit-handler>> call
     unregister-thread next ;
 
 : suspend ( quot state -- obj )
     [
-        self thread-continuation >box
-        self set-thread-state
+        self continuation>> >box
+        self (>>state)
         self swap call next
     ] callcc1 2nip ; inline
 
@@ -157,9 +155,9 @@ M: real sleep
     millis + >integer sleep-until ;
 
 : interrupt ( thread -- )
-    dup thread-state [
-        dup thread-sleep-entry [ sleep-queue heap-delete ] when*
-        f over set-thread-sleep-entry
+    dup state>> [
+        dup sleep-entry>> [ sleep-queue heap-delete ] when*
+        f >>sleep-entry
         dup resume
     ] when drop ;
 
@@ -171,7 +169,7 @@ M: real sleep
             V{ } set-catchstack
             { } set-retainstack
             >r { } set-datastack r>
-            thread-quot [ call stop ] call-clear
+            quot>> [ call stop ] call-clear
         ] 1 (throw)
     ] "spawn" suspend 2drop ;
 
@@ -196,8 +194,8 @@ GENERIC: error-in-thread ( error thread -- )
     <min-heap> 43 setenv
     initial-thread global
     [ drop f "Initial" <thread> ] cache
-    <box> over set-thread-continuation
-    f over set-thread-state
+    <box> >>continuation
+    f >>state
     dup register-thread
     set-self ;
 
index 4b978932bc58cb010caac6d4654071019edb9308..45b0d6b0191f4c69b6b6a9eac184f12ba5c998c1 100755 (executable)
@@ -3,7 +3,7 @@ IN: vocabs.loader.tests
 USING: vocabs.loader tools.test continuations vocabs math
 kernel arrays sequences namespaces io.streams.string
 parser source-files words assocs classes.tuple definitions
-debugger compiler.units tools.vocabs ;
+debugger compiler.units tools.vocabs accessors ;
 
 ! This vocab should not exist, but just in case...
 [ ] [
@@ -68,7 +68,7 @@ IN: vocabs.loader.tests
     <string-reader>
     "resource:core/vocabs/loader/test/a/a.factor"
     parse-stream
-] [ [ no-word-error? ] is? ] must-fail-with
+] [ error>> error>> no-word-error? ] must-fail-with
 
 0 "count-me" set-global
 
@@ -110,6 +110,8 @@ IN: vocabs.loader.tests
     ] with-compilation-unit
 ] unit-test
 
+[ ] [ "vocabs.loader.test.b" changed-vocab ] unit-test
+
 [ ] [ "vocabs.loader.test.b" refresh ] unit-test
 
 [ 3 ] [ "count-me" get-global ] unit-test
index a715aab64f7ee4430503dd519667645ad47d020d..f259378f7e72ef24cc4894e4f53a102ead1b8a5a 100755 (executable)
@@ -284,7 +284,7 @@ HELP: <word>
 
 HELP: gensym
 { $values { "word" word } }
-{ $description "Creates an uninterned word that is not equal to any other word in the system. Gensyms have an automatically-generated name based on a prefix and an incrementing counter." }
+{ $description "Creates an uninterned word that is not equal to any other word in the system." }
 { $examples { $unchecked-example "gensym ." "G:260561" } }
 { $notes "Gensyms are often used as placeholder values that have no meaning of their own but must be unique. For example, the compiler uses gensyms to label sections of code." } ;
 
index cef6b1994389e82a7db13e75b6baff8bb623836f..694e54cf96102236826e1ceb6f6f939f3f55d2dd 100755 (executable)
@@ -1,7 +1,7 @@
 USING: arrays generic assocs kernel math namespaces
 sequences tools.test words definitions parser quotations
 vocabs continuations classes.tuple compiler.units
-io.streams.string ;
+io.streams.string accessors ;
 IN: words.tests
 
 [ 4 ] [
@@ -147,7 +147,7 @@ SYMBOL: quot-uses-b
 ] when*
 
 [ "IN: words.tests : undef-test ; << undef-test >>" eval ]
-[ [ undefined? ] is? ] must-fail-with
+[ error>> undefined? ] must-fail-with
 
 [ ] [
     "IN: words.tests GENERIC: symbol-generic" eval
index 059815e95203a4117501bec36e3bb06b68d2667e..e1d2f11356dcbd96d3649dcac34b39ec44a0c560 100755 (executable)
@@ -2,8 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays definitions graphs assocs kernel kernel.private
 slots.private math namespaces sequences strings vectors sbufs
-quotations assocs hashtables sorting math.parser words.private
-vocabs combinators ;
+quotations assocs hashtables sorting words.private vocabs ;
 IN: words
 
 : word ( -- word ) \ word get-global ;
@@ -66,11 +65,11 @@ SYMBOL: bootstrapping?
 GENERIC: crossref? ( word -- ? )
 
 M: word crossref?
-    {
-        { [ dup "forgotten" word-prop ] [ f ] }
-        { [ dup word-vocabulary ] [ t ] }
-        { [ t ] [ f ] }
-    } cond nip ;
+    dup "forgotten" word-prop [
+        drop f
+    ] [
+        word-vocabulary >boolean
+    ] if ;
 
 GENERIC# (quot-uses) 1 ( obj assoc -- )
 
@@ -121,22 +120,35 @@ SYMBOL: +called+
         compiled-usage [ nip +inlined+ eq? ] assoc-subset update
     ] with each keys ;
 
-M: word redefined* ( word -- )
-    { "inferred-effect" "no-effect" } reset-props ;
+<PRIVATE
 
-SYMBOL: changed-words
+SYMBOL: visited
 
-: changed-word ( word -- )
-    dup changed-words get
-    [ no-compilation-unit ] unless*
-    set-at ;
+: reset-on-redefine { "inferred-effect" "no-effect" } ; inline
+
+: (redefined) ( word -- )
+    dup visited get key? [ drop ] [
+        [ reset-on-redefine reset-props ]
+        [ dup visited get set-at ]
+        [
+            crossref get at keys [ word? ] subset [
+                reset-on-redefine [ word-prop ] with contains?
+            ] subset
+            [ (redefined) ] each
+        ] tri
+    ] if ;
+
+PRIVATE>
+
+: redefined ( word -- )
+    H{ } clone visited [ (redefined) ] with-variable ;
 
 : define ( word def -- )
     [ ] like
     over unxref
     over redefined
     over set-word-def
-    dup changed-word
+    dup changed-definition
     dup crossref? [ dup xref ] when drop ;
 
 : define-declared ( word def effect -- )
@@ -178,7 +190,7 @@ M: word subwords drop f ;
     { "methods" "combination" "default-method" } reset-props ;
 
 : gensym ( -- word )
-    "G:" \ gensym counter number>string append f <word> ;
+    "( gensym )" f <word> ;
 
 : define-temp ( quot -- word )
     gensym dup rot define ;
index b23ee1f83000c8163fe338e17536e4e17c49e92f..92fb9aac81211ac2241a922b61aa6f1bacaad08d 100755 (executable)
@@ -37,9 +37,6 @@ IN: assocs.lib
 
 : insert ( value variable -- ) namespace insert-at ;
 
-: 2seq>assoc ( keys values exemplar -- assoc )
-    >r 2array flip r> assoc-like ;
-
 : generate-key ( assoc -- str )
     >r 256 random-bits >hex r>
     2dup key? [ nip generate-key ] [ drop ] if ;
index fa0c54d0c62809eea5dedc408994f76b2c205a10..782cf16e9e68db15745e605214da77d23bf532f7 100755 (executable)
@@ -9,6 +9,7 @@ namespaces random ;
     { [ os unix? ] [ "random.unix" require ] }
 } cond
 
-! [ [ 32 random-bits ] with-secure-random <mersenne-twister> random-generator set-global ]
-[ millis <mersenne-twister> random-generator set-global ]
-"generator.random" add-init-hook
+[
+    [ 32 random-bits ] with-secure-random
+    <mersenne-twister> random-generator set-global
+] "generator.random" add-init-hook
diff --git a/extra/bubble-chamber/bubble-chamber.factor b/extra/bubble-chamber/bubble-chamber.factor
new file mode 100644 (file)
index 0000000..4b0db46
--- /dev/null
@@ -0,0 +1,88 @@
+
+USING: kernel namespaces sequences random math math.constants math.libm vars
+       ui
+       processing
+       processing.gadget
+       bubble-chamber.common
+       bubble-chamber.particle
+       bubble-chamber.particle.muon
+       bubble-chamber.particle.quark
+       bubble-chamber.particle.hadron
+       bubble-chamber.particle.axion ;
+
+IN: bubble-chamber
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+VARS: particles muons quarks hadrons axions ;
+
+VAR: boom
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: collide-all ( -- )
+
+  2 pi * 1random >collision-theta
+
+  particles> [ collide ] each ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: collide-one ( -- )
+
+  dim 2 / mouse-x - dim 2 / mouse-y - fatan2 >collision-theta
+
+  hadrons> random collide
+  quarks>  random collide
+  muons>   random collide ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: mouse-pressed ( -- )
+  boom on
+  1 background ! kludge
+  11 [ drop collide-one ] each ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: key-released ( -- )
+  key " " =
+    [
+      boom on
+      1 background
+      collide-all
+    ]
+  when ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: bubble-chamber ( -- )
+
+  1000 1000 size*
+
+  [
+    1 background
+    no-stroke
+  
+    1789 [ drop <muon>   ] map >muons
+    1300 [ drop <quark>  ] map >quarks
+    1000 [ drop <hadron> ] map >hadrons
+    111  [ drop <axion>  ] map >axions
+
+    muons> quarks> hadrons> axions> 3append append >particles
+
+    collide-one
+  ] setup
+
+  [
+    boom>
+      [ particles> [ move ] each ]
+    when
+  ] draw
+
+  [ mouse-pressed ] button-down
+  [ key-released  ] key-up ;
+
+: go ( -- ) [ bubble-chamber run ] with-ui ;
+
+MAIN: go
\ No newline at end of file
diff --git a/extra/bubble-chamber/common/common.factor b/extra/bubble-chamber/common/common.factor
new file mode 100644 (file)
index 0000000..c9ce687
--- /dev/null
@@ -0,0 +1,12 @@
+
+USING: kernel math accessors combinators.cleave vars ;
+
+IN: bubble-chamber.common
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+VAR: collision-theta
+
+: dim ( -- dim ) 1000 ;
+
+: center ( -- point ) dim 2 / dup {2} ; foldable
diff --git a/extra/bubble-chamber/particle/axion/axion.factor b/extra/bubble-chamber/particle/axion/axion.factor
new file mode 100644 (file)
index 0000000..9e9bf99
--- /dev/null
@@ -0,0 +1,67 @@
+
+USING: kernel sequences random accessors multi-methods
+       math math.constants math.ranges math.points combinators.cleave
+       processing bubble-chamber.common bubble-chamber.particle ;
+
+IN: bubble-chamber.particle.axion
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+TUPLE: axion < particle ;
+
+: <axion> ( -- axion ) axion construct-empty initialize-particle ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+METHOD: collide { axion }
+
+  center              >>pos
+  2 pi *      1random >>theta
+  1.0   6.0   2random >>speed
+  0.998 1.000 2random >>speed-d
+  0                   >>theta-d
+  0                   >>theta-dd
+
+  [ 0.00001 theta-dd-small? ] [ -0.001 0.001 random-theta-dd ] [ ] while
+
+  drop ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: dy>alpha ( dy -- alpha ) neg 6 * 30 + 255.0 / ;
+
+: axion-white ( dy -- dy ) dup 1 swap dy>alpha {2} stroke ;
+: axion-black ( dy -- dy ) dup 0 swap dy>alpha {2} stroke ;
+
+: axion-point- ( particle dy -- particle ) >r dup pos>> r> v-y point ;
+: axion-point+ ( particle dy -- particle ) >r dup pos>> r> v+y point ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+METHOD: move { axion }
+
+  { 0.06 0.59 } stroke
+  dup pos>>  point
+
+  1 4 [a,b] [ axion-white axion-point- ] each
+  1 4 [a,b] [ axion-black axion-point+ ] each
+
+  dup vel>> move-by
+
+  turn
+
+  step-theta
+  step-theta-d
+  step-speed-mul
+
+  [ ] [ speed-d>> 0.9999 * ] bi >>speed-d
+
+  1000 random 996 >
+    [
+      dup speed>>   neg     >>speed
+      dup speed-d>> neg 2 + >>speed-d
+
+      100 random 30 > [ collide ] [ drop ] if
+    ]
+    [ drop ]
+  if ;
diff --git a/extra/bubble-chamber/particle/hadron/hadron.factor b/extra/bubble-chamber/particle/hadron/hadron.factor
new file mode 100644 (file)
index 0000000..2994577
--- /dev/null
@@ -0,0 +1,60 @@
+
+USING: kernel random math math.constants math.points accessors multi-methods
+       processing
+       processing.color
+       bubble-chamber.common
+       bubble-chamber.particle ;
+
+IN: bubble-chamber.particle.hadron
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+TUPLE: hadron < particle ;
+
+: <hadron> ( -- hadron ) hadron construct-empty initialize-particle ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+METHOD: collide { hadron }
+
+  center              >>pos
+  2 pi *      1random >>theta
+  0.5   3.5   2random >>speed
+  0.996 1.001 2random >>speed-d
+  0                   >>theta-d
+  0                   >>theta-dd
+
+  [ 0.00001 theta-dd-small? ] [ -0.001 0.001 random-theta-dd ] [ ] while
+
+  0 1 0 <rgb> >>myc
+
+  drop ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+METHOD: move { hadron }
+
+  { 1 0.11 } stroke
+  dup pos>> 1 v-y point
+  
+  { 0 0.11 } stroke
+  dup pos>> 1 v+y point
+
+  dup vel>> move-by
+
+  turn
+
+  step-theta
+  step-theta-d
+  step-speed-mul
+
+  1000 random 997 >
+    [
+      1.0     >>speed-d
+      0.00001 >>theta-dd
+
+      100 random 70 > [ dup collide ] when
+    ]
+  when
+
+  out-of-bounds? [ collide ] [ drop ] if ;
diff --git a/extra/bubble-chamber/particle/muon/colors/colors.factor b/extra/bubble-chamber/particle/muon/colors/colors.factor
new file mode 100644 (file)
index 0000000..ab72f65
--- /dev/null
@@ -0,0 +1,53 @@
+
+USING: kernel sequences math math.constants accessors
+       processing
+       processing.color ;
+
+IN: bubble-chamber.particle.muon.colors
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: good-colors ( -- seq )
+  {
+    T{ rgba f 0.23 0.14 0.17 1 }
+    T{ rgba f 0.23 0.14 0.15 1 }
+    T{ rgba f 0.21 0.14 0.15 1 }
+    T{ rgba f 0.51 0.39 0.33 1 }
+    T{ rgba f 0.49 0.33 0.20 1 }
+    T{ rgba f 0.55 0.45 0.32 1 }
+    T{ rgba f 0.69 0.63 0.51 1 }
+    T{ rgba f 0.64 0.39 0.18 1 }
+    T{ rgba f 0.73 0.42 0.20 1 }
+    T{ rgba f 0.71 0.45 0.29 1 }
+    T{ rgba f 0.79 0.45 0.22 1 }
+    T{ rgba f 0.82 0.56 0.34 1 }
+    T{ rgba f 0.88 0.72 0.49 1 }
+    T{ rgba f 0.85 0.69 0.40 1 }
+    T{ rgba f 0.96 0.92 0.75 1 }
+    T{ rgba f 0.99 0.98 0.87 1 }
+    T{ rgba f 0.85 0.82 0.69 1 }
+    T{ rgba f 0.99 0.98 0.87 1 }
+    T{ rgba f 0.82 0.82 0.79 1 }
+    T{ rgba f 0.65 0.69 0.67 1 }
+    T{ rgba f 0.53 0.60 0.55 1 }
+    T{ rgba f 0.57 0.53 0.68 1 }
+    T{ rgba f 0.47 0.42 0.56 1 }
+  } ;
+
+: anti-colors ( -- seq ) good-colors <reversed> ; 
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: color-fraction ( particle -- particle fraction ) dup theta>> pi + 2 pi * / ;
+
+: set-good-color ( particle -- particle )
+  color-fraction dup 0 1 between?
+    [ good-colors at-fraction-of >>myc ]
+    [ drop ]
+  if ;
+
+: set-anti-color ( particle -- particle )
+  color-fraction dup 0 1 between?
+    [ anti-colors at-fraction-of >>mya ]
+    [ drop ]
+  if ;
diff --git a/extra/bubble-chamber/particle/muon/muon.factor b/extra/bubble-chamber/particle/muon/muon.factor
new file mode 100644 (file)
index 0000000..44c7d9f
--- /dev/null
@@ -0,0 +1,62 @@
+
+USING: kernel arrays sequences random
+       math
+       math.ranges
+       math.functions
+       math.vectors
+       multi-methods accessors
+       combinators.cleave
+       processing
+       bubble-chamber.common
+       bubble-chamber.particle
+       bubble-chamber.particle.muon.colors ;
+
+IN: bubble-chamber.particle.muon
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+TUPLE: muon < particle ;
+
+: <muon> ( -- muon ) muon construct-empty initialize-particle ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+METHOD: collide { muon }
+
+  center               >>pos
+  2 32 [a,b] random    >>speed
+  0.0001 0.001 2random >>speed-d
+
+  collision-theta>  -0.1 0.1 2random + >>theta
+  0                                    >>theta-d
+  0                                    >>theta-dd
+
+  [ 0.001 theta-dd-small? ] [ -0.1 0.1 random-theta-dd ] [ ] while
+
+  set-good-color
+  set-anti-color
+
+  drop ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+METHOD: move { muon }
+
+  dup myc>> 0.16 >>alpha stroke
+  dup pos>> point
+
+  dup mya>> 0.16 >>alpha stroke
+  dup pos>> first2 >r dim swap - r> 2array point
+
+  dup
+    [ speed>> ] [ theta>> { sin cos } <arr> ] bi n*v
+  move-by
+
+  step-theta
+  step-theta-d
+  step-speed-sub
+
+  out-of-bounds? [ collide ] [ drop ] if ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
diff --git a/extra/bubble-chamber/particle/particle.factor b/extra/bubble-chamber/particle/particle.factor
new file mode 100644 (file)
index 0000000..755a414
--- /dev/null
@@ -0,0 +1,68 @@
+
+USING: kernel sequences combinators
+       math math.vectors math.functions multi-methods
+       accessors combinators.cleave processing processing.color
+       bubble-chamber.common ;
+
+IN: bubble-chamber.particle
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+GENERIC: collide ( particle -- )
+GENERIC: move    ( particle -- )
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+TUPLE: particle pos vel speed speed-d theta theta-d theta-dd myc mya ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: initialize-particle ( particle -- particle )
+
+  0 0 {2} >>pos
+  0 0 {2} >>vel
+
+  0 >>speed
+  0 >>speed-d
+  0 >>theta
+  0 >>theta-d
+  0 >>theta-dd
+
+  0 0 0 1 <rgba> >>myc
+  0 0 0 1 <rgba> >>mya ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: move-by ( obj delta -- obj ) over pos>> v+ >>pos ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: theta-dd-small? ( par limit -- par ? ) >r dup theta-dd>> abs r> < ;
+
+: random-theta-dd  ( par a b -- par ) 2random >>theta-dd ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: turn ( particle -- particle )
+  dup
+    [ speed>> ] [ theta>> { sin cos } <arr> ] bi n*v
+  >>vel ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: step-theta     ( p -- p ) [ ] [ theta>>   ] [ theta-d>>  ] tri + >>theta   ;
+: step-theta-d   ( p -- p ) [ ] [ theta-d>> ] [ theta-dd>> ] tri + >>theta-d ;
+: step-speed-sub ( p -- p ) [ ] [ speed>>   ] [ speed-d>>  ] tri - >>speed   ;
+: step-speed-mul ( p -- p ) [ ] [ speed>>   ] [ speed-d>>  ] tri * >>speed   ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: x ( particle -- x ) pos>> first  ;
+: y ( particle -- x ) pos>> second ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: out-of-bounds? ( particle -- particle ? )
+  dup
+  { [ x dim neg < ] [ x dim 2 * > ] [ y dim neg < ] [ y dim 2 * > ] } cleave
+  or or or ;
diff --git a/extra/bubble-chamber/particle/quark/quark.factor b/extra/bubble-chamber/particle/quark/quark.factor
new file mode 100644 (file)
index 0000000..32d95c8
--- /dev/null
@@ -0,0 +1,53 @@
+
+USING: kernel arrays sequences random math accessors multi-methods
+       processing
+       bubble-chamber.common
+       bubble-chamber.particle ;
+
+IN: bubble-chamber.particle.quark
+
+TUPLE: quark < particle ;
+
+: <quark> ( -- quark ) quark construct-empty initialize-particle ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+METHOD: collide { quark }
+
+  center                     >>pos
+  collision-theta> -0.11 0.11 2random +  >>theta
+  0.5 3.0 2random                        >>speed
+
+  0.996 1.001 2random                    >>speed-d
+  0                                      >>theta-d
+  0                                      >>theta-dd
+
+  [ 0.00001 theta-dd-small? ] [ -0.001 0.001 random-theta-dd ] [ ] while
+
+  drop ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+METHOD: move { quark }
+
+  dup myc>> 0.13 >>alpha stroke
+  dup pos>>              point
+
+  dup pos>> first2 >r dim swap - r> 2array point
+
+  [ ] [ vel>> ] bi move-by
+
+  turn
+
+  step-theta
+  step-theta-d
+  step-speed-mul
+
+  1000 random 997 >
+    [
+      dup speed>> neg    >>speed
+      2 over speed-d>> - >>speed-d
+    ]
+  when
+
+  out-of-bounds? [ collide ] [ drop ] if ;
index ece6d64ed9c141f8b935f7ec96ad9590fc6f7eeb..0e3a794e246e2719e92e2976ccc58f8a0a585987 100644 (file)
@@ -2,7 +2,7 @@
 USING: kernel namespaces sequences splitting system combinators continuations
        parser io io.files io.launcher io.sockets prettyprint threads
        bootstrap.image benchmark vars bake smtp builder.util accessors
-       io.encodings.utf8
+       debugger io.encodings.utf8
        calendar
        tools.test
        builder.common
@@ -13,16 +13,22 @@ IN: builder
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-! : cd ( path -- ) current-directory set ;
-
 : cd ( path -- ) set-current-directory ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
+: builds/factor ( -- path ) builds "factor" append-path ;
+: build-dir     ( -- path ) builds stamp>   append-path ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
 : prepare-build-machine ( -- )
   builds make-directory
-  builds cd
-  { "git" "clone" "git://factorcode.org/git/factor.git" } run-process drop ;
+  builds
+    [
+      { "git" "clone" "git://factorcode.org/git/factor.git" } try-process
+    ]
+  with-directory ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
@@ -51,23 +57,15 @@ IN: builder
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
 : gnu-make ( -- string )
-  os { "freebsd" "openbsd" "netbsd" } member?
+  os { freebsd openbsd netbsd } member?
     [ "gmake" ]
     [ "make"  ]
   if ;
 
-! : do-make-clean ( -- ) { "make" "clean" } try-process ;
-
 : do-make-clean ( -- ) { gnu-make "clean" } to-strings try-process ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-! : make-vm ( -- desc )
-!   <process>
-!     { "make" }       >>command
-!     "../compile-log" >>stdout
-!     +stdout+         >>stderr ;
-
 : make-vm ( -- desc )
   <process>
     { gnu-make } to-strings >>command
@@ -80,8 +78,8 @@ IN: builder
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
 : copy-image ( -- )
-  builds "factor" append-path my-boot-image-name append-path ".." copy-file-into
-  builds "factor" append-path my-boot-image-name append-path "."  copy-file-into ;
+  builds/factor my-boot-image-name append-path ".." copy-file-into
+  builds/factor my-boot-image-name append-path "."  copy-file-into ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
@@ -94,7 +92,7 @@ IN: builder
     +closed+      >>stdin
     "../boot-log" >>stdout
     +stdout+      >>stderr
-    20 minutes    >>timeout ;
+    60 minutes    >>timeout ;
 
 : do-bootstrap ( -- )
   bootstrap [ "Bootstrap error" print "../boot-log" cat ] run-or-bail ;
@@ -108,7 +106,7 @@ IN: builder
     +closed+         >>stdin
     "../test-log"    >>stdout
     +stdout+         >>stderr
-    120 minutes      >>timeout ;
+    240 minutes      >>timeout ;
 
 : do-builder-test ( -- )
   builder-test [ "Test error" print "../test-log" 100 cat-n ] run-or-bail ;
@@ -127,10 +125,10 @@ SYMBOL: build-status
 
   "report" utf8
     [
-      "Build machine:   " write host-name print
-      "CPU:             " write cpu       print
-      "OS:              " write os        print
-      "Build directory: " write cwd       print
+      "Build machine:   " write host-name             print
+      "CPU:             " write cpu                   .
+      "OS:              " write os                    .
+      "Build directory: " write current-directory get print
 
       git-clone [ "git clone failed" print ] run-or-bail
 
@@ -158,8 +156,6 @@ SYMBOL: build-status
       "Did not pass test-all: "        print "test-all-vocabs"        cat
                                              "test-failures"          cat
       
-!       "test-failures" eval-file test-failures.
-      
       "help-lint results:"             print "help-lint"              cat
 
       "Benchmarks: " print "benchmarks" eval-file benchmarks.
@@ -196,15 +192,27 @@ SYMBOL: builder-recipients
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-: compress-image ( -- )
-  { "bzip2" my-boot-image-name } to-strings run-process drop ;
+: compress-image ( -- ) { "bzip2" my-boot-image-name } to-strings try-process ;
+
+! : build ( -- )
+!   [ (build) ] try
+!   builds cd stamp> cd
+!   [ send-builder-email ] try
+!   { "rm" "-rf" "factor" } [ ] run-or-bail
+!   [ compress-image ] try ;
 
 : build ( -- )
-  [ (build) ] failsafe
-  builds cd stamp> cd
-  [ send-builder-email ] [ drop "not sending mail" . ] recover
-  { "rm" "-rf" "factor" } run-process drop
-  [ compress-image ] failsafe ;
+  [
+    (build)
+    build-dir
+      [
+        { "rm" "-rf" "factor" } try-process
+        compress-image
+      ]
+    with-directory
+  ]
+  try
+  send-builder-email ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
@@ -221,7 +229,7 @@ USE: bootstrap.image.download
 
 : updates-available? ( -- ? )
   git-id
-  git-pull run-process drop
+  git-pull try-process
   git-id
   = not ;
 
@@ -234,12 +242,15 @@ USE: bootstrap.image.download
 : build-loop ( -- )
   builds-check
   [
-    builds "/factor" append cd
-    updates-available? new-image-available? or
-      [ build ]
-    when
+    builds/factor
+      [
+        updates-available? new-image-available? or
+          [ build ]
+        when
+      ]
+    with-directory
   ]
-  failsafe
+  try
   5 minutes sleep
   build-loop ;
 
index d76eda8013ef975f94e74e39fa8fdf456941e9ce..9b449a51c538f7d834b8da0c56d8000eae67cb00 100644 (file)
@@ -1,6 +1,6 @@
 
 USING: kernel system namespaces sequences splitting combinators
-       io io.files io.launcher
+       io io.files io.launcher prettyprint
        bake combinators.cleave builder.common builder.util ;
 
 IN: builder.release
@@ -33,22 +33,22 @@ IN: builder.release
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-: cpu- ( -- cpu ) cpu "." split "-" join ;
+: cpu- ( -- cpu ) cpu unparse "." split "-" join ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-: base-name ( -- string ) { "factor" os cpu- stamp> } to-strings "-" join ;
+: base-name ( -- string )
+  { "factor" [ os unparse ] cpu- stamp> } to-strings "-" join ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
 : extension ( -- extension )
-  os
   {
-    { "linux" [ ".tar.gz" ] }
-    { "winnt" [ ".zip" ] }
-    { "macosx" [ ".dmg" ] }
+    { [ os winnt?  ] [ ".zip"    ] }  
+    { [ os macosx? ] [ ".dmg"    ] }
+    { [ os unix?   ] [ ".tar.gz" ] }
   }
-  case ;
+  cond ;
 
 : archive-name ( -- string ) base-name extension append ;
 
@@ -69,9 +69,9 @@ IN: builder.release
 
 : archive-cmd ( -- cmd )
   {
-    { [ windows? ] [ windows-archive-cmd ] }
-    { [ macosx?  ] [ macosx-archive-cmd  ] }
-    { [ unix?    ] [ unix-archive-cmd    ] }
+    { [ os windows? ] [ windows-archive-cmd ] }
+    { [ os macosx?  ] [ macosx-archive-cmd  ] }
+    { [ os unix?    ] [ unix-archive-cmd    ] }
   }
   cond ;
 
@@ -83,13 +83,13 @@ IN: builder.release
   { "rm" "-rf" common-files } to-strings try-process ;
 
 : remove-factor-app ( -- )
-  macosx? not [ { "rm" "-rf" "Factor.app" } try-process ] when ;
+  os macosx? not [ { "rm" "-rf" "Factor.app" } try-process ] when ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
 SYMBOL: upload-to-factorcode
 
-: platform ( -- string ) { os cpu- } to-strings "-" join ;
+: platform ( -- string ) { [ os unparse ] cpu- } to-strings "-" join ;
 
 : remote-location ( -- dest )
   "factorcode.org:/var/www/factorcode.org/newsite/downloads"
index 3634082f56ebeb6e83a55b74b7c6e62d700f6827..d5c3e9cd941cd54d241349360e406e7425386f1c 100644 (file)
@@ -1,40 +1,35 @@
 
-USING: kernel namespaces sequences assocs builder continuations
-       vocabs vocabs.loader
-       io
-       io.files
-       prettyprint
-       tools.vocabs
-       tools.test
-       io.encodings.utf8
-       combinators.cleave
+! USING: kernel namespaces sequences assocs continuations
+!        vocabs vocabs.loader
+!        io
+!        io.files
+!        prettyprint
+!        tools.vocabs
+!        tools.test
+!        io.encodings.utf8
+!        combinators.cleave
+!        help.lint
+!        bootstrap.stage2 benchmark builder.util ;
+
+USING: kernel namespaces assocs
+       io.files io.encodings.utf8 prettyprint 
        help.lint
-       bootstrap.stage2 benchmark builder.util ;
+       benchmark
+       bootstrap.stage2
+       tools.test tools.vocabs
+       builder.util ;
 
 IN: builder.test
 
 : do-load ( -- )
   try-everything keys "../load-everything-vocabs" utf8 [ . ] with-file-writer ;
 
-! : do-tests ( -- )
-!   run-all-tests keys "../test-all-vocabs" utf8 [ . ] with-file-writer ;
-
 : do-tests ( -- )
   run-all-tests
     [ keys "../test-all-vocabs" utf8 [ .              ] with-file-writer ]
     [      "../test-failures"   utf8 [ test-failures. ] with-file-writer ]
   bi ;
 
-! : do-tests ( -- )
-!   run-all-tests
-!   "../test-all-vocabs" utf8
-!     [
-!         [ keys . ]
-!         [ test-failures. ]
-!       bi
-!     ]
-!   with-file-writer ;
-
 : do-help-lint ( -- )
   "" run-help-lint "../help-lint" utf8 [ typos. ] with-file-writer ;
 
index 2cb0df5ca11d6c5eaa0aae17fa9a4395c5811b9f..6010a340a7bec8aed6458cc474e39c2744fecf0b 100755 (executable)
@@ -13,7 +13,7 @@ IN: bunny.model
         numbers {
             { [ dup length 5 = ] [ 3 head pick push ] }
             { [ dup first 3 = ] [ 1 tail over push ] }
-            { [ t ] [ drop ] }
+            [ drop ]
         } cond (parse-model)
     ] when* ;
 
index f9908e4581fe6136a8d50411ad8da4e2814efb9e..e6a93fcc57a963c418201dbf7a2ab4648370389b 100755 (executable)
@@ -10,17 +10,17 @@ TUPLE: png-gadget png ;
 
 ERROR: cairo-error string ;
 
-: check-zero
+: check-zero ( n -- n )
     dup zero? [
         "PNG dimension is 0" cairo-error
     ] when ;
 
 : cairo-png-error ( n -- )
     {
-        { [ dup CAIRO_STATUS_NO_MEMORY = ] [ "Cairo: no memory" cairo-error ] }
-        { [ dup CAIRO_STATUS_FILE_NOT_FOUND = ] [ "Cairo: file not found" cairo-error ] }
-        { [ dup CAIRO_STATUS_READ_ERROR = ] [ "Cairo: read error" cairo-error ] }
-        { [ t ] [ drop ] }
+        { \ CAIRO_STATUS_NO_MEMORY [ "Cairo: no memory" cairo-error ] }
+        { \ CAIRO_STATUS_FILE_NOT_FOUND [ "Cairo: file not found" cairo-error ] }
+        { \ CAIRO_STATUS_READ_ERROR [ "Cairo: read error" cairo-error ] }
+        [ drop ]
     } cond ;
 
 : <png> ( path -- png )
index 2986422155b6bf812f0880ce53a3a6ad890768eb..b621d3bde3609440c228248a3be7fcefc6c04d11 100755 (executable)
@@ -5,12 +5,11 @@ IN: calendar.windows
 M: windows gmt-offset ( -- hours minutes seconds )
     "TIME_ZONE_INFORMATION" <c-object>
     dup GetTimeZoneInformation {
-        { [ dup TIME_ZONE_ID_INVALID = ] [ win32-error-string throw ] }
-        { [ dup [ TIME_ZONE_ID_UNKNOWN = ] [ TIME_ZONE_ID_STANDARD = ] bi or ] [
-            drop TIME_ZONE_INFORMATION-Bias ] }
-        { [ dup TIME_ZONE_ID_DAYLIGHT = ] [
-            drop
+        { TIME_ZONE_ID_INVALID [ win32-error-string throw ] }
+        { TIME_ZONE_ID_UNKNOWN [ TIME_ZONE_INFORMATION-Bias ] }
+        { TIME_ZONE_ID_STANDARD [ TIME_ZONE_INFORMATION-Bias ] }
+        { TIME_ZONE_ID_DAYLIGHT [
             [ TIME_ZONE_INFORMATION-Bias ]
             [ TIME_ZONE_INFORMATION-DaylightBias ] bi +
         ] }
-    } cond neg 60 /mod 0 ;
+    } case neg 60 /mod 0 ;
diff --git a/extra/cel-shading/authors.txt b/extra/cel-shading/authors.txt
deleted file mode 100644 (file)
index 6a0dc72..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Joe Groff
\ No newline at end of file
diff --git a/extra/cel-shading/summary.txt b/extra/cel-shading/summary.txt
deleted file mode 100644 (file)
index 60da092..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Stanford Bunny rendered with a cel-shading GLSL program
\ No newline at end of file
diff --git a/extra/cel-shading/tags.txt b/extra/cel-shading/tags.txt
deleted file mode 100644 (file)
index 0db7e8e..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-demos
-opengl
-glsl
\ No newline at end of file
index 0cf020a0872d4adfbfbe1130fd1fb488ffb741c0..129b949b1d82681160b33867279ff65797cc6253 100755 (executable)
@@ -1,8 +1,9 @@
 ! Copyright (C) 2006, 2007 Slava Pestov
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien io kernel namespaces core-foundation cocoa.messages
-cocoa cocoa.classes cocoa.runtime sequences threads
-debugger init inspector kernel.private ;
+USING: alien io kernel namespaces core-foundation
+core-foundation.run-loop cocoa.messages cocoa cocoa.classes
+cocoa.runtime sequences threads debugger init inspector
+kernel.private ;
 IN: cocoa.application
 
 : <NSString> ( str -- alien ) <CFString> -> autorelease ;
@@ -21,8 +22,6 @@ IN: cocoa.application
 : with-cocoa ( quot -- )
     [ NSApp drop call ] with-autorelease-pool ;
 
-: CFRunLoopDefaultMode "kCFRunLoopDefaultMode" <NSString> ;
-
 : next-event ( app -- event )
     0 f CFRunLoopDefaultMode 1
     -> nextEventMatchingMask:untilDate:inMode:dequeue: ;
index 20b7e2a02d098cf6a6816f84633dc69c433e5fb6..4b56d81626922c73020c51f2c6546d6b75ef403c 100644 (file)
@@ -10,7 +10,7 @@ CLASS: {
     "foo:"
     "void"
     { "id" "SEL" "NSRect" }
-    [ data-gc "x" set 2drop ]
+    [ gc "x" set 2drop ]
 } ;
 
 : test-foo
index c94984f00b2b4cd276c8ed36c010244ac3730dda..f4cfb2059174dc5d88d6748a42e3e1866d05700c 100755 (executable)
@@ -42,11 +42,13 @@ SYMBOL: super-sent-messages
         "NSArray"
         "NSAutoreleasePool"
         "NSBundle"
+        "NSDictionary"
         "NSError"
         "NSEvent"
         "NSException"
         "NSMenu"
         "NSMenuItem"
+        "NSMutableDictionary"
         "NSNib"
         "NSNotification"
         "NSNotificationCenter"
index 480e19b00583ba940ab16b9387aff335b911611e..90dc19a581b9f7cbbebd0df7af2d54ba91801596 100755 (executable)
@@ -154,7 +154,7 @@ H{
         { [ dup CHAR: ^ = ] [ 3drop "void*" ] }
         { [ dup CHAR: { = ] [ drop objc-struct-type ] }
         { [ dup CHAR: [ = ] [ 3drop "void*" ] }
-        { [ t ] [ 2nip 1string objc>alien-types get at ] }
+        [ 2nip 1string objc>alien-types get at ]
     } cond ;
 
 : parse-objc-type ( string -- ctype ) 0 swap (parse-objc-type) ;
index 5965c74af817c6d2b2a751a3a2e16c4c17188bf0..9e05773f53dfe3fbd78fd0778325e4ca1b5a3565 100644 (file)
@@ -1,23 +1,19 @@
-! Copyright (C) 2007 Slava Pestov.
+! Copyright (C) 2007, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: strings arrays hashtables assocs sequences
-xml.writer xml.utilities kernel namespaces ;
+cocoa.messages cocoa.classes cocoa.application cocoa kernel
+namespaces io.backend ;
 IN: cocoa.plists
 
-GENERIC: >plist ( obj -- tag )
+: assoc>NSDictionary ( assoc -- alien )
+    NSMutableDictionary over assoc-size -> dictionaryWithCapacity:
+    [
+        [
+            spin [ <NSString> ] bi@ -> setObject:forKey:
+        ] curry assoc-each
+    ] keep ;
 
-M: string >plist "string" build-tag ;
-
-M: array >plist
-    [ >plist ] map "array" build-tag* ;
-
-M: hashtable >plist
-    >alist [ >r "key" build-tag r> >plist ] assoc-map concat
-    "dict" build-tag* ;
-
-: build-plist ( obj -- tag )
-    >plist 1array "plist" build-tag*
-    dup { { "version" "1.0" } } update ;
-
-: plist>string ( obj -- string )
-    build-plist build-xml xml>string ;
+: write-plist ( assoc path -- )
+    >r assoc>NSDictionary
+    r> normalize-path <NSString> 0 -> writeToFile:atomically:
+    [ "write-plist failed" throw ] unless ;
index 50694776c515b02e2b58719f1d52bcd7f3c33dec..a9b86e3bcdef714046410bfcc82568cf9c89826f 100755 (executable)
@@ -57,7 +57,7 @@ HELP: mailbox-get?
 \r
 \r
 ARTICLE: "concurrency.mailboxes" "Mailboxes"\r
-"A " { $emphasis "mailbox" } " is a first-in-first-out queue where the operation of removing an element blocks if the queue is empty, instead of throwing an error."\r
+"A " { $emphasis "mailbox" } " is a first-in-first-out queue where the operation of removing an element blocks if the queue is empty, instead of throwing an error. Mailboxes are implemented in the " { $vocab-link "concurrency.mailboxes" } " vocabulary."\r
 { $subsection mailbox }\r
 { $subsection <mailbox> }\r
 "Removing the first element:"\r
@@ -73,3 +73,5 @@ ARTICLE: "concurrency.mailboxes" "Mailboxes"
 "Testing if a mailbox is empty:"\r
 { $subsection mailbox-empty? }\r
 { $subsection while-mailbox-empty } ;\r
+\r
+ABOUT: "concurrency.mailboxes"\r
index 2cb12bcabaf47fc7155876c3338b451cdaf432de..7fe09cdcf5b849f9c28f6466e47bc52753adc624 100755 (executable)
@@ -1,6 +1,7 @@
 IN: concurrency.mailboxes.tests\r
-USING: concurrency.mailboxes vectors sequences threads\r
-tools.test math kernel strings ;\r
+USING: concurrency.mailboxes concurrency.count-downs vectors\r
+sequences threads tools.test math kernel strings namespaces\r
+continuations calendar ;\r
 \r
 [ V{ 1 2 3 } ] [\r
     0 <vector>\r
@@ -38,3 +39,37 @@ tools.test math kernel strings ;
     "junk2" over mailbox-put\r
     mailbox-get\r
 ] unit-test\r
+\r
+<mailbox> "m" set\r
+\r
+1 <count-down> "c" set\r
+1 <count-down> "d" set\r
+\r
+[\r
+    "c" get await\r
+    [ "m" get mailbox-get drop ]\r
+    [ drop "d" get count-down ] recover\r
+] "Mailbox close test" spawn drop\r
+\r
+[ ] [ "c" get count-down ] unit-test\r
+[ ] [ "m" get dispose ] unit-test\r
+[ ] [ "d" get 5 seconds await-timeout ] unit-test\r
+\r
+[ ] [ "m" get dispose ] unit-test\r
+\r
+<mailbox> "m" set\r
+\r
+1 <count-down> "c" set\r
+1 <count-down> "d" set\r
+\r
+[\r
+    "c" get await\r
+    "m" get wait-for-close\r
+    "d" get count-down\r
+] "Mailbox close test" spawn drop\r
+\r
+[ ] [ "c" get count-down ] unit-test\r
+[ ] [ "m" get dispose ] unit-test\r
+[ ] [ "d" get 5 seconds await-timeout ] unit-test\r
+\r
+[ ] [ "m" get dispose ] unit-test\r
index 7b6405679f52242e9ec0f9939990c63c1b1a88a5..36aafbdc84720797f013989e33efbb4dd0cc6cab 100755 (executable)
@@ -3,41 +3,50 @@
 IN: concurrency.mailboxes\r
 USING: dlists threads sequences continuations\r
 namespaces random math quotations words kernel arrays assocs\r
-init system concurrency.conditions ;\r
+init system concurrency.conditions accessors ;\r
 \r
-TUPLE: mailbox threads data ;\r
+TUPLE: mailbox threads data closed ;\r
+\r
+: check-closed ( mailbox -- )\r
+    closed>> [ "Mailbox closed" throw ] when ; inline\r
+\r
+M: mailbox dispose\r
+    t >>closed threads>> notify-all ;\r
 \r
 : <mailbox> ( -- mailbox )\r
-    <dlist> <dlist> mailbox construct-boa ;\r
+    <dlist> <dlist> mailbox construct-boa ;\r
 \r
 : mailbox-empty? ( mailbox -- bool )\r
-    mailbox-data dlist-empty? ;\r
+    data>> dlist-empty? ;\r
 \r
 : mailbox-put ( obj mailbox -- )\r
-    [ mailbox-data push-front ] keep\r
-    mailbox-threads notify-all yield ;\r
+    [ data>> push-front ]\r
+    [ threads>> notify-all ] bi yield ;\r
+\r
+: wait-for-mailbox ( mailbox timeout -- )\r
+    >r threads>> r> "mailbox" wait ;\r
 \r
 : block-unless-pred ( mailbox timeout pred -- )\r
-    pick mailbox-data over dlist-contains? [\r
+    pick check-closed\r
+    pick data>> over dlist-contains? [\r
         3drop\r
     ] [\r
-        >r over mailbox-threads over "mailbox" wait r>\r
-        block-unless-pred\r
+        >r 2dup wait-for-mailbox r> block-unless-pred\r
     ] if ; inline\r
 \r
 : block-if-empty ( mailbox timeout -- mailbox )\r
+    over check-closed\r
     over mailbox-empty? [\r
-        over mailbox-threads over "mailbox" wait\r
-        block-if-empty\r
+        2dup wait-for-mailbox block-if-empty\r
     ] [\r
         drop\r
     ] if ;\r
 \r
 : mailbox-peek ( mailbox -- obj )\r
-    mailbox-data peek-back ;\r
+    data>> peek-back ;\r
 \r
 : mailbox-get-timeout ( mailbox timeout -- obj )\r
-    block-if-empty mailbox-data pop-back ;\r
+    block-if-empty data>> pop-back ;\r
 \r
 : mailbox-get ( mailbox -- obj )\r
     f mailbox-get-timeout ;\r
@@ -45,7 +54,7 @@ TUPLE: mailbox threads data ;
 : mailbox-get-all-timeout ( mailbox timeout -- array )\r
     block-if-empty\r
     [ dup mailbox-empty? ]\r
-    [ dup mailbox-data pop-back ]\r
+    [ dup data>> pop-back ]\r
     [ ] unfold nip ;\r
 \r
 : mailbox-get-all ( mailbox -- array )\r
@@ -60,11 +69,18 @@ TUPLE: mailbox threads data ;
 \r
 : mailbox-get-timeout? ( mailbox timeout pred -- obj )\r
     3dup block-unless-pred\r
-    nip >r mailbox-data r> delete-node-if ; inline\r
+    nip >r data>> r> delete-node-if ; inline\r
 \r
 : mailbox-get? ( mailbox pred -- obj )\r
     f swap mailbox-get-timeout? ; inline\r
 \r
+: wait-for-close-timeout ( mailbox timeout -- )\r
+    over closed>>\r
+    [ 2drop ] [ 2dup wait-for-mailbox wait-for-close-timeout ] if ;\r
+\r
+: wait-for-close ( mailbox -- )\r
+    f wait-for-close-timeout ;\r
+\r
 TUPLE: linked-error thread ;\r
 \r
 : <linked-error> ( error thread -- linked )\r
index e7aa5d1a7e496be1154bd7faaa2f21c45a0ad9cd..1219982f510b129567f95af4d1c6de5b4186c5cc 100755 (executable)
@@ -32,7 +32,7 @@ HELP: spawn-linked
 { $description "Start a thread which runs the given quotation. If that quotation throws an error which is not caught then the error will get propagated to the thread that spawned it. This can be used to set up 'supervisor' threades that restart child threades that crash due to uncaught errors.\n" } 
 { $see-also spawn } ;
 
-ARTICLE: { "concurrency" "messaging" } "Mailboxes"
+ARTICLE: { "concurrency" "messaging" } "Sending and receiving messages"
 "Each thread has an associated mailbox. Other threads can place items on this queue by sending the thread a message. A thread can check its mailbox for messages, blocking if none are pending, and thread them as they are queued."
 $nl
 "The messages that are sent from thread to thread are any Factor value. Factor tuples are ideal for this sort of thing as you can send a tuple to a thread and the generic word dispatch mechanism can be used to perform actions depending on what the type of the tuple is."
@@ -43,7 +43,8 @@ $nl
 { $subsection receive }
 { $subsection receive-timeout }
 { $subsection receive-if }
-{ $subsection receive-if-timeout } ;
+{ $subsection receive-if-timeout }
+{ $see-also "concurrency.mailboxes" } ;
 
 ARTICLE: { "concurrency" "synchronous-sends" } "Synchronous sends"
 "The " { $link send } " word sends a message asynchronously, and the sending thread continues immediately. It is also possible to send a message to a thread and block until a response is received:"
index 6de381b166108ba775169f25dea7b7be1ea86769..b69773f3b1631098f48735d5736069a204250de7 100755 (executable)
@@ -3,7 +3,8 @@
 !
 USING: kernel threads vectors arrays sequences
 namespaces tools.test continuations dlists strings math words
-match quotations concurrency.messaging concurrency.mailboxes ;
+match quotations concurrency.messaging concurrency.mailboxes
+concurrency.count-downs ;
 IN: concurrency.messaging.tests
 
 [ ] [ my-mailbox mailbox-data dlist-delete-all ] unit-test
@@ -52,4 +53,15 @@ SYMBOL: exit
     [ value , self , ] { } make "counter" get send
     receive
     exit "counter" get send
-] unit-test
\ No newline at end of file
+] unit-test
+
+! Not yet
+
+! 1 <count-down> "c" set
+
+! [
+!     "c" get count-down
+!     receive drop
+! ] "Bad synchronous send" spawn "t" set
+
+! [ 3 "t" get send-synchronous ] must-fail
\ No newline at end of file
index 6365b91517f48048d52c4ab30882f579287a53a0..d0da724cc6d6df72877b43e2f10776969a2f8539 100755 (executable)
@@ -5,8 +5,9 @@ sequences sequences.lib assocs system sorting math.parser ;
 IN: contributors
 
 : changelog ( -- authors )
-    image parent-directory cd
-    "git-log --pretty=format:%an" <process-stream> lines ;
+    image parent-directory [
+        "git-log --pretty=format:%an" <process-stream> lines
+    ] with-directory ;
 
 : patch-counts ( authors -- assoc )
     dup prune
index 73b8fce22907924bf49ad8a6c9d336ec712c9f4b..77ad30ad8ff4acdbc4793d1795f8183c569e3f9b 100644 (file)
@@ -9,9 +9,9 @@ TYPEDEF: void* CFBundleRef
 TYPEDEF: void* CFStringRef
 TYPEDEF: void* CFURLRef
 TYPEDEF: void* CFUUIDRef
-TYPEDEF: void* CFRunLoopRef
 TYPEDEF: bool Boolean
 TYPEDEF: int CFIndex
+TYPEDEF: int SInt32
 TYPEDEF: double CFTimeInterval
 TYPEDEF: double CFAbsoluteTime
 
@@ -85,5 +85,3 @@ FUNCTION: void CFRelease ( void* cf ) ;
     ] [
         "Cannot load bundled named " prepend throw
     ] ?if ;
-
-FUNCTION: CFRunLoopRef CFRunLoopGetMain ( ) ;
index 55f2462061c8bd7dec4f5a3cbaeb52ace8b5ba97..24211a59c7af6a1a95af6489da81c5c4a39617e5 100644 (file)
@@ -1,7 +1,8 @@
 ! Copyright (C) 2008 Slava Pestov
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien alien.c-types alien.syntax kernel math sequences
-namespaces assocs init continuations core-foundation ;
+namespaces assocs init accessors continuations combinators
+core-foundation core-foundation.run-loop ;
 IN: core-foundation.fsevents
 
 ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
@@ -151,12 +152,10 @@ SYMBOL: event-stream-callbacks
 
 [
     event-stream-callbacks global
-    [ [ drop expired? not ] assoc-subset ] change-at
+    [ [ drop expired? not ] assoc-subset H{ } assoc-like ] change-at
     1 \ event-stream-counter set-global
 ] "core-foundation" add-init-hook
 
-event-stream-callbacks global [ H{ } assoc-like ] change-at
-
 : add-event-source-callback ( quot -- id )
     event-stream-counter <alien>
     [ event-stream-callbacks get set-at ] keep ;
@@ -184,11 +183,11 @@ event-stream-callbacks global [ H{ } assoc-like ] change-at
     }
     "cdecl" [
         [ >event-triple ] 3curry map
-        swap event-stream-callbacks get at call
-        drop
+        swap event-stream-callbacks get at
+        dup [ call drop ] [ 3drop ] if
     ] alien-callback ;
 
-TUPLE: event-stream info handle ;
+TUPLE: event-stream info handle closed ;
 
 : <event-stream> ( quot paths latency flags -- event-stream )
     >r >r >r
@@ -196,9 +195,15 @@ TUPLE: event-stream info handle ;
     >r master-event-source-callback r>
     r> r> r> <FSEventStream>
     dup enable-event-stream
-    event-stream construct-boa ;
+    event-stream construct-boa ;
 
 M: event-stream dispose
-    dup event-stream-info remove-event-source-callback
-    event-stream-handle dup disable-event-stream
-    FSEventStreamRelease ;
+    dup closed>> [ drop ] [
+        t >>closed
+        {
+            [ info>> remove-event-source-callback ]
+            [ handle>> disable-event-stream ]
+            [ handle>> FSEventStreamInvalidate ]
+            [ handle>> FSEventStreamRelease ]
+        } cleave
+    ] if ;
diff --git a/extra/core-foundation/run-loop/run-loop.factor b/extra/core-foundation/run-loop/run-loop.factor
new file mode 100644 (file)
index 0000000..7594766
--- /dev/null
@@ -0,0 +1,38 @@
+! Copyright (C) 2008 Slava Pestov
+! See http://factorcode.org/license.txt for BSD license.
+USING: alien.syntax kernel threads init namespaces alien
+core-foundation ;
+IN: core-foundation.run-loop
+
+: kCFRunLoopRunFinished 1 ; inline
+: kCFRunLoopRunStopped 2 ; inline
+: kCFRunLoopRunTimedOut 3 ; inline
+: kCFRunLoopRunHandledSource 4 ; inline
+
+TYPEDEF: void* CFRunLoopRef
+
+FUNCTION: CFRunLoopRef CFRunLoopGetMain ( ) ;
+
+FUNCTION: SInt32 CFRunLoopRunInMode (
+   CFStringRef mode,
+   CFTimeInterval seconds,
+   Boolean returnAfterSourceHandled
+) ;
+
+: CFRunLoopDefaultMode ( -- alien )
+    #! Ugly, but we don't have static NSStrings
+    \ CFRunLoopDefaultMode get-global dup expired? [
+        drop
+        "kCFRunLoopDefaultMode" <CFString>
+        dup \ CFRunLoopDefaultMode set-global
+    ] when ;
+
+: run-loop-thread ( -- )
+    CFRunLoopDefaultMode 0 f CFRunLoopRunInMode
+    kCFRunLoopRunHandledSource = [ 1000 sleep ] unless
+    run-loop-thread ;
+
+: start-run-loop-thread ( -- )
+    [ run-loop-thread t ] "CFRunLoop dispatcher" spawn-server drop ;
+
+[ start-run-loop-thread ] "core-foundation.run-loop" add-init-hook
index d054eda31b0c03f75fc1a7e2f5211ab665c482de..37e92db60f2fd1254a1f26f22a79c94e5ad593b2 100755 (executable)
@@ -125,4 +125,4 @@ SYMBOLS: h0 h1 h2 h3 h4 A B C D E w K ;
     [ zero? ] left-trim
     dup length odd? [ 1 tail ] when
     seq>2seq [ byte-array>sha1 ] bi@
-    swap 2seq>seq ;
+    2seq>seq ;
diff --git a/extra/crypto/test/blum-blum-shub.factor b/extra/crypto/test/blum-blum-shub.factor
deleted file mode 100644 (file)
index b1b6034..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-USING: kernel math test namespaces crypto crypto-internals ;
-
-[ 6 ] [ 5 T{ bbs f 590695557939 811977232793 } random-bbs-bits* ] unit-test
-[ 792723710536787233474130382522 ] [ 100 T{ bbs f 200352954495 846054538649 } [ random-bbs-bits* drop ] 2keep random-bbs-bits* ] unit-test
-
index 55e672ec806d13d8fd8834259e60c89e13b94068..1a1a18c942b18d1541f83ed4df91222dd703d3b9 100755 (executable)
@@ -11,14 +11,19 @@ TUPLE: db
     update-statements
     delete-statements ;
 
-: <db> ( handle -- obj )
-    H{ } clone H{ } clone H{ } clone
-    db construct-boa ;
+: construct-db ( class -- obj )
+    construct-empty
+        H{ } clone >>insert-statements
+        H{ } clone >>update-statements
+        H{ } clone >>delete-statements ;
 
 GENERIC: make-db* ( seq class -- db )
-GENERIC: db-open ( db -- )
+
+: make-db ( seq class -- db )
+    construct-db make-db* ;
+
+GENERIC: db-open ( db -- db )
 HOOK: db-close db ( handle -- )
-: make-db ( seq class -- db ) construct-empty make-db* ;
 
 : dispose-statements ( seq -- ) [ dispose drop ] assoc-each ;
 
@@ -30,10 +35,13 @@ HOOK: db-close db ( handle -- )
         handle>> db-close
     ] with-variable ;
 
+! TUPLE: sql sql in-params out-params ;
 TUPLE: statement handle sql in-params out-params bind-params bound? ;
-TUPLE: simple-statement ;
-TUPLE: prepared-statement ;
-TUPLE: nonthrowable-statement ;
+TUPLE: simple-statement < statement ;
+TUPLE: prepared-statement < statement ;
+TUPLE: nonthrowable-statement < statement ;
+TUPLE: throwable-statement < statement ;
+
 : make-nonthrowable ( obj -- obj' )
     dup sequence? [
         [ make-nonthrowable ] map
@@ -41,14 +49,13 @@ TUPLE: nonthrowable-statement ;
         nonthrowable-statement construct-delegate
     ] if ;
 
-MIXIN: throwable-statement
-INSTANCE: statement throwable-statement
-INSTANCE: simple-statement throwable-statement
-INSTANCE: prepared-statement throwable-statement
-
 TUPLE: result-set sql in-params out-params handle n max ;
-: <statement> ( sql in out -- statement )
-    { (>>sql) (>>in-params) (>>out-params) } statement construct ;
+
+: construct-statement ( sql in out class -- statement )
+    construct-empty
+        swap >>out-params
+        swap >>in-params
+        swap >>sql ;
 
 HOOK: <simple-statement> db ( str in out -- statement )
 HOOK: <prepared-statement> db ( str in out -- statement )
@@ -88,11 +95,14 @@ M: nonthrowable-statement execute-statement ( statement -- )
     dup #rows >>max
     0 >>n drop ;
 
-: <result-set> ( query handle tuple -- result-set )
-    >r >r { sql>> in-params>> out-params>> } get-slots r>
-    { (>>sql) (>>in-params) (>>out-params) (>>handle) } result-set
-    construct r> construct-delegate ;
-
+: construct-result-set ( query handle class -- result-set )
+    construct-empty
+        swap >>handle
+        >r [ sql>> ] [ in-params>> ] [ out-params>> ] tri r>
+        swap >>out-params
+        swap >>in-params
+        swap >>sql ;
+    
 : sql-row ( result-set -- seq )
     dup #columns [ row-column ] with map ;
 
@@ -110,7 +120,7 @@ M: nonthrowable-statement execute-statement ( statement -- )
     accumulator >r query-each r> { } like ; inline
 
 : with-db ( db seq quot -- )
-    >r make-db dup db-open db r>
+    >r make-db db-open db r>
     [ db get swap [ drop ] swap compose with-disposal ] curry with-variable ;
 
 : default-query ( query -- result-set )
index 59d1b6ff3d1ac5330062eceef208bca7b469b3b4..ca912f200d65611d1871c592edfb43837f75a299 100644 (file)
@@ -18,16 +18,16 @@ TUPLE: mysql-result-set ;
 : mysql-error ( mysql -- )
     [ mysql_error throw ] when* ;
 
-: mysql-connect ( mysql-connection -- )
-    new-mysql over set-mysql-db-handle
-    dup {
-        mysql-db-handle
-        mysql-db-host
-        mysql-db-user
-        mysql-db-password
-        mysql-db-db
-        mysql-db-port
-    } get-slots f 0 mysql_real_connect mysql-error ;
+: mysql-connect ( mysql-connection -- )
+    new-mysql over set-mysql-db-handle
+    dup {
+        mysql-db-handle
+        mysql-db-host
+        mysql-db-user
+        mysql-db-password
+        mysql-db-db
+        mysql-db-port
+    } get-slots f 0 mysql_real_connect mysql-error ;
 
 ! =========================================================
 ! Low level mysql utility definitions
index 7925989bf5879016150f0f3574064b205bdf6f0d..ee5ba622e526dd7d6590bfcb94af4dec14fbf4da 100755 (executable)
@@ -6,7 +6,7 @@ IN: db.postgresql.ffi
 
 << "postgresql" {
     { [ os winnt? ]  [ "libpq.dll" ] }
-    { [ os macosx? ] [ "/opt/local/lib/postgresql82/libpq.dylib" ] }
+    { [ os macosx? ] [ "libpq.dylib" ] }
     { [ os unix?  ]  [ "libpq.so" ] }
 } cond "cdecl" add-library >>
 
index f9805560adfda016beb7b9b1db467e7e6ef420ae..322143e7a2f1535b382974b05917d2b76f2028ec 100755 (executable)
@@ -5,40 +5,39 @@ kernel math math.parser namespaces prettyprint quotations
 sequences debugger db db.postgresql.lib db.postgresql.ffi
 db.tuples db.types tools.annotations math.ranges
 combinators sequences.lib classes locals words tools.walker
-namespaces.lib ;
+namespaces.lib accessors ;
 IN: db.postgresql
 
-TUPLE: postgresql-db host port pgopts pgtty db user pass ;
-TUPLE: postgresql-statement ;
-INSTANCE: postgresql-statement throwable-statement
-TUPLE: postgresql-result-set ;
+TUPLE: postgresql-db < db
+    host port pgopts pgtty db user pass ;
+
+TUPLE: postgresql-statement < throwable-statement ;
+
+TUPLE: postgresql-result-set < result-set ;
+
 : <postgresql-statement> ( statement in out -- postgresql-statement )
-    <statement>
-    postgresql-statement construct-delegate ;
+    postgresql-statement construct-statement ;
 
 M: postgresql-db make-db* ( seq tuple -- db )
-    >r first4 r> [
-        {
-            set-postgresql-db-host
-            set-postgresql-db-user
-            set-postgresql-db-pass
-            set-postgresql-db-db
-        } set-slots
-    ] keep ;
-
-M: postgresql-db db-open ( db -- )
-        dup {
-        postgresql-db-host
-        postgresql-db-port
-        postgresql-db-pgopts
-        postgresql-db-pgtty
-        postgresql-db-db
-        postgresql-db-user
-        postgresql-db-pass
-    } get-slots connect-postgres <db> swap set-delegate ;
+    >r first4 r>
+        swap >>db
+        swap >>pass
+        swap >>user
+        swap >>host ;
+
+M: postgresql-db db-open ( db -- db )
+    dup {
+        [ host>> ]
+        [ port>> ]
+        [ pgopts>> ]
+        [ pgtty>> ]
+        [ db>> ]
+        [ user>> ]
+        [ pass>> ]
+    } cleave connect-postgres >>handle ;
 
 M: postgresql-db dispose ( db -- )
-    db-handle PQfinish ;
+    handle>> PQfinish ;
 
 M: postgresql-statement bind-statement* ( statement -- )
     drop ;
@@ -50,10 +49,10 @@ M: postgresql-statement bind-tuple ( tuple statement -- )
     ] keep set-statement-bind-params ;
 
 M: postgresql-result-set #rows ( result-set -- n )
-    result-set-handle PQntuples ;
+    handle>> PQntuples ;
 
 M: postgresql-result-set #columns ( result-set -- n )
-    result-set-handle PQnfields ;
+    handle>> PQnfields ;
 
 M: postgresql-result-set row-column ( result-set column -- obj )
     >r dup result-set-handle swap result-set-n r> pq-get-string ;
@@ -69,7 +68,7 @@ M: postgresql-statement query-results ( query -- result-set )
     ] [
         dup do-postgresql-statement
     ] if*
-    postgresql-result-set <result-set>
+    postgresql-result-set construct-result-set
     dup init-result-set ;
 
 M: postgresql-result-set advance-row ( result-set -- )
@@ -90,7 +89,7 @@ M: postgresql-result-set dispose ( result-set -- )
 
 M: postgresql-statement prepare-statement ( statement -- )
     [
-        >r db get db-handle "" r>
+        >r db get handle>> "" r>
         dup statement-sql swap statement-in-params
         length f PQprepare postgresql-error
     ] keep set-statement-handle ;
index c490ace77091ea6d83a1cb19129c374e1b800e8a..488026fcc7c989402ac9f0cc3a60da642bed63ec 100644 (file)
@@ -38,5 +38,3 @@ TUPLE: person name age ;
         { offset 40 }
         { limit 20 }
     } ;
-
-
index 99dde992808fb7df45541cee32f56741caa7b661..26e8429efdbb90def0395abc71d461b2318747a5 100755 (executable)
@@ -55,7 +55,7 @@ TUPLE: no-sql-match ;
         { [ dup number? ] [ number>string sql% ] }
         { [ dup symbol? ] [ unparse sql% ] }
         { [ dup word? ] [ unparse sql% ] }
-        { [ t ] [ T{ no-sql-match } throw ] }
+        [ T{ no-sql-match } throw ]
     } cond ;
 
 : parse-sql ( obj -- sql in-spec out-spec in out )
index f81d7de4b820a2ee358e189055c919cff1909821..e66accd7e90f08369402b67066af85daf0d97660 100755 (executable)
@@ -20,7 +20,7 @@ IN: db.sqlite.lib
     {
         { [ dup SQLITE_OK = ] [ drop ] }
         { [ dup SQLITE_ERROR = ] [ sqlite-statement-error ] }
-        { [ t ] [ sqlite-error ] }
+        [ sqlite-error ]
     } cond ;
 
 : sqlite-open ( filename -- db )
index 9b3185bcf2052e43c4b862e57b7548d408d125fe..11c0150cd20b89729e5e9c2798aca346e61804c9 100755 (executable)
@@ -5,61 +5,48 @@ hashtables io.files kernel math math.parser namespaces
 prettyprint sequences strings classes.tuple alien.c-types
 continuations db.sqlite.lib db.sqlite.ffi db.tuples
 words combinators.lib db.types combinators
-io namespaces.lib ;
-USE: tools.walker
+io namespaces.lib accessors ;
 IN: db.sqlite
 
-TUPLE: sqlite-db path ;
+TUPLE: sqlite-db < db path ;
 
 M: sqlite-db make-db* ( path db -- db )
-    [ set-sqlite-db-path ] keep ;
+    swap >>path ;
 
-M: sqlite-db db-open ( db -- )
-    dup sqlite-db-path sqlite-open <db>
-    swap set-delegate ;
+M: sqlite-db db-open ( db -- db )
+    [ path>> sqlite-open ] [ swap >>handle ] bi ;
 
 M: sqlite-db db-close ( handle -- ) sqlite-close ;
 M: sqlite-db dispose ( db -- ) dispose-db ;
-: with-sqlite ( path quot -- ) sqlite-db swap with-db ; inline
 
-TUPLE: sqlite-statement ;
-INSTANCE: sqlite-statement throwable-statement
+TUPLE: sqlite-statement < throwable-statement ;
 
-TUPLE: sqlite-result-set has-more? ;
+TUPLE: sqlite-result-set < result-set has-more? ;
 
 M: sqlite-db <simple-statement> ( str in out -- obj )
     <prepared-statement> ;
 
 M: sqlite-db <prepared-statement> ( str in out -- obj )
-    {
-        set-statement-sql
-        set-statement-in-params
-        set-statement-out-params
-    } statement construct
-    sqlite-statement construct-delegate ;
+    sqlite-statement construct-statement ;
 
 : sqlite-maybe-prepare ( statement -- statement )
-    dup statement-handle [
-        [
-            delegate
-            db get db-handle over statement-sql sqlite-prepare
-            swap set-statement-handle
-        ] keep
+    dup handle>> [
+        db get handle>> over sql>> sqlite-prepare
+        >>handle
     ] unless ;
 
 M: sqlite-statement dispose ( statement -- )
-    statement-handle
+    handle>>
     [ [ sqlite3_reset drop ] keep sqlite-finalize ] when* ;
 
 M: sqlite-result-set dispose ( result-set -- )
-    f swap set-result-set-handle ;
+    f >>handle drop ;
 
 : sqlite-bind ( triples handle -- )
     swap [ first3 sqlite-bind-type ] with each ;
 
 : reset-statement ( statement -- )
-    sqlite-maybe-prepare
-    statement-handle sqlite-reset ;
+    sqlite-maybe-prepare handle>> sqlite-reset ;
 
 M: sqlite-statement bind-statement* ( statement -- )
     sqlite-maybe-prepare
@@ -69,11 +56,11 @@ M: sqlite-statement bind-statement* ( statement -- )
 
 M: sqlite-statement bind-tuple ( tuple statement -- )
     [
-        statement-in-params
+        in-params>>
         [
-            [ sql-spec-column-name ":" prepend ]
-            [ sql-spec-slot-name rot get-slot-named ]
-            [ sql-spec-type ] tri 3array
+            [ column-name>> ":" prepend ]
+            [ slot-name>> rot get-slot-named ]
+            [ type>> ] tri 3array
         ] with map
     ] keep
     bind-statement ;
@@ -86,25 +73,24 @@ M: sqlite-db insert-tuple* ( tuple statement -- )
     execute-statement last-insert-id swap set-primary-key ;
 
 M: sqlite-result-set #columns ( result-set -- n )
-    result-set-handle sqlite-#columns ;
+    handle>> sqlite-#columns ;
 
 M: sqlite-result-set row-column ( result-set n -- obj )
-    >r result-set-handle r> sqlite-column ;
+    [ handle>> ] [ sqlite-column ] bi* ;
 
 M: sqlite-result-set row-column-typed ( result-set n -- obj )
-    dup pick result-set-out-params nth sql-spec-type
-    >r >r result-set-handle r> r> sqlite-column-typed ;
+    dup pick out-params>> nth type>>
+    >r >r handle>> r> r> sqlite-column-typed ;
 
 M: sqlite-result-set advance-row ( result-set -- )
-    [ result-set-handle sqlite-next ] keep
-    set-sqlite-result-set-has-more? ;
+    dup handle>> sqlite-next >>has-more? drop ;
 
 M: sqlite-result-set more-rows? ( result-set -- ? )
-    sqlite-result-set-has-more? ;
+    has-more?>> ;
 
 M: sqlite-statement query-results ( query -- result-set )
     sqlite-maybe-prepare
-    dup statement-handle sqlite-result-set <result-set>
+    dup handle>> sqlite-result-set construct-result-set
     dup advance-row ;
 
 M: sqlite-db begin-transaction ( -- ) "BEGIN" sql-command ;
@@ -119,9 +105,9 @@ M: sqlite-db create-sql-statement ( class -- statement )
     [
         "create table " 0% 0%
         "(" 0% [ ", " 0% ] [
-            dup sql-spec-column-name 0%
+            dup column-name>> 0%
             " " 0%
-            dup sql-spec-type t lookup-type 0%
+            dup type>> t lookup-type 0%
             modifiers 0%
         ] interleave ");" 0%
     ] sqlite-make ;
@@ -134,7 +120,7 @@ M: sqlite-db <insert-native-statement> ( tuple -- statement )
         "insert into " 0% 0%
         "(" 0%
         maybe-remove-id
-        dup [ ", " 0% ] [ sql-spec-column-name 0% ] interleave
+        dup [ ", " 0% ] [ column-name>> 0% ] interleave
         ") values(" 0%
         [ ", " 0% ] [ bind% ] interleave
         ");" 0%
@@ -145,11 +131,11 @@ M: sqlite-db <insert-nonnative-statement> ( tuple -- statement )
 
 : where-primary-key% ( specs -- )
     " where " 0%
-    find-primary-key dup sql-spec-column-name 0% " = " 0% bind% ;
+    find-primary-key dup column-name>> 0% " = " 0% bind% ;
 
 : where-clause ( specs -- )
     " where " 0%
-    [ " and " 0% ] [ dup sql-spec-column-name 0% " = " 0% bind% ] interleave ;
+    [ " and " 0% ] [ dup column-name>> 0% " = " 0% bind% ] interleave ;
 
 M: sqlite-db <update-tuple-statement> ( class -- statement )
     [
@@ -157,7 +143,7 @@ M: sqlite-db <update-tuple-statement> ( class -- statement )
         0%
         " set " 0%
         dup remove-id
-        [ ", " 0% ] [ dup sql-spec-column-name 0% " = " 0% bind% ] interleave
+        [ ", " 0% ] [ dup column-name>> 0% " = " 0% bind% ] interleave
         where-primary-key%
     ] sqlite-make ;
 
@@ -166,23 +152,23 @@ M: sqlite-db <delete-tuple-statement> ( specs table -- sql )
         "delete from " 0% 0%
         " where " 0%
         find-primary-key
-        dup sql-spec-column-name 0% " = " 0% bind%
+        dup column-name>> 0% " = " 0% bind%
     ] sqlite-make ;
 
 ! : select-interval ( interval name -- ) ;
 ! : select-sequence ( seq name -- ) ;
 
 M: sqlite-db bind% ( spec -- )
-    dup 1, sql-spec-column-name ":" prepend 0% ;
+    dup 1, column-name>> ":" prepend 0% ;
 
 M: sqlite-db <select-by-slots-statement> ( tuple class -- statement )
     [
         "select " 0%
         over [ ", " 0% ]
-        [ dup sql-spec-column-name 0% 2, ] interleave
+        [ dup column-name>> 0% 2, ] interleave
 
         " from " 0% 0%
-        [ sql-spec-slot-name swap get-slot-named ] with subset
+        [ slot-name>> swap get-slot-named ] with subset
         dup empty? [ drop ] [ where-clause ] if ";" 0%
     ] sqlite-make ;
 
index 6b61981119d1c9f56ceb4304fd526da52c80ee21..951ded32ea402806eccd7c00cfe179a8b7e3aa68 100755 (executable)
@@ -260,10 +260,10 @@ C: <secret> secret
 ! [ test-random-id ] test-sqlite
  [ native-person-schema test-tuples ] test-sqlite
  [ assigned-person-schema test-tuples ] test-sqlite
-! [ assigned-person-schema test-repeated-insert ] test-sqlite
-! [ native-person-schema test-tuples ] test-postgresql
-! [ assigned-person-schema test-tuples ] test-postgresql
-! [ assigned-person-schema test-repeated-insert ] test-postgresql
+ [ assigned-person-schema test-repeated-insert ] test-sqlite
+ [ native-person-schema test-tuples ] test-postgresql
+ [ assigned-person-schema test-tuples ] test-postgresql
+ [ assigned-person-schema test-repeated-insert ] test-postgresql
 
 ! \ insert-tuple must-infer
 ! \ update-tuple must-infer
index 497a6c51207c923d0b53d7a5ba3ccfdccbc27f2c..5e0abcd5ba5fa58da1948df4b19f69a543513853 100644 (file)
@@ -36,15 +36,15 @@ MIMIC: bee goodbye hello
 [ { t 1 0 } ] [ 1 0 <hello> bing ] unit-test
 [ 1 ] [ 1 0 <hello> f <goodbye> foo ] unit-test
 [ { t 1 0 } ] [ 1 0 <hello> f <goodbye> bar ] unit-test
-[ { f 1 0 } ] [ f 1 0 <hello> <goodbye> bing ] unit-test
+[ { f 1 0 } ] [ f 1 0 <hello> <goodbye> bing ] unit-test
 [ 3 ] [ 1 0 <hello> 2 whoa ] unit-test
 [ 3 ] [ 1 0 <hello> f <goodbye> 2 whoa ] unit-test
 
 [ ] [ 10 [ "USE: delegate IN: delegate.tests CONSULT: baz goodbye goodbye-these ;" eval ] times ] unit-test
 [ V{ goodbye } ] [ baz protocol-users ] unit-test
 
-[ "USING: delegate ;\nIN: delegate.tests\nPROTOCOL: baz foo bar { whoa 1 } ;\n" ]
-[ [ baz see ] with-string-writer ] unit-test
+[ "USING: delegate ;\nIN: delegate.tests\nPROTOCOL: baz foo bar { whoa 1 } ;\n" ]
+[ [ baz see ] with-string-writer ] unit-test
 
 ! [ ] [ [ baz forget ] with-compilation-unit ] unit-test
 ! [ f ] [ goodbye baz method ] unit-test
index b1435e0dbc15524f2dd19e75a158bda4b0993016..736645890e40dc09e6ff805b1245cd83095e20a6 100755 (executable)
@@ -19,10 +19,5 @@ PROTOCOL: stream-protocol
     make-cell-stream stream-write-table ;
 
 PROTOCOL: definition-protocol
-    where set-where forget uses redefined*
+    where set-where forget uses
     synopsis* definer definition ;
-
-PROTOCOL: prettyprint-section-protocol
-    section-fits? indent-section? unindent-first-line?
-    newline-after?  short-section? short-section long-section
-    <section> delegate>block add-section ;
index 14f0dc41acd066e659f6bb75be97acab1d2c43db..1c0802b721a68ea4c4384f27a0cccc4c0cfeedd6 100755 (executable)
@@ -151,14 +151,14 @@ TUPLE: char-elt ;
     -rot {
         { [ over { 0 0 } = ] [ drop ] }
         { [ over second zero? ] [ >r first 1- r> line-end ] }
-        { [ t ] [ pick call ] }
+        [ pick call ]
     } cond nip ; inline
 
 : (next-char) ( loc document quot -- loc )
     -rot {
         { [ 2dup doc-end = ] [ drop ] }
         { [ 2dup line-end? ] [ drop first 1+ 0 2array ] }
-        { [ t ] [ pick call ] }
+        [ pick call ]
     } cond nip ; inline
 
 M: char-elt prev-elt
index e871d5f808afe6918abeab18627f19d82403ac5d..16de8f5eee5784d0509e3256a05d5406e2cb76d7 100755 (executable)
@@ -3,7 +3,7 @@
 USING: parser kernel namespaces sequences definitions io.files
 inspector continuations tools.crossref tools.vocabs 
 io prettyprint source-files assocs vocabs vocabs.loader
-io.backend splitting classes.tuple ;
+io.backend splitting accessors ;
 IN: editors
 
 TUPLE: no-edit-hook ;
@@ -18,7 +18,7 @@ SYMBOL: edit-hook
 
 : editor-restarts ( -- alist )
     available-editors
-    [ "Load " over append swap ] { } map>assoc ;
+    [ [ "Load " prepend ] keep ] { } map>assoc ;
 
 : no-edit-hook ( -- )
     \ no-edit-hook construct-empty
@@ -26,7 +26,7 @@ SYMBOL: edit-hook
     require ;
 
 : edit-location ( file line -- )
-    >r (normalize-path) "\\\\?\\" ?head drop r>
+    >r (normalize-path) r>
     edit-hook get [ call ] [ no-edit-hook edit-location ] if* ;
 
 : edit ( defspec -- )
@@ -35,18 +35,31 @@ SYMBOL: edit-hook
 : edit-vocab ( name -- )
     vocab-source-path 1 edit-location ;
 
+GENERIC: find-parse-error ( error -- error' )
+
+M: parse-error find-parse-error
+    dup error>> find-parse-error [ ] [ ] ?if ;
+
+M: condition find-parse-error
+    error>> find-parse-error ;
+
+M: object find-parse-error
+    drop f ;
+
 : :edit ( -- )
-    error get delegates [ parse-error? ] find-last nip [
-        dup parse-error-file source-file-path
-        swap parse-error-line edit-location
+    error get find-parse-error [
+        [ file>> path>> ] [ line>> ] bi edit-location
     ] when* ;
 
 : fix ( word -- )
-    "Fixing " write dup pprint " and all usages..." print nl
-    dup usage swap prefix [
-        "Editing " write dup .
-        "RETURN moves on to the next usage, C+d stops." print
-        flush
-        edit
-        readln
+    [ "Fixing " write pprint " and all usages..." print nl ]
+    [ [ usage ] keep prefix ] bi
+    [
+        [ "Editing " write . ]
+        [
+            "RETURN moves on to the next usage, C+d stops." print
+            flush
+            edit
+            readln
+        ] bi
     ] all? drop ;
index d983bd271564dc979217e83e56eb4067a58e3003..6c20aac7f2dcd08232592525f62ca1bd91bbe726 100755 (executable)
@@ -22,11 +22,11 @@ DEFER: (fry)
         drop 1quotation
     ] [
         unclip {
-            { , [ [ curry ] ((fry)) ] }
-            { @ [ [ compose ] ((fry)) ] }
+            { , [ [ curry ] ((fry)) ] }
+            { @ [ [ compose ] ((fry)) ] }
 
             ! to avoid confusion, remove if fry goes core
-            { namespaces:, [ [ curry ] ((fry)) ] }
+            { namespaces:, [ [ curry ] ((fry)) ] }
 
             [ swap >r suffix r> (fry) ]
         } case
index 95a56da2d2b4cd3a189680d8c9e68de25bd3530c..283fea6fcc672e7d005265c7d78fdcf963100010 100644 (file)
@@ -2,6 +2,7 @@ USING: system ;
 IN: hardware-info.backend
 
 HOOK: cpus os ( -- n )
+HOOK: cpu-mhz os ( -- n )
 HOOK: memory-load os ( -- n )
 HOOK: physical-mem os ( -- n )
 HOOK: available-mem os ( -- n )
index 6d27cf52526ba6e6dcafdc4763455cd717966aa2..cc345c7537893237ffb2572bfe8773405974fa9d 100755 (executable)
@@ -3,19 +3,21 @@ combinators vocabs.loader hardware-info.backend system ;
 IN: hardware-info
 
 : write-unit ( x n str -- )
-    [ 2^ /i number>string write bl ] [ write ] bi* ;
+    [ 2^ /f number>string write bl ] [ write ] bi* ;
 
 : kb ( x -- ) 10 "kB" write-unit ;
 : megs ( x -- ) 20 "MB" write-unit ;
 : gigs ( x -- ) 30 "GB" write-unit ;
+: ghz ( x -- ) 1000000000 /f number>string write bl "GHz" write ;
 
 << {
     { [ os windows? ] [ "hardware-info.windows" ] }
     { [ os linux? ] [ "hardware-info.linux" ] }
     { [ os macosx? ] [ "hardware-info.macosx" ] }
-    { [ t ] [ f ] }
+    [ f ]
 } cond [ require ] when* >>
 
 : hardware-report. ( -- )
     "CPUs: " write cpus number>string write nl
+    "CPU Speed: " write cpu-mhz ghz nl
     "Physical RAM: " write physical-mem megs nl ;
index dac052a1dedb6d36daceb740bfc0a976b2bc65eb..91838d2a53f194ca4cf30baed31adcce4b9ae7e8 100644 (file)
@@ -41,7 +41,7 @@ M: macosx physical-mem ( -- n ) { 6 5 } sysctl-query-uint ;
 : machine-arch ( -- n ) { 6 12 } sysctl-query-string ;
 : vector-unit ( -- n ) { 6 13 } sysctl-query-uint ;
 : bus-frequency ( -- n ) { 6 14 } sysctl-query-uint ;
-: cpu-frequency ( -- n ) { 6 15 } sysctl-query-uint ;
+M: macosx cpu-mhz ( -- n ) { 6 15 } sysctl-query-uint ;
 : cacheline-size ( -- n ) { 6 16 } sysctl-query-uint ;
 : l1-icache-size ( -- n ) { 6 17 } sysctl-query-uint ;
 : l1-dcache-size ( -- n ) { 6 18 } sysctl-query-uint ;
index 55c2ac6c0d9faaa9764b249780ca504d7f2ab40d..c61a3c8b8a4e150bd613f7fe78c4d3b1777b4f16 100755 (executable)
@@ -1,5 +1,5 @@
 USING: alien.c-types hardware-info kernel math namespaces
-windows windows.kernel32 hardware-info.backend ;
+windows windows.kernel32 hardware-info.backend system ;
 IN: hardware-info.windows.ce
 
 : memory-status ( -- MEMORYSTATUS )
index 075ce2d0e8dbff8437414c70d7229ef76c2ccf0f..9b21bf7fff552f76ceb591ae7d49a732b82f0a71 100755 (executable)
@@ -199,7 +199,7 @@ ARTICLE: "cookbook-io" "Input and output cookbook"
 }
 "Convert a file of 4-byte cells from little to big endian or vice versa, by directly mapping it into memory and operating on it with sequence words:"
 { $code
-    "\"mydata.dat\" dup file-info file-info-length ["
+    "\"mydata.dat\" dup file-info size>> ["
     "    4 <sliced-groups> [ reverse-here ] change-each"
     "] with-mapped-file"
 }
@@ -224,7 +224,7 @@ $nl
     ":errors - print 2 compiler errors."
     ":warnings - print 50 compiler warnings."
 }
-"These warnings arise from the compiler's stack effect checker. Warnings are non-fatal conditions -- not all code has a static stack effect, so you try to minimize warnings but understand that in many cases they cannot be eliminated. Errors indicate programming mistakes, such as erronous stack effect declarations."
+"These warnings arise from the compiler's stack effect checker. Warnings are non-fatal conditions -- not all code has a static stack effect, so you try to minimize warnings but understand that in many cases they cannot be eliminated. Errors indicate programming mistakes, such as erroneous stack effect declarations."
 { $references
     "To learn more about the compiler and static stack effect inference, read these articles:"
     "compiler"
@@ -259,7 +259,7 @@ $nl
 { $code "#! /usr/bin/env factor -script" }
 "Running the text file will run it through Factor, assuming the " { $snippet "factor" } " binary is in your " { $snippet "$PATH" } "."
 $nl
-"The space between " { $snippet "#!" } " and " { $snippet "/usr/bin/env" } " is necessary, since " { $link POSTPONE: #! } " is a parsing word, and a syntax error would otherwise result. The " { $snippet "-script" } " switch supresses compiler messages, and exits Factor when the script finishes."
+"The space between " { $snippet "#!" } " and " { $snippet "/usr/bin/env" } " is necessary, since " { $link POSTPONE: #! } " is a parsing word, and a syntax error would otherwise result. The " { $snippet "-script" } " switch suppresses compiler messages, and exits Factor when the script finishes."
 { $references
     { }
     "cli"
@@ -273,7 +273,7 @@ $nl
 $nl
 "Keep the following guidelines in mind to avoid losing your sense of balance:"
 { $list
-    "SImplify, simplify, simplify. Break your program up into small words which operate on a few values at a time. Most word definitions should fit on a single line; very rarely should they exceed two or three lines."
+    "Simplify, simplify, simplify. Break your program up into small words which operate on a few values at a time. Most word definitions should fit on a single line; very rarely should they exceed two or three lines."
     "In addition to keeping your words short, keep them meaningful. Give them good names, and make sure each word only does one thing. Try documenting your words; if the documentation for a word is unclear or complex, chances are the word definition is too. Don't be afraid to refactor your code."
     "If your code looks repetitive, factor it some more."
     "If after factoring, your code still looks repetitive, introduce combinators."
@@ -285,7 +285,7 @@ $nl
     "Every time you define a word which simply manipulates sequences, hashtables or objects in an abstract way which is not related to your program domain, check the library to see if you can reuse an existing definition."
     { "Learn to use the " { $link "inference" } " tool." }
     { "Write unit tests. Factor provides good support for unit testing; see " { $link "tools.test" } ". Once your program has a good test suite you can refactor with confidence and catch regressions early." }
-    "Don't write Factor as if it were C. Imperitive programming and indexed loops are almost always not the most idiomatic solution."
+    "Don't write Factor as if it were C. Imperative programming and indexed loops are almost always not the most idiomatic solution."
     { "Use sequences, assocs and objects to group related data. Object allocation is very cheap. Don't be afraid to create tuples, pairs and triples. Don't be afraid of operations which allocate new objects either, such as " { $link append } "." }
     { "If you find yourself writing a loop with a sequence and an index, there's almost always a better way. Learn the " { $link "sequences-combinators" } " by heart." }
     { "If you find yourself writing a heavily nested loop which performs several steps on each iteration, there is almost always a better way. Break the problem down into a series of passes over the data instead, gradually transforming it into the desired result with a series of simple loops. Factor the loops out and reuse them. If you're working on anything math-related, learn " { $link "math-vectors" } " by heart." }
@@ -312,7 +312,7 @@ ARTICLE: "cookbook-pitfalls" "Pitfalls to avoid"
     $nl
     "Unit tests for the " { $vocab-link "inference" } " vocabulary can be used to ensure that any methods your vocabulary defines on core generic words have static stack effects:"
     { $code "\"inference\" test" }
-    "In general, you should strive to write code with inferrable stack effects, even for sections of a program which are not performance sensitive; the " { $link infer. } " tool together with the optimizing compiler's error reporting can catch many bugs ahead of time." }
+    "In general, you should strive to write code with inferable stack effects, even for sections of a program which are not performance sensitive; the " { $link infer. } " tool together with the optimizing compiler's error reporting can catch many bugs ahead of time." }
     { "Be careful when calling words which access variables from a " { $link make-assoc } " which constructs an assoc with arbitrary keys, since those keys might shadow variables." }
     { "If " { $link run-file } " throws a stack depth assertion, it means that the top-level form in the file left behind values on the stack. The stack depth is compared before and after loading a source file, since this type of situation is almost always an error. If you have a legitimate need to load a source file which returns data in some manner, define a word in the source file which produces this data on the stack and call the word after loading the file." }
 } ;
index e347fde051e6e7c4c2d71cc16a3551e31dc10d29..0b17461a9964360c4b71caa3d9f95468f57dd382 100644 (file)
@@ -14,7 +14,7 @@ M: link uses
     collect-elements [ \ f or ] map ;
 
 : help-path ( topic -- seq )
-    [ dup ] [ [ article-parent ] keep ] [ ] unfold nip 1 tail ;
+    [ article-parent ] follow 1 tail ;
 
 : set-article-parents ( parent article -- )
     article-children [ set-article-parent ] with each ;
index 847a5952af024b3a4b102c7a204df63093af7ac5..acdbca82eebfc68c25a57fa5e650693d6e253551 100755 (executable)
@@ -2,7 +2,8 @@ USING: help help.markup help.syntax help.definitions help.topics
 namespaces words sequences classes assocs vocabs kernel arrays
 prettyprint.backend kernel.private io generic math system
 strings sbufs vectors byte-arrays bit-arrays float-arrays
-quotations io.streams.byte-array io.encodings.string ;
+quotations io.streams.byte-array io.encodings.string
+classes.builtin ;
 IN: help.handbook
 
 ARTICLE: "conventions" "Conventions"
index 4e8424f7a3340f6ce6f143050ec92821b29849fa..aa2704a799fc1b17831a99a8487e8e793d1c29c5 100755 (executable)
@@ -139,7 +139,7 @@ M: word set-article-parent swap "help-parent" set-word-prop ;
     {
         { [ dup empty? ] [ (:help-none) ] }
         { [ dup length 1 = ] [ first help ] }
-        { [ t ] [ (:help-multi) ] }
+        [ (:help-multi) ]
     } cond (:help-debugger) ;
 
 : remove-article ( name -- )
index 9450f87215d93ee33bf5a2947cedc2c2c7a1b8cb..65120a5d01b977e57fc421c47744e04e861b0ca3 100755 (executable)
@@ -1,4 +1,4 @@
-! Copyright (C) 2005, 2007 Slava Pestov.
+! Copyright (C) 2005, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays kernel parser sequences words help help.topics
 namespaces vocabs definitions compiler.units ;
@@ -16,4 +16,7 @@ IN: help.syntax
     over add-article >link r> remember-definition ; parsing
 
 : ABOUT:
-    scan-object in get vocab set-vocab-help ; parsing
+    scan-object
+    in get vocab
+    dup changed-definition
+    set-vocab-help ; parsing
index 5ed9ab84c1d43d1bba9db0b4982fc000f62ae73d..3078cf23a52fb3134c41b8fb37dbbaf2675ff95f 100644 (file)
@@ -92,7 +92,7 @@ M: printer print-tag ( tag -- )
             [ print-closing-named-tag ] }
         { [ dup tag-name string? ]
             [ print-opening-named-tag ] }
-        { [ t ] [ <unknown-tag-error> throw ] }
+        [ <unknown-tag-error> throw ]
     } cond ;
 
 SYMBOL: tablestack
index 6ff4829b486cc6e36d003dd628242b4426c08dc4..a6afe804437b2f521b2a2bf4fcb64cc5d1013798 100755 (executable)
@@ -145,10 +145,10 @@ TUPLE: cookie name value path domain expires http-only ;
 
 : (unparse-cookie) ( key value -- )
     {
-        { [ dup f eq? ] [ 2drop ] }
-        { [ dup t eq? ] [ drop , ] }
-        { [ t ] [ "=" swap 3append , ] }
-    } cond ;
+        { f [ drop ] }
+        { t [ , ] }
+        [ "=" swap 3append , ]
+    } case ;
 
 : unparse-cookie ( cookie -- strings )
     [
@@ -399,7 +399,7 @@ body ;
         { [ dup not ] [ drop ] }
         { [ dup string? ] [ write ] }
         { [ dup callable? ] [ call ] }
-        { [ t ] [ stdio get stream-copy ] }
+        [ stdio get stream-copy ]
     } cond ;
 
 M: response write-response ( respose -- )
index 2cc0f80f030e43d24d62c04ea340dc96aaf103f6..e1561bce893daf76492fbe392e966dfbcbdd9605 100755 (executable)
@@ -89,7 +89,7 @@ SYMBOL: form-hook
     {
         { [ over "http://" head? ] [ link>string ] }
         { [ over "/" head? ] [ absolute-redirect ] }
-        { [ t ] [ relative-redirect ] }
+        [ relative-redirect ]
     } cond ;
 
 : <redirect> ( to query code message -- response )
index 905c7320ca7096aa7901e2d2de0a781633cb79a2..8632e0f139e8f1e7154eebcd24f902f79367c678 100755 (executable)
@@ -10,7 +10,7 @@ IN: http.server.static
 TUPLE: file-responder root hook special ;\r
 \r
 : file-http-date ( filename -- string )\r
-    file-info file-info-modified timestamp>http-string ;\r
+    file-info modified>> timestamp>http-string ;\r
 \r
 : last-modified-matches? ( filename -- ? )\r
     file-http-date dup [\r
@@ -27,7 +27,7 @@ TUPLE: file-responder root hook special ;
     [\r
         <content>\r
         swap\r
-        [ file-info file-info-size "content-length" set-header ]\r
+        [ file-info size>> "content-length" set-header ]\r
         [ file-http-date "last-modified" set-header ]\r
         [ '[ , binary <file-reader> stdio get stream-copy ] >>body ]\r
         tri\r
index f3d9d54a25e91acd34884f66c0c424a99e8acd08..6cd5c78b7225e5637e21c5358f41625a39eeb3e2 100755 (executable)
@@ -26,7 +26,7 @@ M: template-lexer skip-word
         {
             { [ 2dup nth CHAR: " = ] [ drop 1+ ] }
             { [ 2dup swap tail-slice "%>" head? ] [ drop 2 + ] }
-            { [ t ] [ f skip ] }
+            [ f skip ]
         } cond
     ] change-lexer-column ;
 
index 0f6ca3a2c91f171cee5338ca5ffabb30043a39ba..4446b82f208f2ffd91ebc0dacc7287b9234c71b2 100755 (executable)
@@ -129,9 +129,6 @@ HELP: <process>
 { $values { "process" process } }
 { $description "Creates a new, empty process. It must be filled in before being passed to " { $link run-process } "." } ;
 
-HELP: process-stream
-{ $class-description "A bidirectional stream for interacting with a running process. Instances are created by calling " { $link <process-stream> } ". The " { $link process-stream-process } " slot holds a " { $link process } " instance." } ;
-
 HELP: <process-stream>
 { $values
   { "desc" "a launch descriptor" }
@@ -144,7 +141,7 @@ HELP: with-process-stream
   { "desc" "a launch descriptor" }
   { "quot" quotation }
   { "status" "an exit code" } }
-{ $description "Calls " { $snippet "quot" } " in a dynamic scope where " { $link stdio } " is rebound to a " { $link process-stream } ". After the quotation returns, waits for the process to end and outputs the exit code." } ;
+{ $description "Calls " { $snippet "quot" } " in a dynamic scope where " { $link stdio } " is rebound to a process stream. After the quotation returns, waits for the process to end and outputs the exit code." } ;
 
 HELP: wait-for-process
 { $values { "process" process } { "status" integer } }
index 20c5bb92c99f8a0e1929ca0747e4a11fb1b50400..00352adc7b5463490164f0c82d6c97de27d41ea9 100755 (executable)
@@ -3,7 +3,7 @@
 USING: io io.backend io.timeouts system kernel namespaces
 strings hashtables sequences assocs combinators vocabs.loader
 init threads continuations math io.encodings io.streams.duplex
-io.nonblocking accessors ;
+io.nonblocking accessors concurrency.flags ;
 IN: io.launcher
 
 TUPLE: process < identity-tuple
@@ -56,14 +56,25 @@ SYMBOL: processes
 
 [ H{ } clone processes set-global ] "io.launcher" add-init-hook
 
-HOOK: register-process io-backend ( process -- )
+HOOK: wait-for-processes io-backend ( -- ? )
 
-M: object register-process drop ;
+SYMBOL: wait-flag
+
+: wait-loop ( -- )
+    processes get assoc-empty?
+    [ wait-flag get-global lower-flag ]
+    [ wait-for-processes [ 100 sleep ] when ] if ;
+
+: start-wait-thread ( -- )
+    <flag> wait-flag set-global
+    [ wait-loop t ] "Process wait" spawn-server drop ;
+
+[ start-wait-thread ] "io.launcher" add-init-hook
 
 : process-started ( process handle -- )
     >>handle
-    V{ } clone over processes get set-at
-    register-process ;
+    V{ } clone swap processes get set-at
+    wait-flag get-global raise-flag ;
 
 M: process hashcode* process-handle hashcode* ;
 
@@ -139,18 +150,18 @@ M: process timed-out kill-process ;
 
 HOOK: (process-stream) io-backend ( process -- handle in out )
 
-TUPLE: process-stream process ;
+: <process-stream*> ( desc encoding -- stream process )
+    >r >process dup dup (process-stream) <reader&writer>
+    r> <encoder-duplex> -roll
+    process-started ;
 
 : <process-stream> ( desc encoding -- stream )
-    >r >process dup dup (process-stream)
-    >r >r process-started process-stream construct-boa
-    r> r> <reader&writer> r> <encoder-duplex>
-    over set-delegate ;
+    <process-stream*> drop ; inline
 
 : with-process-stream ( desc quot -- status )
-    swap <process-stream>
+    swap <process-stream*> >r
     [ swap with-stream ] keep
-    process>> wait-for-process ; inline
+    r> wait-for-process ; inline
 
 : notify-exit ( process status -- )
     >>status
index b17d7aeab932a25db6aaa3d988e9848136c74472..a00f7cd92b38248bc8e734e51986d8b97036dea9 100755 (executable)
@@ -1,10 +1,10 @@
 USING: io io.mmap io.files kernel tools.test continuations
-sequences io.encodings.ascii ;
+sequences io.encodings.ascii accessors ;
 IN: io.mmap.tests
 
 [ "mmap-test-file.txt" resource-path delete-file ] ignore-errors
 [ ] [ "12345" "mmap-test-file.txt" resource-path ascii set-file-contents ] unit-test
-[ ] [ "mmap-test-file.txt" resource-path dup file-info file-info-size [ CHAR: 2 0 pick set-nth drop ] with-mapped-file ] unit-test
-[ 5 ] [ "mmap-test-file.txt" resource-path dup file-info file-info-size [ length ] with-mapped-file ] unit-test
+[ ] [ "mmap-test-file.txt" resource-path dup file-info size>> [ CHAR: 2 0 pick set-nth drop ] with-mapped-file ] unit-test
+[ 5 ] [ "mmap-test-file.txt" resource-path dup file-info size>> [ length ] with-mapped-file ] unit-test
 [ "22345" ] [ "mmap-test-file.txt" resource-path ascii file-contents ] unit-test
 [ "mmap-test-file.txt" resource-path delete-file ] ignore-errors
index 76a354b0bd8926bf57524e50e983842bba0aac25..cd6a06a8e97002adf527e2183203e50c99fc651c 100755 (executable)
 IN: io.monitors\r
-USING: help.markup help.syntax continuations ;\r
+USING: help.markup help.syntax continuations\r
+concurrency.mailboxes quotations ;\r
+\r
+HELP: with-monitors\r
+{ $values { "quot" quotation } }\r
+{ $description "Calls a quotation in a new dynamic scope where file system monitor operations can be performed." }\r
+{ $errors "Throws an error if the platform does not support file system change monitors." } ;\r
 \r
 HELP: <monitor>\r
 { $values { "path" "a pathname string" } { "recursive?" "a boolean" } { "monitor" "a new monitor" } }\r
-{ $description "Opens a file system change monitor which listens for changes on " { $snippet "path" } ". The boolean indicates whether changes in subdirectories should be reported."\r
-$nl\r
-"Not all operating systems support recursive monitors; if recursive monitoring is not available, an error is thrown and the caller must implement alternative logic for monitoring subdirectories." } ;\r
+{ $contract "Opens a file system change monitor which listens for changes on " { $snippet "path" } ". The boolean indicates whether changes in subdirectories should be reported." }\r
+{ $errors "Throws an error if the pathname does not exist, if a monitor could not be created or if the platform does not support monitors." } ;\r
+\r
+HELP: (monitor)\r
+{ $values { "path" "a pathname string" } { "recursive?" "a boolean" } { "mailbox" mailbox } { "monitor" "a new monitor" } }\r
+{ $contract "Opens a file system change monitor which listens for changes on " { $snippet "path" } " and posts notifications to " { $snippet "mailbox" } " as triples with shape " { $snippet "{ path changed monitor } " } ". The boolean indicates whether changes in subdirectories should be reported." }\r
+{ $errors "Throws an error if the pathname does not exist, if a monitor could not be created or if the platform does not support monitors." } ;\r
 \r
 HELP: next-change\r
 { $values { "monitor" "a monitor" } { "path" "a pathname string" } { "changed" "a change descriptor" } }\r
-{ $description "Waits for file system changes and outputs the pathname of the first changed file. The change descriptor is aq sequence of symbols documented in " { $link "io.monitors.descriptors" } "." } ;\r
+{ $contract "Waits for file system changes and outputs the pathname of the first changed file. The change descriptor is a sequence of symbols documented in " { $link "io.monitors.descriptors" } "." }\r
+{ $errors "Throws an error if the monitor is closed from another thread." } ;\r
 \r
 HELP: with-monitor\r
 { $values { "path" "a pathname string" } { "recursive?" "a boolean" } { "quot" "a quotation with stack effect " { $snippet "( monitor -- )" } } }\r
-{ $description "Opens a file system change monitor and passes it to the quotation. Closes the monitor after the quotation returns or throws an error." } ;\r
+{ $description "Opens a file system change monitor and passes it to the quotation. Closes the monitor after the quotation returns or throws an error." }\r
+{ $errors "Throws an error if the pathname does not exist, if a monitor could not be created or if the platform does not support monitors." } ;\r
 \r
 HELP: +add-file+\r
-{ $description "Indicates that the file has been added to the directory." } ;\r
+{ $description "Indicates that a file has been added to its parent directory." } ;\r
 \r
 HELP: +remove-file+\r
-{ $description "Indicates that the file has been removed from the directory." } ;\r
+{ $description "Indicates that a file has been removed from its parent directory." } ;\r
 \r
 HELP: +modify-file+\r
-{ $description "Indicates that the file contents have changed." } ;\r
+{ $description "Indicates that a file's contents have changed." } ;\r
+\r
+HELP: +rename-file-old+\r
+{ $description "Indicates that a file has been renamed, and this is the old name." } ;\r
+\r
+HELP: +rename-file-new+\r
+{ $description "Indicates that a file has been renamed, and this is the new name." } ;\r
 \r
 HELP: +rename-file+\r
-{ $description "Indicates that file has been renamed." } ;\r
+{ $description "Indicates that file has been renamed." } ;\r
 \r
 ARTICLE: "io.monitors.descriptors" "File system change descriptors"\r
 "Change descriptors output by " { $link next-change } ":"\r
 { $subsection +add-file+ }\r
 { $subsection +remove-file+ }\r
 { $subsection +modify-file+ }\r
-{ $subsection +rename-file+ }\r
-{ $subsection +add-file+ } ;\r
+{ $subsection +rename-file-old+ }\r
+{ $subsection +rename-file-new+ }\r
+{ $subsection +rename-file+ } ;\r
+\r
+ARTICLE: "io.monitors.platforms" "Monitors on different platforms"\r
+"Whether the " { $snippet "path" } " output value of " { $link next-change } " contains an absolute path or a path relative to the path given to " { $link <monitor> } " is platform-specific. User code should not assume either case."\r
+{ $heading "Mac OS X" }\r
+"Factor uses " { $snippet "FSEventStream" } "s to implement monitors on Mac OS X. This requires Mac OS X 10.5 or later."\r
+$nl\r
+{ $snippet "FSEventStream" } "s always monitor directory hierarchies recursively, and the " { $snippet "recursive?" } " parameter to " { $link <monitor> } " has no effect."\r
+$nl\r
+"The " { $snippet "changed" } " output value of the " { $link next-change } " word always outputs " { $link +modify-file+ } " and the " { $snippet "path" } " output value is always the directory containing the file that changed. Unlike other platforms, fine-grained information is not available."\r
+{ $heading "Windows" }\r
+"Factor uses " { $snippet "ReadDirectoryChanges" } " to implement monitors on Windows."\r
+$nl\r
+"Both recursive and non-recursive monitors are directly supported by the operating system."\r
+{ $heading "Linux" }\r
+"Factor uses " { $snippet "inotify" } " to implement monitors on Linux. This requires Linux kernel version 2.6.16 or later."\r
+$nl\r
+"Factor simulates recursive monitors by creating a hierarchy of monitors for every subdirectory, since " { $snippet "inotify" } " can only monitor a single directory. This is transparent to user code."\r
+$nl\r
+"Inside a single " { $link with-monitors } " scope, only one monitor may be created for any given directory."\r
+{ $heading "BSD" }\r
+"Factor uses " { $snippet "kqueue" } " to implement monitors on BSD."\r
+$nl\r
+"The " { $snippet "kqueue" } " system is limited to monitoring individual files and directories. Monitoring a directory only notifies of files being added and removed to the directory itself, not of changes to file contents."\r
+{ $heading "Windows CE" }\r
+"Windows CE does not support monitors." ;\r
 \r
 ARTICLE: "io.monitors" "File system change monitors"\r
 "File system change monitors listen for changes to file names, attributes and contents under a specified directory. They can optionally be recursive, in which case subdirectories are also monitored."\r
 $nl\r
+"Monitoring operations must be wrapped in a combinator:"\r
+{ $subsection with-monitors }\r
 "Creating a file system change monitor and listening for changes:"\r
 { $subsection <monitor> }\r
 { $subsection next-change }\r
+"An alternative programming style is where instead of having a thread listen for changes on a monitor, change notifications are posted to a mailbox:"\r
+{ $subsection (monitor) }\r
 { $subsection "io.monitors.descriptors" }\r
-"Monitors are closed by calling " { $link dispose } " or " { $link with-disposal } "."\r
-$nl\r
-"A utility combinator which opens a monitor and cleans it up after:"\r
+{ $subsection "io.monitors.platforms" } \r
+"Monitors are closed by calling " { $link dispose } " or " { $link with-disposal } ". An easy way to pair construction with disposal is to use a combinator:"\r
 { $subsection with-monitor }\r
-"An example which watches the Factor directory for changes:"\r
+"Monitors support the " { $link "io.timeouts" } "."\r
+$nl\r
+"An example which watches a directory for changes:"\r
 { $code\r
     "USE: io.monitors"\r
     ": watch-loop ( monitor -- )"\r
     "    dup next-change . . nl nl flush watch-loop ;"\r
     ""\r
-    "\"\" resource-path f [ watch-loop ] with-monitor"\r
+    ": watch-directory ( path -- )"\r
+    "    [ t [ watch-loop ] with-monitor ] with-monitors"\r
 } ;\r
 \r
 ABOUT: "io.monitors"\r
diff --git a/extra/io/monitors/monitors-tests.factor b/extra/io/monitors/monitors-tests.factor
new file mode 100644 (file)
index 0000000..ab919dd
--- /dev/null
@@ -0,0 +1,91 @@
+IN: io.monitors.tests
+USING: io.monitors tools.test io.files system sequences
+continuations namespaces concurrency.count-downs kernel io
+threads calendar prettyprint ;
+
+os { winnt linux macosx } member? [
+    [
+        [ "monitor-test" temp-file delete-tree ] ignore-errors
+
+        [ ] [ "monitor-test" temp-file make-directory ] unit-test
+
+        [ ] [ "monitor-test" temp-file t <monitor> "m" set ] unit-test
+
+        [ ] [ "monitor-test/a1" temp-file make-directory ] unit-test
+
+        [ ] [ "monitor-test/a2" temp-file make-directory ] unit-test
+
+        [ ] [ "monitor-test/a1" temp-file "monitor-test/a2" temp-file move-file-into ] unit-test
+
+        [ t ] [ "monitor-test/a2/a1" temp-file exists? ] unit-test
+
+        [ ] [ "monitor-test/a2/a1/a3.txt" temp-file touch-file ] unit-test
+
+        [ t ] [ "monitor-test/a2/a1/a3.txt" temp-file exists? ] unit-test
+
+        [ ] [ "monitor-test/a2/a1/a4.txt" temp-file touch-file ] unit-test
+        [ ] [ "monitor-test/a2/a1/a5.txt" temp-file touch-file ] unit-test
+        [ ] [ "monitor-test/a2/a1/a4.txt" temp-file delete-file ] unit-test
+        [ ] [ "monitor-test/a2/a1/a5.txt" temp-file "monitor-test/a2/a1/a4.txt" temp-file move-file ] unit-test
+
+        [ t ] [ "monitor-test/a2/a1/a4.txt" temp-file exists? ] unit-test
+
+        [ ] [ "m" get dispose ] unit-test
+    ] with-monitors
+
+    
+    [
+        [ "monitor-test" temp-file delete-tree ] ignore-errors
+        
+        [ ] [ "monitor-test/xyz" temp-file make-directories ] unit-test
+        
+        [ ] [ "monitor-test" temp-file t <monitor> "m" set ] unit-test
+        
+        [ ] [ 1 <count-down> "b" set ] unit-test
+        
+        [ ] [ 1 <count-down> "c1" set ] unit-test
+        
+        [ ] [ 1 <count-down> "c2" set ] unit-test
+        
+        [ ] [
+            [
+                "b" get count-down
+
+                [
+                    "m" get next-change drop
+                    dup print flush
+                    dup parent-directory
+                    [ right-trim-separators "xyz" tail? ] either? not
+                ] [ ] [ ] while
+
+                "c1" get count-down
+                
+                [
+                    "m" get next-change drop
+                    dup print flush
+                    dup parent-directory
+                    [ right-trim-separators "yxy" tail? ] either? not
+                ] [ ] [ ] while
+
+                "c2" get count-down
+            ] "Monitor test thread" spawn drop
+        ] unit-test
+        
+        [ ] [ "b" get await ] unit-test
+        
+        [ ] [ "monitor-test/xyz/test.txt" temp-file touch-file ] unit-test
+
+        [ ] [ "c1" get 15 seconds await-timeout ] unit-test
+        
+        [ ] [ "monitor-test/subdir/blah/yxy" temp-file make-directories ] unit-test
+
+        [ ] [ "monitor-test/subdir/blah/yxy/test.txt" temp-file touch-file ] unit-test
+
+        [ ] [ "c2" get 15 seconds await-timeout ] unit-test
+
+        ! Dispose twice
+        [ ] [ "m" get dispose ] unit-test
+
+        [ ] [ "m" get dispose ] unit-test
+    ] with-monitors
+] when
index 1678c2de41a82356e7ebbb21a2e23e36b04d34d4..51cbdd5b1b70410f54f7a2d5d294456c428ccf85 100755 (executable)
@@ -1,82 +1,50 @@
 ! Copyright (C) 2008 Slava Pestov.\r
 ! See http://factorcode.org/license.txt for BSD license.\r
 USING: io.backend kernel continuations namespaces sequences\r
-assocs hashtables sorting arrays threads boxes io.timeouts ;\r
+assocs hashtables sorting arrays threads boxes io.timeouts\r
+accessors concurrency.mailboxes ;\r
 IN: io.monitors\r
 \r
-<PRIVATE\r
+HOOK: init-monitors io-backend ( -- )\r
 \r
-TUPLE: monitor queue closed? ;\r
+HOOK: dispose-monitors io-backend ( -- )\r
 \r
-: check-monitor ( monitor -- )\r
-    monitor-closed? [ "Monitor closed" throw ] when ;\r
-\r
-: (monitor) ( delegate -- monitor )\r
-    H{ } clone {\r
-        set-delegate\r
-        set-monitor-queue\r
-    } monitor construct ;\r
-\r
-GENERIC: fill-queue ( monitor -- )\r
-\r
-: changed-file ( changed path -- )\r
-    namespace [ append ] change-at ;\r
-\r
-: dequeue-change ( assoc -- path changes )\r
-    delete-any prune natural-sort >array ;\r
-\r
-M: monitor dispose\r
-    dup check-monitor\r
-    t over set-monitor-closed?\r
-    delegate dispose ;\r
-\r
-! Simple monitor; used on Linux and Mac OS X. On Windows,\r
-! monitors are full-fledged ports.\r
-TUPLE: simple-monitor handle callback timeout ;\r
-\r
-M: simple-monitor timeout simple-monitor-timeout ;\r
-\r
-M: simple-monitor set-timeout set-simple-monitor-timeout ;\r
+: with-monitors ( quot -- )\r
+    [\r
+        init-monitors\r
+        [ dispose-monitors ] [ ] cleanup\r
+    ] with-scope ; inline\r
 \r
-: <simple-monitor> ( handle -- simple-monitor )\r
-    f (monitor) <box> {\r
-        set-simple-monitor-handle\r
-        set-delegate\r
-        set-simple-monitor-callback\r
-    } simple-monitor construct ;\r
+TUPLE: monitor < identity-tuple path queue timeout ;\r
 \r
-: construct-simple-monitor ( handle class -- simple-monitor )\r
-    >r <simple-monitor> r> construct-delegate ; inline\r
+M: monitor hashcode* path>> hashcode* ;\r
 \r
-: notify-callback ( simple-monitor -- )\r
-    simple-monitor-callback [ resume ] if-box? ;\r
+M: monitor timeout timeout>> ;\r
 \r
-M: simple-monitor timed-out\r
-    notify-callback ;\r
+M: monitor set-timeout (>>timeout) ;\r
 \r
-M: simple-monitor fill-queue ( monitor -- )\r
-    [\r
-        [ swap simple-monitor-callback >box ]\r
-        "monitor" suspend drop\r
-    ] with-timeout\r
-    check-monitor ;\r
+: construct-monitor ( path mailbox class -- monitor )\r
+    construct-empty\r
+        swap >>queue\r
+        swap >>path ; inline\r
 \r
-M: simple-monitor dispose ( monitor -- )\r
-    dup delegate dispose notify-callback ;\r
+: queue-change ( path changes monitor -- )\r
+    3dup and and\r
+    [ [ 3array ] keep queue>> mailbox-put ] [ 3drop ] if ;\r
 \r
-PRIVATE>\r
+HOOK: (monitor) io-backend ( path recursive? mailbox -- monitor )\r
 \r
-HOOK: <monitor> io-backend ( path recursive? -- monitor )\r
+: <monitor> ( path recursive? -- monitor )\r
+    <mailbox> (monitor) ;\r
 \r
 : next-change ( monitor -- path changed )\r
-    dup check-monitor\r
-    dup monitor-queue dup assoc-empty? [\r
-        drop dup fill-queue next-change\r
-    ] [ nip dequeue-change ] if ;\r
+    [ queue>> ] [ timeout ] bi mailbox-get-timeout first2 ;\r
 \r
 SYMBOL: +add-file+\r
 SYMBOL: +remove-file+\r
 SYMBOL: +modify-file+\r
+SYMBOL: +rename-file-old+\r
+SYMBOL: +rename-file-new+\r
 SYMBOL: +rename-file+\r
 \r
 : with-monitor ( path recursive? quot -- )\r
diff --git a/extra/io/monitors/recursive/recursive-tests.factor b/extra/io/monitors/recursive/recursive-tests.factor
new file mode 100644 (file)
index 0000000..3182747
--- /dev/null
@@ -0,0 +1,59 @@
+USING: accessors math kernel namespaces continuations
+io.files io.monitors io.monitors.recursive io.backend
+concurrency.mailboxes
+tools.test ;
+IN: io.monitors.recursive.tests
+
+\ pump-thread must-infer
+
+SINGLETON: mock-io-backend
+
+TUPLE: counter i ;
+
+SYMBOL: dummy-monitor-created
+SYMBOL: dummy-monitor-disposed
+
+TUPLE: dummy-monitor < monitor ;
+
+M: dummy-monitor dispose
+    drop dummy-monitor-disposed get [ 1+ ] change-i drop ;
+
+M: mock-io-backend (monitor)
+    nip
+    over exists? [
+        dummy-monitor construct-monitor
+        dummy-monitor-created get [ 1+ ] change-i drop
+    ] [
+        "Does not exist" throw
+    ] if ;
+
+M: mock-io-backend link-info
+    global [ link-info ] bind ;
+
+[ ] [ 0 counter construct-boa dummy-monitor-created set ] unit-test
+[ ] [ 0 counter construct-boa dummy-monitor-disposed set ] unit-test
+
+[ ] [
+    mock-io-backend io-backend [
+        "" resource-path <mailbox> <recursive-monitor> dispose
+    ] with-variable
+] unit-test
+
+[ t ] [ dummy-monitor-created get i>> 0 > ] unit-test
+
+[ t ] [ dummy-monitor-created get i>> dummy-monitor-disposed get i>> = ] unit-test
+
+[ "doesnotexist" temp-file delete-tree ] ignore-errors
+
+[
+    mock-io-backend io-backend [
+        "doesnotexist" temp-file <mailbox> <recursive-monitor> dispose
+    ] with-variable
+] must-fail
+
+[ ] [
+    mock-io-backend io-backend [
+        "" resource-path <mailbox> <recursive-monitor>
+        [ dispose ] [ dispose ] bi
+    ] with-variable
+] unit-test
diff --git a/extra/io/monitors/recursive/recursive.factor b/extra/io/monitors/recursive/recursive.factor
new file mode 100644 (file)
index 0000000..8c2560f
--- /dev/null
@@ -0,0 +1,105 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors sequences assocs arrays continuations combinators kernel
+threads concurrency.messaging concurrency.mailboxes
+concurrency.promises
+io.files io.monitors ;
+IN: io.monitors.recursive
+
+! Simulate recursive monitors on platforms that don't have them
+
+TUPLE: recursive-monitor < monitor children thread ready ;
+
+DEFER: add-child-monitor
+
+: qualify-path ( path -- path' )
+    monitor tget path>> prepend-path ;
+
+: add-child-monitors ( path -- )
+    #! We yield since this directory scan might take a while.
+    [
+        directory* [ first add-child-monitor yield ] each
+    ] curry ignore-errors ;
+
+: add-child-monitor ( path -- )
+    qualify-path dup link-info type>> +directory+ eq? [
+        [ add-child-monitors ]
+        [
+            [ f my-mailbox (monitor) ] keep
+            monitor tget children>> set-at
+        ] bi
+    ] [ drop ] if ;
+
+USE: io
+USE: prettyprint
+
+: remove-child-monitor ( monitor -- )
+    monitor tget children>> delete-at*
+    [ dispose ] [ drop ] if ;
+
+M: recursive-monitor dispose
+    dup queue>> closed>> [
+        drop
+    ] [
+        [ "stop" swap thread>> send-synchronous drop ]
+        [ queue>> dispose ] bi
+    ] if ;
+
+: stop-pump ( -- )
+    monitor tget children>> [ nip dispose ] assoc-each ;
+
+: pump-step ( msg -- )
+    first3 path>> swap >r prepend-path r> monitor tget 3array
+    monitor tget queue>>
+    mailbox-put ;
+
+: child-added ( path monitor -- )
+    path>> prepend-path add-child-monitor ;
+
+: child-removed ( path monitor -- )
+    path>> prepend-path remove-child-monitor ;
+
+: update-hierarchy ( msg -- )
+    first3 swap [
+        {
+            { +add-file+ [ child-added ] }
+            { +remove-file+ [ child-removed ] }
+            { +rename-file-old+ [ child-removed ] }
+            { +rename-file-new+ [ child-added ] }
+            [ 3drop ]
+        } case
+    ] with with each ;
+
+: pump-loop ( -- )
+    receive dup synchronous? [
+        >r stop-pump t r> reply-synchronous
+    ] [
+        [ [ update-hierarchy ] curry ignore-errors ] [ pump-step ] bi
+        pump-loop
+    ] if ;
+
+: monitor-ready ( error/t -- )
+    monitor tget ready>> fulfill ;
+
+: pump-thread ( monitor -- )
+    monitor tset
+    [ "" add-child-monitor t monitor-ready ]
+    [ [ self <linked-error> monitor-ready ] keep rethrow ]
+    recover
+    pump-loop ;
+
+: start-pump-thread ( monitor -- )
+    dup [ pump-thread ] curry
+    "Recursive monitor pump" spawn
+    >>thread drop ;
+
+: wait-for-ready ( monitor -- )
+    ready>> ?promise ?linked drop ;
+
+: <recursive-monitor> ( path mailbox -- monitor )
+    >r (normalize-path) r>
+    recursive-monitor construct-monitor
+        H{ } clone >>children
+        <promise> >>ready
+    dup start-pump-thread
+    dup wait-for-ready ;
index ee9978f2c89a7bc8a106c79a30acd8eb028bdb8a..78bf0ba92116e65c93806da803970aade2ae9e33 100755 (executable)
@@ -36,10 +36,10 @@ HELP: port
 $nl
 "Ports have the following slots:"
 { $list
-    { { $link port-handle } " - a native handle identifying the underlying native resource used by the port" }
-    { { $link port-error } " - the most recent I/O error, if any. This error is thrown to the waiting thread when " { $link pending-error } " is called by stream operations" }
-    { { $link port-type } " - a symbol identifying the port's intended purpose" }
-    { { $link port-eof? } " - a flag indicating if the port has reached the end of file while reading" }
+    { { $snippet "handle" } " - a native handle identifying the underlying native resource used by the port" }
+    { { $snippet "error" } " - the most recent I/O error, if any. This error is thrown to the waiting thread when " { $link pending-error } " is called by stream operations" }
+    { { $snippet "type" } " - a symbol identifying the port's intended purpose" }
+    { { $snippet "eof" } " - a flag indicating if the port has reached the end of file while reading" }
 } } ;
 
 HELP: input-port
@@ -53,8 +53,8 @@ HELP: init-handle
 { $contract "Prepares a native handle for use by the port; called by " { $link <port> } "." } ;
 
 HELP: <port>
-{ $values { "handle" "a native handle identifying an I/O resource" } { "buffer" "a " { $link buffer } " or " { $link f } } { "type" symbol } { "port" "a new " { $link port } } }
-{ $description "Creates a new " { $link port } " using the specified native handle and I/O buffer." }
+{ $values { "handle" "a native handle identifying an I/O resource" } { "type" symbol } { "port" "a new " { $link port } } }
+{ $description "Creates a new " { $link port } " with no buffer." }
 $low-level-note ;
 
 HELP: <buffered-port>
index 85319ad8ef155726dec78c1fccc453e21341975e..048a5d7b1cc82388280456876212cd331e5219cf 100755 (executable)
@@ -1,46 +1,39 @@
 ! Copyright (C) 2005, 2008 Slava Pestov, Doug Coleman
 ! See http://factorcode.org/license.txt for BSD license.
-IN: io.nonblocking
 USING: math kernel io sequences io.buffers io.timeouts generic
 byte-vectors system io.streams.duplex io.encodings
 io.backend continuations debugger classes byte-arrays namespaces
-splitting dlists assocs io.encodings.binary ;
+splitting dlists assocs io.encodings.binary accessors ;
+IN: io.nonblocking
 
 SYMBOL: default-buffer-size
 64 1024 * default-buffer-size set-global
 
-! Common delegate of native stream readers and writers
-TUPLE: port
-handle
-error
-timeout
-type eof? ;
-
-M: port timeout port-timeout ;
-
-M: port set-timeout set-port-timeout ;
+TUPLE: port handle buffer error timeout closed eof ;
 
-SYMBOL: closed
+M: port timeout timeout>> ;
 
-PREDICATE: input-port < port port-type input-port eq? ;
-PREDICATE: output-port < port port-type output-port eq? ;
+M: port set-timeout (>>timeout) ;
 
 GENERIC: init-handle ( handle -- )
+
 GENERIC: close-handle ( handle -- )
 
-: <port> ( handle buffer type -- port )
-    pick init-handle {
-        set-port-handle
-        set-delegate
-        set-port-type
-    } port construct ;
+: <port> ( handle class -- port )
+    construct-empty
+        swap dup init-handle >>handle ; inline
+
+: <buffered-port> ( handle class -- port )
+    <port>
+        default-buffer-size get <buffer> >>buffer ; inline
 
-: <buffered-port> ( handle type -- port )
-    default-buffer-size get <buffer> swap <port> ;
+TUPLE: input-port < port ;
 
 : <reader> ( handle -- input-port )
     input-port <buffered-port> ;
 
+TUPLE: output-port < port ;
+
 : <writer> ( handle -- output-port )
     output-port <buffered-port> ;
 
@@ -48,7 +41,10 @@ GENERIC: close-handle ( handle -- )
     swap <reader> [ swap <writer> ] [ ] [ dispose drop ] cleanup ;
 
 : pending-error ( port -- )
-    dup port-error f rot set-port-error [ throw ] when* ;
+    [ f ] change-error drop [ throw ] when* ;
+
+: check-closed ( port -- port )
+    dup closed>> [ "Port closed" throw ] when ;
 
 HOOK: cancel-io io-backend ( port -- )
 
@@ -59,21 +55,22 @@ M: port timed-out cancel-io ;
 GENERIC: (wait-to-read) ( port -- )
 
 : wait-to-read ( count port -- )
-    tuck buffer-length > [ (wait-to-read) ] [ drop ] if ;
+    tuck buffer>> buffer-length > [ (wait-to-read) ] [ drop ] if ;
 
 : wait-to-read1 ( port -- )
     1 swap wait-to-read ;
 
 : unless-eof ( port quot -- value )
-    >r dup buffer-empty? over port-eof? and
-    [ f swap set-port-eof? f ] r> if ; inline
+    >r dup buffer>> buffer-empty? over eof>> and
+    [ f >>eof drop f ] r> if ; inline
 
 M: input-port stream-read1
-    dup wait-to-read1 [ buffer-pop ] unless-eof ;
+    check-closed
+    dup wait-to-read1 [ buffer>> buffer-pop ] unless-eof ;
 
 : read-step ( count port -- byte-array/f )
     [ wait-to-read ] 2keep
-    [ dupd buffer-read ] unless-eof nip ;
+    [ dupd buffer>> buffer-read ] unless-eof nip ;
 
 : read-loop ( count port accum -- )
     pick over length - dup 0 > [
@@ -87,6 +84,7 @@ M: input-port stream-read1
     ] if ;
 
 M: input-port stream-read
+    check-closed
     >r 0 max >fixnum r>
     2dup read-step dup [
         pick over length > [
@@ -94,72 +92,75 @@ M: input-port stream-read
             [ push-all ] keep
             [ read-loop ] keep
             B{ } like
-        ] [
-            2nip
-        ] if
-    ] [
-        2nip
-    ] if ;
+        ] [ 2nip ] if
+    ] [ 2nip ] if ;
 
 M: input-port stream-read-partial ( max stream -- byte-array/f )
+    check-closed
     >r 0 max >fixnum r> read-step ;
 
-: can-write? ( len writer -- ? )
+: can-write? ( len buffer -- ? )
     [ buffer-fill + ] keep buffer-capacity <= ;
 
 : wait-to-write ( len port -- )
-    tuck can-write? [ drop ] [ stream-flush ] if ;
+    tuck buffer>> can-write? [ drop ] [ stream-flush ] if ;
 
 M: output-port stream-write1
-    1 over wait-to-write byte>buffer ;
+    check-closed
+    1 over wait-to-write
+    buffer>> byte>buffer ;
 
 M: output-port stream-write
-    over length over buffer-size > [
-        [ buffer-size <groups> ] keep
-        [ stream-write ] curry each
+    check-closed
+    over length over buffer>> buffer-size > [
+        [ buffer>> buffer-size <groups> ]
+        [ [ stream-write ] curry ] bi
+        each
     ] [
-        over length over wait-to-write >buffer
+        [ >r length r> wait-to-write ]
+        [ buffer>> >buffer ] 2bi
     ] if ;
 
 GENERIC: port-flush ( port -- )
 
 M: output-port stream-flush ( port -- )
-    dup port-flush pending-error ;
+    check-closed
+    [ port-flush ] [ pending-error ] bi ;
+
+GENERIC: close-port ( port -- )
+
+M: output-port close-port
+    [ port-flush ] [ call-next-method ] bi ;
 
-: close-port ( port type -- )
-    output-port eq? [ dup port-flush ] when
+M: port close-port
     dup cancel-io
-    dup port-handle close-handle
-    dup delegate [ buffer-free ] when*
-    f swap set-delegate ;
+    dup handle>> close-handle
+    [ [ buffer-free ] when* f ] change-buffer drop ;
 
 M: port dispose
-    dup port-type closed eq?
-    [ drop ]
-    [ dup port-type >r closed over set-port-type r> close-port ]
-    if ;
+    dup closed>> [ drop ] [ t >>closed close-port ] if ;
 
-TUPLE: server-port addr client client-addr encoding ;
+TUPLE: server-port < port addr client client-addr encoding ;
 
 : <server-port> ( handle addr encoding -- server )
-    rot server-port <port>
-    { set-server-port-addr set-server-port-encoding set-delegate }
-    server-port construct ;
+    rot server-port <port>
+        swap >>encoding
+        swap >>addr ;
 
-: check-server-port ( port -- )
-    port-type server-port assert= ;
+: check-server-port ( port -- port )
+    dup server-port? [ "Not a server port" throw ] unless ; inline
 
-TUPLE: datagram-port addr packet packet-addr ;
+TUPLE: datagram-port < port addr packet packet-addr ;
 
 : <datagram-port> ( handle addr -- datagram )
-    >r f datagram-port <port> r>
-    { set-delegate set-datagram-port-addr }
-    datagram-port construct ;
+    swap datagram-port <port>
+        swap >>addr ;
 
-: check-datagram-port ( port -- )
-    port-type datagram-port assert= ;
+: check-datagram-port ( port -- port )
+    check-closed
+    dup datagram-port? [ "Not a datagram port" throw ] unless ; inline
 
-: check-datagram-send ( packet addrspec port -- )
-    dup check-datagram-port
-    datagram-port-addr [ class ] bi@ assert=
-    class byte-array assert= ;
+: check-datagram-send ( packet addrspec port -- packet addrspec port )
+    check-datagram-port
+    2dup addr>> [ class ] bi@ assert=
+    pick class byte-array assert= ;
index 0b7e62690803041518dade0e586c489b1cffcc84..1d5ed16dc58596af8d4e412cc3b5838f806bbde7 100755 (executable)
@@ -12,17 +12,17 @@ SYMBOL: servers
 
 LOG: accepted-connection NOTICE
 
-: with-client ( client quot -- )
+: with-client ( client addrspec quot -- )
     [
-        over client-stream-addr accepted-connection
+        swap accepted-connection
         with-stream*
-    ] curry with-disposal ; inline
+    ] 2curry with-disposal ; inline
 
 \ with-client DEBUG add-error-logging
 
 : accept-loop ( server quot -- )
     [
-        >r accept r> [ with-client ] 2curry "Client" spawn drop
+        >r accept r> [ with-client ] 3curry "Client" spawn drop
     ] 2keep accept-loop ; inline
 
 : server-loop ( addrspec encoding quot -- )
index 5b0790ca2dd95b883101eac29765c8ac9331dc65..498430fdbc84108db12459fed0c91b9be0182f17 100755 (executable)
@@ -90,7 +90,7 @@ M: inet6 parse-sockaddr
         { [ dup AF_INET = ] [ T{ inet4 } ] }
         { [ dup AF_INET6 = ] [ T{ inet6 } ] }
         { [ dup AF_UNIX = ] [ T{ local } ] }
-        { [ t ] [ f ] }
+        [ f ]
     } cond nip ;
 
 M: f parse-sockaddr nip ;
index fa38ec90eee1a057811e0c72057506d95505ce82..ad78b4631cac2472f3b5dacb9d204575f5b98ecc 100755 (executable)
@@ -17,8 +17,6 @@ ARTICLE: "network-connection" "Connection-oriented networking"
 "Connection-oriented network servers are implemented by first opening a server socket, then waiting for connections:"
 { $subsection <server> }
 { $subsection accept }
-"The stream returned by " { $link accept } " holds the address specifier of the remote client:"
-{ $subsection client-stream-addr }
 "Server sockets are closed by calling " { $link dispose } "."
 $nl
 "Address specifiers have the following interpretation with connection-oriented networking words:"
@@ -118,10 +116,8 @@ HELP: <server>
 { $errors "Throws an error if the address is already in use, or if it if the system forbids access." } ;
 
 HELP: accept
-{ $values { "server" "a handle" } { "client" "a bidirectional stream" } }
-{ $description "Waits for a connection to a server socket created by " { $link <server> } ", and outputs a bidirectional stream when the connection has been established. The encoding of this stream is the one that was passed to the server constructor."
-$nl
-"The returned client stream responds to the " { $link client-stream-addr } " word with the address of the incoming connection." }
+{ $values { "server" "a handle" } { "client" "a bidirectional stream" } { "addrspec" "an address specifier" } }
+{ $description "Waits for a connection to a server socket created by " { $link <server> } ", and outputs a bidirectional stream when the connection has been established. The encoding of this stream is the one that was passed to the server constructor." }
 { $errors "Throws an error if the server socket is closed or otherwise is unavailable." } ;
 
 HELP: <datagram>
index 17799227b8eadba4f8a830a749902a04265cc25c..04141c56efa8e32a34f7b7b202f650ae8f4c1d68 100755 (executable)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2007, 2008 Slava Pestov, Daniel Ehrenberg.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: generic kernel io.backend namespaces continuations
-sequences arrays io.encodings io.nonblocking ;
+sequences arrays io.encodings io.nonblocking accessors ;
 IN: io.sockets
 
 TUPLE: local path ;
@@ -21,20 +21,14 @@ TUPLE: inet host port ;
 
 C: <inet> inet
 
-TUPLE: client-stream addr ;
+HOOK: ((client)) io-backend ( addrspec -- client-in client-out )
 
-: <client-stream> ( addrspec delegate -- stream )
-    { set-client-stream-addr set-delegate }
-    client-stream construct ;
-
-HOOK: (client) io-backend ( addrspec -- client-in client-out )
-
-GENERIC: client* ( addrspec -- client-in client-out )
-M: array client* [ (client) 2array ] attempt-all first2 ;
-M: object client* (client) ;
+GENERIC: (client) ( addrspec -- client-in client-out )
+M: array (client) [ ((client)) 2array ] attempt-all first2 ;
+M: object (client) ((client)) ;
 
 : <client> ( addrspec encoding -- stream )
-    >r client* r> <encoder-duplex> ;
+    >r (client) r> <encoder-duplex> ;
 
 HOOK: (server) io-backend ( addrspec -- handle )
 
@@ -43,10 +37,9 @@ HOOK: (server) io-backend ( addrspec -- handle )
 
 HOOK: (accept) io-backend ( server -- addrspec handle )
 
-: accept ( server -- client )
-    [ (accept) dup <reader&writer> ] keep
-    server-port-encoding <encoder-duplex>
-    <client-stream> ;
+: accept ( server -- client addrspec )
+    [ (accept) dup <reader&writer> ] [ encoding>> ] bi
+    <encoder-duplex> swap ;
 
 HOOK: <datagram> io-backend ( addrspec -- datagram )
 
@@ -58,7 +51,8 @@ HOOK: resolve-host io-backend ( host serv passive? -- seq )
 
 HOOK: host-name io-backend ( -- string )
 
-M: inet client*
-    dup inet-host swap inet-port f resolve-host
-    dup empty? [ "Host name lookup failed" throw ] when
-    client* ;
+M: inet (client)
+    [ host>> ] [ port>> ] bi f resolve-host
+    [ empty? [ "Host name lookup failed" throw ] when ]
+    [ (client) ]
+    bi ;
index df7e1389cc539b5fb701163dae57b2e2900de8e5..64104083bedc78e50886ee5b240a165944a904eb 100755 (executable)
@@ -18,13 +18,13 @@ HELP: with-timeout
 { $description "Applies the quotation to the object. If the object's timeout expires before the quotation returns, " { $link timed-out } " is called on the object." } ;\r
 \r
 ARTICLE: "io.timeouts" "I/O timeout protocol"\r
-"Streams and processes support optional timeouts, which impose an upper bound on the length of time for which an operation on these objects can block. Timeouts are used in network servers to prevent malicious clients from holding onto connections forever, and to ensure that runaway processes get killed."\r
+"Streams, processes and monitors support optional timeouts, which impose an upper bound on the length of time for which an operation on these objects can block. Timeouts are used in network servers to prevent malicious clients from holding onto connections forever, and to ensure that runaway processes get killed."\r
 { $subsection timeout }\r
 { $subsection set-timeout }\r
 "The I/O timeout protocol can be implemented by any class wishing to support timeouts on blocking operations."\r
 { $subsection timed-out }\r
 "A combinator to be used in operations which can time out:"\r
 { $subsection with-timeout }\r
-{ $see-also "stream-protocol" "io.launcher" } ;\r
+{ $see-also "stream-protocol" "io.launcher" "io.monitors" } ;\r
 \r
 ABOUT: "io.timeouts"\r
old mode 100755 (executable)
new mode 100644 (file)
index 865490b..396b8cf
@@ -14,18 +14,13 @@ TUPLE: io-task port callbacks ;
 : io-task-fd port>> handle>> ;
 
 : <io-task> ( port continuation/f class -- task )
-    >r [ 1vector ] [ V{ } clone ] if* io-task construct-boa
-    r> construct-delegate ; inline
+    construct-empty
+        swap [ 1vector ] [ V{ } clone ] if* >>callbacks
+        swap >>port ; inline
 
-TUPLE: input-task ;
+TUPLE: input-task < io-task ;
 
-: <input-task> ( port continuation class -- task )
-    >r input-task <io-task> r> construct-delegate ; inline
-
-TUPLE: output-task ;
-
-: <output-task> ( port continuation class -- task )
-    >r output-task <io-task> r> construct-delegate ; inline
+TUPLE: output-task < io-task ;
 
 GENERIC: do-io-task ( task -- ? )
 GENERIC: io-task-container ( mx task -- hashtable )
@@ -37,9 +32,10 @@ M: input-task io-task-container drop reads>> ;
 
 M: output-task io-task-container drop writes>> ;
 
-: <mx> ( -- mx ) f H{ } clone H{ } clone mx construct-boa ;
-
-: construct-mx ( class -- obj ) <mx> swap construct-delegate ;
+: construct-mx ( class -- obj )
+    construct-empty
+        H{ } clone >>reads
+        H{ } clone >>writes ; inline
 
 GENERIC: register-io-task ( task mx -- )
 GENERIC: unregister-io-task ( task mx -- )
@@ -123,16 +119,18 @@ M: unix cancel-io ( port -- )
 
 ! Readers
 : reader-eof ( reader -- )
-    dup buffer-empty? [ t >>eof? ] when drop ;
+    dup buffer>> buffer-empty? [ t >>eof ] when drop ;
 
 : (refill) ( port -- n )
-    [ handle>> ] [ buffer-end ] [ buffer-capacity ] tri read ;
+    [ handle>> ]
+    [ buffer>> buffer-end ]
+    [ buffer>> buffer-capacity ] tri read ;
 
 : refill ( port -- ? )
     #! Return f if there is a recoverable error
-    dup buffer-empty? [
+    dup buffer>> buffer-empty? [
         dup (refill)  dup 0 >= [
-            swap n>buffer t
+            swap buffer>> n>buffer t
         ] [
             drop defer-error
         ] if
@@ -140,10 +138,10 @@ M: unix cancel-io ( port -- )
         drop t
     ] if ;
 
-TUPLE: read-task ;
+TUPLE: read-task < input-task ;
 
 : <read-task> ( port continuation -- task )
-    read-task <input-task> ;
+    read-task <io-task> ;
 
 M: read-task do-io-task
     io-task-port dup refill
@@ -155,28 +153,33 @@ M: input-port (wait-to-read)
 
 ! Writers
 : write-step ( port -- ? )
-    dup [ handle>> ] [ buffer@ ] [ buffer-length ] tri write
-    dup 0 >= [ swap buffer-consume f ] [ drop defer-error ] if ;
+    dup
+    [ handle>> ]
+    [ buffer>> buffer@ ]
+    [ buffer>> buffer-length ] tri
+    write dup 0 >=
+    [ swap buffer>> buffer-consume f ]
+    [ drop defer-error ] if ;
 
-TUPLE: write-task ;
+TUPLE: write-task < output-task ;
 
 : <write-task> ( port continuation -- task )
-    write-task <output-task> ;
+    write-task <io-task> ;
 
 M: write-task do-io-task
-    io-task-port dup [ buffer-empty? ] [ port-error ] bi or
-    [ 0 swap buffer-reset t ] [ write-step ] if ;
+    io-task-port dup [ buffer>> buffer-empty? ] [ port-error ] bi or
+    [ 0 swap buffer>> buffer-reset t ] [ write-step ] if ;
 
 : add-write-io-task ( port continuation -- )
-    over port-handle mx get-global mx-writes at*
+    over handle>> mx get-global writes>> at*
     [ io-task-callbacks push drop ]
     [ drop <write-task> add-io-task ] if ;
 
 : (wait-to-write) ( port -- )
     [ add-write-io-task ] with-port-continuation drop ;
 
-M: port port-flush ( port -- )
-    dup buffer-empty? [ drop ] [ (wait-to-write) ] if ;
+M: output-port port-flush ( port -- )
+    dup buffer>> buffer-empty? [ drop ] [ (wait-to-write) ] if ;
 
 M: unix io-multiplex ( ms/f -- )
     mx get-global wait-for-events ;
@@ -187,13 +190,12 @@ M: unix (init-stdio) ( -- )
     2 <writer> ;
 
 ! mx io-task for embedding an fd-based mx inside another mx
-TUPLE: mx-port mx ;
+TUPLE: mx-port < port mx ;
 
 : <mx-port> ( mx -- port )
-    dup fd>> f mx-port <port>
-    { set-mx-port-mx set-delegate } mx-port construct ;
+    dup fd>> mx-port <port> swap >>mx ;
 
-TUPLE: mx-task ;
+TUPLE: mx-task < io-task ;
 
 : <mx-task> ( port -- task )
     f mx-task <io-task> ;
@@ -203,3 +205,6 @@ M: mx-task do-io-task
 
 : multiplexer-error ( n -- )
     0 < [ err_no ignorable-error? [ (io-error) ] unless ] when ;
+
+: ?flag ( n mask symbol -- n )
+    pick rot bitand 0 > [ , ] [ drop ] if ;
index 6f6517868e29f82476b512d4a53739b06d05ea76..1b51b3c4e4c4c07a604818368b742aed7e7582b7 100755 (executable)
@@ -1,23 +1,22 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 IN: io.unix.bsd
-USING: io.backend io.unix.backend io.unix.kqueue io.unix.select
-io.launcher io.unix.launcher namespaces kernel assocs
-threads continuations system ;
-
-! On Mac OS X, we use select() for the top-level
-! multiplexer, and we hang a kqueue off of it for process exit
-! notification.
-
-! kqueue is buggy with files and ptys so we can't use it as the
-! main multiplexer.
+USING: namespaces system kernel accessors assocs continuations
+unix
+io.backend io.unix.backend io.unix.select io.unix.kqueue io.monitors ;
 
 M: bsd init-io ( -- )
     <select-mx> mx set-global
     <kqueue-mx> kqueue-mx set-global
-    kqueue-mx get-global <mx-port> <mx-task> dup io-task-fd
-    2dup mx get-global mx-reads set-at
-    mx get-global mx-writes set-at ;
+    kqueue-mx get-global <mx-port> <mx-task>
+    dup io-task-fd
+    [ mx get-global reads>> set-at ]
+    [ mx get-global writes>> set-at ] 2bi ;
+
+M: bsd init-monitors ;
+
+M: bsd dispose-monitors ;
 
-M: bsd register-process ( process -- )
-    process-handle kqueue-mx get-global add-pid-task ;
+M: bsd (monitor) ( path recursive? mailbox -- )
+    swap [ "Recursive kqueue monitors not supported" throw ] when
+    <vnode-monitor> ;
index 1459549f9ec39881eb994eda3894d0312406f55b..2d7ca9ba3f1c308ec8bdba827c61a516f9915c43 100644 (file)
@@ -5,7 +5,7 @@ bit-arrays sequences assocs unix unix.linux.epoll math
 namespaces structs ;
 IN: io.unix.epoll
 
-TUPLE: epoll-mx events ;
+TUPLE: epoll-mx < mx events ;
 
 : max-events ( -- n )
     #! We read up to 256 events at a time. This is an arbitrary
@@ -33,12 +33,10 @@ M: output-task io-task-events drop EPOLLOUT ;
     epoll_ctl io-error ;
 
 M: epoll-mx register-io-task ( task mx -- )
-    2dup EPOLL_CTL_ADD do-epoll-ctl 
-    delegate register-io-task ;
+    [ EPOLL_CTL_ADD do-epoll-ctl ] [ call-next-method ] 2bi ;
 
 M: epoll-mx unregister-io-task ( task mx -- )
-    2dup delegate unregister-io-task
-    EPOLL_CTL_DEL do-epoll-ctl ;
+    [ call-next-method ] [ EPOLL_CTL_DEL do-epoll-ctl ] 2bi ;
 
 : wait-event ( mx timeout -- n )
     >r { mx-fd epoll-mx-events } get-slots max-events
index 39c18b460121976d702ab4f31591edd15d445a29..5873568a9ea47bc357a75f45d961ec5bce1786e7 100755 (executable)
@@ -72,20 +72,20 @@ M: unix delete-directory ( path -- )
 M: unix copy-file ( from to -- )
     [ normalize-path ] bi@
     [ (copy-file) ]
-    [ swap file-info file-info-permissions chmod io-error ]
+    [ swap file-info permissions>> chmod io-error ]
     2bi ;
 
 : stat>type ( stat -- type )
-    stat-st_mode {
-        { [ dup S_ISREG  ] [ +regular-file+     ] }
-        { [ dup S_ISDIR  ] [ +directory+        ] }
-        { [ dup S_ISCHR  ] [ +character-device+ ] }
-        { [ dup S_ISBLK  ] [ +block-device+     ] }
-        { [ dup S_ISFIFO ] [ +fifo+             ] }
-        { [ dup S_ISLNK  ] [ +symbolic-link+    ] }
-        { [ dup S_ISSOCK ] [ +socket+           ] }
-        { [ t            ] [ +unknown+          ] }
-    } cond nip ;
+    stat-st_mode S_IFMT bitand {
+        { S_IFREG [ +regular-file+ ] }
+        { S_IFDIR [ +directory+ ] }
+        { S_IFCHR [ +character-device+ ] }
+        { S_IFBLK [ +block-device+ ] }
+        { S_IFIFO [ +fifo+ ] }
+        { S_IFLNK [ +symbolic-link+ ] }
+        { S_IFSOCK [ +socket+ ] }
+        [ drop +unknown+ ]
+    } case ;
 
 : stat>file-info ( stat -- info )
     {
old mode 100755 (executable)
new mode 100644 (file)
index 97b186e..3a140bd
@@ -1,12 +1,14 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien.c-types kernel io.nonblocking io.unix.backend
-sequences assocs unix unix.time unix.kqueue unix.process math namespaces
-combinators threads vectors io.launcher
-io.unix.launcher ;
+USING: alien.c-types kernel math math.bitfields namespaces
+locals accessors combinators threads vectors hashtables
+sequences assocs continuations
+unix unix.time unix.kqueue unix.process
+io.nonblocking io.unix.backend io.launcher io.unix.launcher
+io.monitors ;
 IN: io.unix.kqueue
 
-TUPLE: kqueue-mx events ;
+TUPLE: kqueue-mx < mx events monitors ;
 
 : max-events ( -- n )
     #! We read up to 256 events at a time. This is an arbitrary
@@ -15,8 +17,9 @@ TUPLE: kqueue-mx events ;
 
 : <kqueue-mx> ( -- mx )
     kqueue-mx construct-mx
-    kqueue dup io-error over set-mx-fd
-    max-events "kevent" <c-array> over set-kqueue-mx-events ;
+        H{ } clone >>monitors
+        kqueue dup io-error >>fd
+        max-events "kevent" <c-array> >>events ;
 
 GENERIC: io-task-filter ( task -- n )
 
@@ -24,52 +27,78 @@ M: input-task io-task-filter drop EVFILT_READ ;
 
 M: output-task io-task-filter drop EVFILT_WRITE ;
 
+GENERIC: io-task-fflags ( task -- n )
+
+M: io-task io-task-fflags drop 0 ;
+
 : make-kevent ( task flags -- event )
     "kevent" <c-object>
     tuck set-kevent-flags
     over io-task-fd over set-kevent-ident
+    over io-task-fflags over set-kevent-fflags
     swap io-task-filter over set-kevent-filter ;
 
 : register-kevent ( kevent mx -- )
-    mx-fd swap 1 f 0 f kevent
+    fd>> swap 1 f 0 f kevent
     0 < [ err_no ESRCH = [ (io-error) ] unless ] when ;
 
 M: kqueue-mx register-io-task ( task mx -- )
-    over EV_ADD make-kevent over register-kevent
-    delegate register-io-task ;
+    [ >r EV_ADD make-kevent r> register-kevent ]
+    [ call-next-method ]
+    2bi ;
 
 M: kqueue-mx unregister-io-task ( task mx -- )
-    2dup delegate unregister-io-task
-    swap EV_DELETE make-kevent swap register-kevent ;
+    [ call-next-method ]
+    [ >r EV_DELETE make-kevent r> register-kevent ]
+    2bi ;
 
 : wait-kevent ( mx timespec -- n )
-    >r dup mx-fd f 0 roll kqueue-mx-events max-events r> kevent
+    >r [ fd>> f 0 ] keep events>> max-events r> kevent
     dup multiplexer-error ;
 
-: kevent-read-task ( mx fd -- )
-    over mx-reads at handle-io-task ;
+:: kevent-read-task ( mx fd kevent -- )
+    mx fd mx reads>> at handle-io-task ;
 
-: kevent-write-task ( mx fd -- )
-    over mx-reads at handle-io-task ;
+:: kevent-write-task ( mx fd kevent -- )
+    mx fd mx writes>> at handle-io-task ;
 
-: kevent-proc-task ( pid -- )
-    dup wait-for-pid swap find-process
+:: kevent-proc-task ( mx pid kevent -- )
+    pid wait-for-pid
+    pid find-process
     dup [ swap notify-exit ] [ 2drop ] if ;
 
+: parse-action ( mask -- changed )
+    [
+        NOTE_DELETE +remove-file+ ?flag
+        NOTE_WRITE +modify-file+ ?flag
+        NOTE_EXTEND +modify-file+ ?flag
+        NOTE_ATTRIB +modify-file+ ?flag
+        NOTE_RENAME +rename-file+ ?flag
+        NOTE_REVOKE +remove-file+ ?flag
+        drop
+    ] { } make prune ;
+
+:: kevent-vnode-task ( mx kevent fd -- )
+    ""
+    kevent kevent-fflags parse-action
+    fd mx monitors>> at queue-change ;
+
 : handle-kevent ( mx kevent -- )
-    dup kevent-ident swap kevent-filter {
+    [ ] [ kevent-ident ] [ kevent-filter ] tri {
         { [ dup EVFILT_READ = ] [ drop kevent-read-task ] }
         { [ dup EVFILT_WRITE = ] [ drop kevent-write-task ] }
-        { [ dup EVFILT_PROC = ] [ drop kevent-proc-task drop ] }
+        { [ dup EVFILT_PROC = ] [ drop kevent-proc-task ] }
+        { [ dup EVFILT_VNODE = ] [ drop kevent-vnode-task ] }
     } cond ;
 
 : handle-kevents ( mx n -- )
-    [ over kqueue-mx-events kevent-nth handle-kevent ] with each ;
+    [ over events>> kevent-nth handle-kevent ] with each ;
 
 M: kqueue-mx wait-for-events ( ms mx -- )
     swap dup [ make-timespec ] when
     dupd wait-kevent handle-kevents ;
 
+! Procs
 : make-proc-kevent ( pid -- kevent )
     "kevent" <c-object>
     tuck set-kevent-ident
@@ -77,5 +106,44 @@ M: kqueue-mx wait-for-events ( ms mx -- )
     EVFILT_PROC over set-kevent-filter
     NOTE_EXIT over set-kevent-fflags ;
 
-: add-pid-task ( pid mx -- )
+: register-pid-task ( pid mx -- )
     swap make-proc-kevent swap register-kevent ;
+
+! VNodes
+TUPLE: vnode-monitor < monitor fd ;
+
+: vnode-fflags ( -- n )
+    {
+        NOTE_DELETE
+        NOTE_WRITE
+        NOTE_EXTEND
+        NOTE_ATTRIB
+        NOTE_LINK
+        NOTE_RENAME
+        NOTE_REVOKE
+    } flags ;
+
+: make-vnode-kevent ( fd flags -- kevent )
+    "kevent" <c-object>
+    tuck set-kevent-flags
+    tuck set-kevent-ident
+    EVFILT_VNODE over set-kevent-filter
+    vnode-fflags over set-kevent-fflags ;
+
+: register-monitor ( monitor mx -- )
+    >r dup fd>> r>
+    [ >r EV_ADD EV_CLEAR bitor make-vnode-kevent r> register-kevent drop ]
+    [ monitors>> set-at ] 3bi ;
+
+: unregister-monitor ( monitor mx -- )
+    >r fd>> r>
+    [ monitors>> delete-at ]
+    [ >r EV_DELETE make-vnode-kevent r> register-kevent ] 2bi ;
+
+: <vnode-monitor> ( path mailbox -- monitor )
+    >r [ O_RDONLY 0 open dup io-error ] keep r>
+    vnode-monitor construct-monitor swap >>fd
+    [ dup kqueue-mx get register-monitor ] [ ] [ fd>> close ] cleanup ;
+
+M: vnode-monitor dispose
+    [ kqueue-mx get unregister-monitor ] [ fd>> close ] bi ;
index 5f0a9b96cb35e686f48c9c46faec637118af3956..2c1e6261c045301224a8aa24ab86d1f5dfcfde74 100755 (executable)
@@ -31,7 +31,10 @@ USE: unix
 : redirect-fd ( oldfd fd -- )
     2dup = [ 2drop ] [ dupd dup2 io-error close ] if ;
 
-: reset-fd ( fd -- ) F_SETFL 0 fcntl io-error ;
+: reset-fd ( fd -- )
+    #! We drop the error code because on *BSD, fcntl of
+    #! /dev/null fails.
+    F_SETFL 0 fcntl drop ;
 
 : redirect-inherit ( obj mode fd -- )
     2nip reset-fd ;
@@ -52,7 +55,7 @@ USE: unix
         { [ pick string? ] [ redirect-file ] }
         { [ pick +closed+ eq? ] [ redirect-closed ] }
         { [ pick +inherit+ eq? ] [ redirect-closed ] }
-        { [ t ] [ redirect-stream ] }
+        [ redirect-stream ]
     } cond ;
 
 : ?closed dup +closed+ eq? [ drop "/dev/null" ] when ;
@@ -66,18 +69,18 @@ USE: unix
         ?closed write-flags 2 redirect
     ] if ;
 
+: setup-environment ( process -- process )
+    dup pass-environment? [
+        dup get-environment set-os-envs
+    ] when ;
+
 : spawn-process ( process -- * )
-    [
-        setup-priority
-        setup-redirection
-        current-directory get resource-path cd
-        dup pass-environment? [
-            dup get-environment set-os-envs
-        ] when
-
-        get-arguments exec-args-with-path
-        (io-error)
-    ] [ 255 exit ] recover ;
+    [ setup-priority ] [ 250 _exit ] recover
+    [ setup-redirection ] [ 251 _exit ] recover
+    [ current-directory get (normalize-path) cd ] [ 252 _exit ] recover
+    [ setup-environment ] [ 253 _exit ] recover
+    [ get-arguments exec-args-with-path ] [ 254 _exit ] recover
+    255 _exit ;
 
 M: unix current-process-handle ( -- handle ) getpid ;
 
@@ -108,7 +111,7 @@ M: unix (process-stream)
 
 ! Inefficient process wait polling, used on Linux and Solaris.
 ! On BSD and Mac OS X, we use kqueue() which scales better.
-: wait-for-processes ( -- ? )
+M: unix wait-for-processes ( -- ? )
     -1 0 <int> tuck WNOHANG waitpid
     dup 0 <= [
         2drop t
@@ -119,7 +122,3 @@ M: unix (process-stream)
             2drop f
         ] if
     ] if ;
-
-: start-wait-thread ( -- )
-    [ wait-for-processes [ 250 sleep ] when t ]
-    "Process reaper" spawn-server drop ;
index 78af0dd50db493552d69789fea7198ec2653fb16..e75f4c5f6b9b3a08ba2285a1a20902b367daadeb 100755 (executable)
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel io.backend io.monitors io.monitors.private
-io.files io.buffers io.nonblocking io.timeouts io.unix.backend
-io.unix.select io.unix.launcher unix.linux.inotify assocs
-namespaces threads continuations init math alien.c-types alien
-vocabs.loader accessors system ;
+USING: kernel io.backend io.monitors io.unix.backend
+io.unix.select io.unix.linux.monitors system namespaces ;
 IN: io.unix.linux
 
-TUPLE: linux-monitor ;
-
-: <linux-monitor> ( wd -- monitor )
-    linux-monitor construct-simple-monitor ;
-
-TUPLE: inotify watches ;
-
-: watches ( -- assoc ) inotify get-global watches>> ;
-
-: wd>monitor ( wd -- monitor ) watches at ;
-
-: <inotify> ( -- port/f )
-    H{ } clone
-    inotify_init dup 0 < [ 2drop f ] [
-        inotify <buffered-port>
-        { set-inotify-watches set-delegate } inotify construct
-    ] if ;
-
-: inotify-fd inotify get-global handle>> ;
-
-: (add-watch) ( path mask -- wd )
-    inotify-fd -rot inotify_add_watch dup io-error ;
-
-: check-existing ( wd -- )
-    watches key? [
-        "Cannot open multiple monitors for the same file" throw
-    ] when ;
-
-: add-watch ( path mask -- monitor )
-    (add-watch) dup check-existing
-    [ <linux-monitor> dup ] keep watches set-at ;
-
-: remove-watch ( monitor -- )
-    dup simple-monitor-handle watches delete-at
-    simple-monitor-handle inotify-fd swap inotify_rm_watch io-error ;
-
-: check-inotify
-    inotify get [
-        "inotify is not supported by this Linux release" throw
-    ] unless ;
-
-M: linux <monitor> ( path recursive? -- monitor )
-    check-inotify
-    drop IN_CHANGE_EVENTS add-watch ;
-
-M: linux-monitor dispose ( monitor -- )
-    dup delegate dispose remove-watch ;
-
-: ?flag ( n mask symbol -- n )
-    pick rot bitand 0 > [ , ] [ drop ] if ;
-
-: parse-action ( mask -- changed )
-    [
-        IN_CREATE +add-file+ ?flag
-        IN_DELETE +remove-file+ ?flag
-        IN_DELETE_SELF +remove-file+ ?flag
-        IN_MODIFY +modify-file+ ?flag
-        IN_ATTRIB +modify-file+ ?flag
-        IN_MOVED_FROM +rename-file+ ?flag
-        IN_MOVED_TO +rename-file+ ?flag
-        IN_MOVE_SELF +rename-file+ ?flag
-        drop
-    ] { } make ;
-
-: parse-file-notify ( buffer -- changed path )
-    { inotify-event-name inotify-event-mask } get-slots
-    parse-action swap alien>char-string ;
-
-: events-exhausted? ( i buffer -- ? )
-    fill>> >= ;
-
-: inotify-event@ ( i buffer -- alien )
-    ptr>> <displaced-alien> ;
-
-: next-event ( i buffer -- i buffer )
-    2dup inotify-event@
-    inotify-event-len "inotify-event" heap-size +
-    swap >r + r> ;
-
-: parse-file-notifications ( i buffer -- )
-    2dup events-exhausted? [ 2drop ] [
-        2dup inotify-event@ dup inotify-event-wd wd>monitor [
-            monitor-queue [
-                parse-file-notify changed-file
-            ] bind
-        ] keep notify-callback
-        next-event parse-file-notifications
-    ] if ;
-
-: read-notifications ( port -- )
-    dup refill drop
-    0 over parse-file-notifications
-    0 swap buffer-reset ;
-
-TUPLE: inotify-task ;
-
-: <inotify-task> ( port -- task )
-    f inotify-task <input-task> ;
-
-: init-inotify ( mx -- )
-    <inotify> dup [
-        dup inotify set-global
-        <inotify-task> swap register-io-task
-    ] [
-        2drop
-    ] if ;
-
-M: inotify-task do-io-task ( task -- )
-    io-task-port read-notifications f ;
-
 M: linux init-io ( -- )
-    <select-mx>
-    [ mx set-global ]
-    [ init-inotify ] bi ;
+    <select-mx> mx set-global ;
 
 linux set-io-backend
-
-[ start-wait-thread ] "io.unix.linux" add-init-hook
diff --git a/extra/io/unix/linux/monitors/monitors.factor b/extra/io/unix/linux/monitors/monitors.factor
new file mode 100644 (file)
index 0000000..f92fb36
--- /dev/null
@@ -0,0 +1,126 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel io.backend io.monitors io.monitors.recursive
+io.files io.buffers io.monitors io.nonblocking io.timeouts
+io.unix.backend io.unix.select unix.linux.inotify assocs
+namespaces threads continuations init math math.bitfields
+alien.c-types alien vocabs.loader accessors system hashtables ;
+IN: io.unix.linux.monitors
+
+TUPLE: linux-monitor < monitor wd ;
+
+: <linux-monitor> ( wd path mailbox -- monitor )
+    linux-monitor construct-monitor
+        swap >>wd ;
+
+SYMBOL: watches
+
+SYMBOL: inotify
+
+: wd>monitor ( wd -- monitor ) watches get at ;
+
+: <inotify> ( -- port/f )
+    inotify_init dup 0 < [ drop f ] [ <reader> ] if ;
+
+: inotify-fd inotify get handle>> ;
+
+: check-existing ( wd -- )
+    watches get key? [
+        "Cannot open multiple monitors for the same file" throw
+    ] when ;
+
+: (add-watch) ( path mask -- wd )
+    inotify-fd -rot inotify_add_watch dup io-error dup check-existing ;
+
+: add-watch ( path mask mailbox -- monitor )
+    >r
+    >r (normalize-path) r>
+    [ (add-watch) ] [ drop ] 2bi r>
+    <linux-monitor> [ ] [ ] [ wd>> ] tri watches get set-at ;
+
+: check-inotify
+    inotify get [
+        "Calling <monitor> outside with-monitors" throw
+    ] unless ;
+
+M: linux (monitor) ( path recursive? mailbox -- monitor )
+    swap [
+        <recursive-monitor>
+    ] [
+        check-inotify
+        IN_CHANGE_EVENTS swap add-watch
+    ] if ;
+
+M: linux-monitor dispose ( monitor -- )
+    [ wd>> watches get delete-at ]
+    [ wd>> inotify-fd swap inotify_rm_watch io-error ] bi ;
+
+: ignore-flags? ( mask -- ? )
+    {
+        IN_DELETE_SELF
+        IN_MOVE_SELF
+        IN_UNMOUNT
+        IN_Q_OVERFLOW
+        IN_IGNORED
+    } flags bitand 0 > ;
+
+: parse-action ( mask -- changed )
+    [
+        IN_CREATE +add-file+ ?flag
+        IN_DELETE +remove-file+ ?flag
+        IN_MODIFY +modify-file+ ?flag
+        IN_ATTRIB +modify-file+ ?flag
+        IN_MOVED_FROM +rename-file-old+ ?flag
+        IN_MOVED_TO +rename-file-new+ ?flag
+        drop
+    ] { } make prune ;
+
+: parse-file-notify ( buffer -- path changed )
+    dup inotify-event-mask ignore-flags? [
+        drop f f
+    ] [
+        [ inotify-event-name alien>char-string ]
+        [ inotify-event-mask parse-action ] bi
+    ] if ;
+
+: events-exhausted? ( i buffer -- ? )
+    fill>> >= ;
+
+: inotify-event@ ( i buffer -- alien )
+    ptr>> <displaced-alien> ;
+
+: next-event ( i buffer -- i buffer )
+    2dup inotify-event@
+    inotify-event-len "inotify-event" heap-size +
+    swap >r + r> ;
+
+: parse-file-notifications ( i buffer -- )
+    2dup events-exhausted? [ 2drop ] [
+        2dup inotify-event@ dup inotify-event-wd wd>monitor
+        >r parse-file-notify r> queue-change
+        next-event parse-file-notifications
+    ] if ;
+
+: inotify-read-loop ( port -- )
+    dup wait-to-read1
+    0 over buffer>> parse-file-notifications
+    0 over buffer>> buffer-reset
+    inotify-read-loop ;
+
+: inotify-read-thread ( port -- )
+    [ inotify-read-loop ] curry ignore-errors ;
+
+M: linux init-monitors
+    H{ } clone watches set
+    <inotify> [
+        [ inotify set ]
+        [
+            [ inotify-read-thread ] curry
+            "Linux monitor thread" spawn drop
+        ] bi
+    ] [
+        "Linux kernel version is too old" throw
+    ] if* ;
+
+M: linux dispose-monitors
+    inotify get dispose ;
index c1c73ea0185eef0223c016820b9e789a01c9176f..68eb2f13bb7db8c9cc5de2d6823bc45b7203528c 100644 (file)
@@ -1,23 +1,27 @@
-USING: io.unix.bsd io.backend io.monitors io.monitors.private
-continuations kernel core-foundation.fsevents sequences
-namespaces arrays system ;
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: io.unix.bsd io.backend io.monitors core-foundation.fsevents
+continuations kernel sequences namespaces arrays system locals
+accessors ;
 IN: io.unix.macosx
 
-macosx set-io-backend
-
-TUPLE: macosx-monitor ;
+TUPLE: macosx-monitor < monitor handle ;
 
 : enqueue-notifications ( triples monitor -- )
-    tuck monitor-queue
-    [ [ first { +modify-file+ } swap changed-file ] each ] bind
-    notify-callback ;
+    [
+        >r first { +modify-file+ } r> queue-change
+    ] curry each ;
+
+M: macosx init-monitors ;
 
-M: macosx <monitor>
-    drop
-    f macosx-monitor construct-simple-monitor
+M: macosx dispose-monitors ;
+
+M:: macosx (monitor) ( path recursive? mailbox -- monitor )
+    path mailbox macosx-monitor construct-monitor
     dup [ enqueue-notifications ] curry
-    rot 1array 0 0 <event-stream>
-    over set-simple-monitor-handle ;
+    path 1array 0 0 <event-stream> >>handle ;
 
 M: macosx-monitor dispose
-    dup simple-monitor-handle dispose delegate dispose ;
+    handle>> dispose ;
+
+macosx set-io-backend
index c5771c8ffc14d0df12b2e7d4092ad75c020303cf..ed134788b6001aa2ce5dac9a1af7cc66fafc7c7f 100644 (file)
@@ -1,3 +1,3 @@
-USING: io.backend system ;
+USING: io.unix.bsd io.backend system ;
 
 netbsd set-io-backend
index 9b3021646d22571607cd30780fe85eafa3b37084..dfc466f94b239466f36cb4e0253ffd36f29ce16c 100644 (file)
@@ -1,3 +1,3 @@
-USING: io.unix.bsd io.backend core-foundation.fsevents system ;
+USING: io.unix.bsd io.backend system ;
 
 openbsd set-io-backend
index aceee0f31114e48e21bbbac4d9a8a0ffe9d12bf2..facaf4d73da6bd0c242d2a8cd21e47630f097b91 100755 (executable)
@@ -5,7 +5,7 @@ bit-arrays sequences assocs unix math namespaces structs
 accessors ;
 IN: io.unix.select
 
-TUPLE: select-mx read-fdset write-fdset ;
+TUPLE: select-mx < mx read-fdset write-fdset ;
 
 ! Factor's bit-arrays are an array of bytes, OS X expects
 ! FD_SET to be an array of cells, so we have to account for
@@ -15,8 +15,8 @@ TUPLE: select-mx read-fdset write-fdset ;
 
 : <select-mx> ( -- mx )
     select-mx construct-mx
-    FD_SETSIZE 8 * <bit-array> >>read-fdset
-    FD_SETSIZE 8 * <bit-array> >>write-fdset ;
+        FD_SETSIZE 8 * <bit-array> >>read-fdset
+        FD_SETSIZE 8 * <bit-array> >>write-fdset ;
 
 : clear-nth ( n seq -- ? )
     [ nth ] [ f -rot set-nth ] 2bi ;
@@ -29,7 +29,6 @@ TUPLE: select-mx read-fdset write-fdset ;
     [ handle-fd ] 2curry assoc-each ;
 
 : init-fdset ( tasks fdset -- )
-    ! dup clear-bits
     [ >r drop t swap munge r> set-nth ] curry assoc-each ;
 
 : read-fdset/tasks
@@ -45,9 +44,9 @@ TUPLE: select-mx read-fdset write-fdset ;
     [ reads>> max-fd ] [ writes>> max-fd ] bi max 1+ ;
 
 : init-fdsets ( mx -- nfds read write except )
-    [ num-fds ] keep
-    [ read-fdset/tasks tuck init-fdset ] keep
-    write-fdset/tasks tuck init-fdset
+    [ num-fds ]
+    [ read-fdset/tasks tuck init-fdset ]
+    [ write-fdset/tasks tuck init-fdset ] tri
     f ;
 
 M: select-mx wait-for-events ( ms mx -- )
index a54205a8789469a8c1d9ff459ea1ec8b0385c05d..cecc70fb0825a7d65b90f6214febcfff6958d609 100755 (executable)
@@ -7,7 +7,7 @@ USING: alien alien.c-types generic io kernel math namespaces
 io.nonblocking parser threads unix sequences
 byte-arrays io.sockets io.binary io.unix.backend
 io.streams.duplex io.sockets.impl math.parser continuations libc
-combinators io.backend io.files io.files.private system ;
+combinators io.backend io.files io.files.private system accessors ;
 IN: io.unix.sockets
 
 : pending-init-error ( port -- )
@@ -30,10 +30,10 @@ M: unix addrinfo-error ( n -- )
 : init-client-socket ( fd -- )
     SOL_SOCKET SO_OOBINLINE sockopt ;
 
-TUPLE: connect-task ;
+TUPLE: connect-task < output-task ;
 
 : <connect-task> ( port continuation -- task )
-    connect-task <output-task> ;
+    connect-task <io-task> ;
 
 M: connect-task do-io-task
     io-task-port dup port-handle f 0 write
@@ -42,7 +42,7 @@ M: connect-task do-io-task
 : wait-to-connect ( port -- )
     [ <connect-task> add-io-task ] with-port-continuation drop ;
 
-M: unix (client) ( addrspec -- client-in client-out )
+M: unix ((client)) ( addrspec -- client-in client-out )
     dup make-sockaddr/size >r >r
     protocol-family SOCK_STREAM socket-fd
     dup r> r> connect
@@ -61,10 +61,10 @@ USE: unix
 : init-server-socket ( fd -- )
     SOL_SOCKET SO_REUSEADDR sockopt ;
 
-TUPLE: accept-task ;
+TUPLE: accept-task < input-task ;
 
 : <accept-task> ( port continuation  -- task )
-    accept-task <input-task> ;
+    accept-task <io-task> ;
 
 : accept-sockaddr ( port -- fd sockaddr )
     dup port-handle swap server-port-addr sockaddr-type
@@ -97,11 +97,10 @@ M: unix (server) ( addrspec -- handle )
 
 M: unix (accept) ( server -- addrspec handle )
     #! Wait for a client connection.
-    dup check-server-port
-    dup wait-to-accept
-    dup pending-error
-    dup server-port-client-addr
-    swap server-port-client ;
+    check-server-port
+    [ wait-to-accept ]
+    [ pending-error ]
+    [ [ client-addr>> ] [ client>> ] bi ] tri ;
 
 ! Datagram sockets - UDP and Unix domain
 M: unix <datagram>
@@ -128,10 +127,10 @@ packet-size <byte-array> receive-buffer set-global
         rot head
     ] if ;
 
-TUPLE: receive-task ;
+TUPLE: receive-task < input-task ;
 
 : <receive-task> ( stream continuation  -- task )
-    receive-task <input-task> ;
+    receive-task <io-task> ;
 
 M: receive-task do-io-task
     io-task-port
@@ -148,19 +147,18 @@ M: receive-task do-io-task
     [ <receive-task> add-io-task ] with-port-continuation drop ;
 
 M: unix receive ( datagram -- packet addrspec )
-    dup check-datagram-port
-    dup wait-receive
-    dup pending-error
-    dup datagram-port-packet
-    swap datagram-port-packet-addr ;
+    check-datagram-port
+    [ wait-receive ]
+    [ pending-error ]
+    [ [ packet>> ] [ packet-addr>> ] bi ] tri ;
 
 : do-send ( socket data sockaddr len -- n )
     >r >r dup length 0 r> r> sendto ;
 
-TUPLE: send-task packet sockaddr len ;
+TUPLE: send-task < output-task packet sockaddr len ;
 
 : <send-task> ( packet sockaddr len stream continuation -- task )
-    send-task <output-task> [
+    send-task <io-task> [
         {
             set-send-task-packet
             set-send-task-sockaddr
@@ -180,7 +178,7 @@ M: send-task do-io-task
     2drop 2drop ;
 
 M: unix send ( packet addrspec datagram -- )
-    3dup check-datagram-send
+    check-datagram-send
     [ >r make-sockaddr/size r> wait-send ] keep
     pending-error ;
 
index c8ed4fc41c41afc8620ee00fe80e6554989dea1f..ff315bc5299e7433f864e2f7dc237e0293491358 100755 (executable)
@@ -11,7 +11,7 @@ IN: io.unix.tests
 
     socket-server <local>
     ascii <server> [
-        accept [
+        accept drop [
             "Hello world" print flush
             readln "XYZ" = "FOO" "BAR" ? print flush
         ] with-stream
index b4328f31b3df1620097b13d85c618e8504f8d016..1e5638fb4a1c66d1de1bdce41869cd349569dc75 100755 (executable)
@@ -1,5 +1,5 @@
 USING: io.unix.backend io.unix.files io.unix.sockets io.timeouts
 io.unix.launcher io.unix.mmap io.backend combinators namespaces
-system vocabs.loader sequences words ;
+system vocabs.loader sequences words init ;
 
 "io.unix." os word-name append require
diff --git a/extra/io/windows/launcher/launcher-tests.factor b/extra/io/windows/launcher/launcher-tests.factor
new file mode 100755 (executable)
index 0000000..1dba8bd
--- /dev/null
@@ -0,0 +1,10 @@
+IN: io.windows.launcher.tests\r
+USING: tools.test io.windows.launcher ;\r
+\r
+[ "hello world" ] [ { "hello" "world" } join-arguments ] unit-test\r
+\r
+[ "bob \"mac arthur\"" ] [ { "bob" "mac arthur" } join-arguments ] unit-test\r
+\r
+[ "bob mac\\\\arthur" ] [ { "bob" "mac\\\\arthur" } join-arguments ] unit-test\r
+\r
+[ "bob \"mac arthur\\\\\"" ] [ { "bob" "mac arthur\\" } join-arguments ] unit-test\r
index 2724966a8f8d75e26ee81e515336e1fcffa4f5cc..04e149d26124c8a2c58facaefb42af85c10aaca1 100755 (executable)
@@ -1,11 +1,12 @@
 ! Copyright (C) 2007, 2008 Doug Coleman, Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien alien.c-types arrays continuations destructors io
+USING: alien alien.c-types arrays continuations io
 io.windows io.windows.nt.pipes libc io.nonblocking
-io.streams.duplex windows.types math windows.kernel32 windows
-namespaces io.launcher kernel sequences windows.errors assocs
+io.streams.duplex windows.types math windows.kernel32
+namespaces io.launcher kernel sequences windows.errors
 splitting system threads init strings combinators
-io.backend accessors concurrency.flags io.files ;
+io.backend accessors concurrency.flags io.files assocs
+io.files.private windows destructors ;
 IN: io.windows.launcher
 
 TUPLE: CreateProcess-args
@@ -27,8 +28,7 @@ TUPLE: CreateProcess-args
     "STARTUPINFO" heap-size over set-STARTUPINFO-cb >>lpStartupInfo
     "PROCESS_INFORMATION" <c-object> >>lpProcessInformation
     TRUE >>bInheritHandles
-    0 >>dwCreateFlags
-    current-directory get (normalize-path) >>lpCurrentDirectory ;
+    0 >>dwCreateFlags ;
 
 : call-CreateProcess ( CreateProcess-args -- )
     {
@@ -44,8 +44,21 @@ TUPLE: CreateProcess-args
         lpProcessInformation>>
     } get-slots CreateProcess win32-error=0/f ;
 
+: count-trailing-backslashes ( str n -- str n )
+    >r "\\" ?tail [
+        r> 1+ count-trailing-backslashes
+    ] [
+        r>
+    ] if ;
+
+: fix-trailing-backslashes ( str -- str' )
+    0 count-trailing-backslashes
+    2 * CHAR: \\ <repetition> append ;
+
 : escape-argument ( str -- newstr )
-    CHAR: \s over member? [ "\"" swap "\"" 3append ] when ;
+    CHAR: \s over member? [
+        "\"" swap fix-trailing-backslashes "\"" 3append
+    ] when ;
 
 : join-arguments ( args -- cmd-line )
     [ escape-argument ] map " " join ;
@@ -116,6 +129,8 @@ M: windows current-process-handle ( -- handle )
 
 M: windows run-process* ( process -- handle )
     [
+        current-directory get (normalize-path) cd
+
         dup make-CreateProcess-args
         tuck fill-redirection
         dup call-CreateProcess
@@ -142,26 +157,10 @@ M: windows kill-process* ( handle -- )
     over process-handle dispose-process
     notify-exit ;
 
-: wait-for-processes ( processes -- ? )
-    keys dup
+M: windows wait-for-processes ( -- ? )
+    processes get keys dup
     [ process-handle PROCESS_INFORMATION-hProcess ] map
     dup length swap >c-void*-array 0 0
     WaitForMultipleObjects
     dup HEX: ffffffff = [ win32-error ] when
     dup WAIT_TIMEOUT = [ 2drop t ] [ swap nth process-exited f ] if ;
-
-SYMBOL: wait-flag
-
-: wait-loop ( -- )
-    processes get dup assoc-empty?
-    [ drop wait-flag get-global lower-flag ]
-    [ wait-for-processes [ 100 sleep ] when ] if ;
-
-: start-wait-thread ( -- )
-    <flag> wait-flag set-global
-    [ wait-loop t ] "Process wait" spawn-server drop ;
-
-M: windows register-process
-    drop wait-flag get-global raise-flag ;
-
-[ start-wait-thread ] "io.windows.launcher" add-init-hook
index 822973b85bf14cf5a7d088dbed88f2f0f6d66b33..3c490b780c9f9134be0a3259ba0f20b86f80fdcb 100755 (executable)
@@ -39,7 +39,7 @@ M: winnt add-completion ( handle -- )
         GetLastError {
             { [ dup expected-io-error? ] [ 2drop t ] }
             { [ dup eof? ] [ drop t swap set-port-eof? f ] }
-            { [ t ] [ (win32-error-string) throw ] }
+            [ (win32-error-string) throw ]
         } cond
     ] [
         drop t
index 1e6268fbc0b0025b36f8eca71e9c11612514926a..0fa4b4151c5c51e4f86c5fa812478e321e144ced 100755 (executable)
@@ -27,8 +27,6 @@ IN: io.windows.nt.files.tests
 [ f ] [ "." root-directory? ] unit-test
 [ f ] [ ".." root-directory? ] unit-test
 
-[ ] [ "" resource-path cd ] unit-test
-
 [ "\\foo\\bar" ] [ "/foo/bar" normalize-path ":" split1 nip ] unit-test
 
 [ "\\\\?\\C:\\builds\\factor\\log.txt" ] [
index 3232ab6ff355de1fac8e79e544bec5502d62ce33..745b9f6afcf69b7f9df6410aa2d39add8c98e99a 100755 (executable)
@@ -25,7 +25,7 @@ M: winnt root-directory? ( path -- ? )
           { [ dup length 2 = ] [ dup second CHAR: : = ] } && nip ] [
             t
         ] }
-        { [ t ] [ f ] }
+        [ f ]
     } cond nip ;
 
 ERROR: not-absolute-path ;
@@ -64,7 +64,7 @@ M: winnt FileArgs-overlapped ( port -- overlapped )
     dup pending-error
     tuck get-overlapped-result
     dup pick update-file-ptr
-    swap buffer-consume ;
+    swap buffer>> buffer-consume ;
 
 : (flush-output) ( port -- )
     dup make-FileArgs
@@ -73,7 +73,7 @@ M: winnt FileArgs-overlapped ( port -- overlapped )
         >r FileArgs-lpOverlapped r>
         [ save-callback ] 2keep
         [ finish-flush ] keep
-        dup buffer-empty? [ drop ] [ (flush-output) ] if
+        dup buffer>> buffer-empty? [ drop ] [ (flush-output) ] if
     ] [
         2drop
     ] if ;
@@ -82,7 +82,7 @@ M: winnt FileArgs-overlapped ( port -- overlapped )
     [ [ (flush-output) ] with-timeout ] with-destructors ;
 
 M: port port-flush
-    dup buffer-empty? [ dup flush-output ] unless drop ;
+    dup buffer>> buffer-empty? [ dup flush-output ] unless drop ;
 
 : finish-read ( overlapped port -- )
     dup pending-error
index fac6471b8cbeaec73965a57aa265028ad52645cb..8b13b9b3b952bbe007e2a8b49829acbf769b2f5d 100755 (executable)
@@ -1,7 +1,7 @@
 IN: io.windows.launcher.nt.tests\r
 USING: io.launcher tools.test calendar accessors\r
 namespaces kernel system arrays io io.files io.encodings.ascii\r
-sequences parser assocs hashtables ;\r
+sequences parser assocs hashtables math ;\r
 \r
 [ ] [\r
     <process>\r
@@ -129,3 +129,14 @@ sequences parser assocs hashtables ;
 \r
     "HOME" swap at "XXX" =\r
 ] unit-test\r
+\r
+2 [\r
+    [ ] [\r
+        <process>\r
+            "cmd.exe /c dir" >>command\r
+            "dir.txt" temp-file >>stdout\r
+        try-process\r
+    ] unit-test\r
+\r
+    [ ] [ "dir.txt" temp-file delete-file ] unit-test\r
+] times\r
index 4bbf7c8e32425372c37db1045af669b427c38c67..f57902608f5acad544f01dace0370b495ce5265c 100755 (executable)
@@ -4,8 +4,8 @@ USING: alien alien.c-types arrays continuations destructors io
 io.windows libc io.nonblocking io.streams.duplex windows.types
 math windows.kernel32 windows namespaces io.launcher kernel
 sequences windows.errors assocs splitting system strings
-io.windows.launcher io.windows.nt.pipes io.backend
-combinators shuffle accessors locals ;
+io.windows.launcher io.windows.nt.pipes io.backend io.files
+io.files.private combinators shuffle accessors locals ;
 IN: io.windows.nt.launcher
 
 : duplicate-handle ( handle -- handle' )
@@ -39,7 +39,7 @@ IN: io.windows.nt.launcher
     create-mode
     FILE_ATTRIBUTE_NORMAL ! flags and attributes
     f ! template file
-    CreateFile dup invalid-handle? dup close-later ;
+    CreateFile dup invalid-handle? dup close-always ;
 
 : set-inherit ( handle ? -- )
     >r HANDLE_FLAG_INHERIT r> >BOOLEAN SetHandleInformation win32-error=0/f ;
@@ -55,7 +55,7 @@ IN: io.windows.nt.launcher
         { [ pick +inherit+ eq? ] [ redirect-inherit ] }
         { [ pick +closed+ eq? ] [ redirect-closed ] }
         { [ pick string? ] [ redirect-file ] }
-        { [ t ] [ redirect-stream ] }
+        [ redirect-stream ]
     } cond ;
 
 : default-stdout ( args -- handle )
@@ -120,6 +120,8 @@ M: winnt fill-redirection ( process args -- )
 
 M: winnt (process-stream)
     [
+        current-directory get (normalize-path) cd
+
         dup make-CreateProcess-args
 
         fill-stdout-pipe
index 164b529b617ea16205946657af3e196257d07940..8f873ee23bbe87c608c768c9c3740a677bee3c4e 100755 (executable)
@@ -37,10 +37,12 @@ M: winnt <monitor> ( path recursive? -- monitor )
     ] with-destructors ;
 
 : begin-reading-changes ( monitor -- overlapped )
-    dup port-handle win32-file-handle
-    over buffer-ptr
-    pick buffer-size
-    roll win32-monitor-recursive? 1 0 ?
+    {
+        [ handle>> handle>> ]
+        [ buffer>> buffer-ptr ]
+        [ buffer>> buffer-size ]
+        [ win32-monitor-recursive? 1 0 ? ]
+    } cleave
     FILE_NOTIFY_CHANGE_ALL
     0 <uint>
     (make-overlapped)
@@ -58,13 +60,13 @@ M: winnt <monitor> ( path recursive? -- monitor )
 
 : parse-action ( action -- changed )
     {
-        { [ dup FILE_ACTION_ADDED = ] [ +add-file+ ] }
-        { [ dup FILE_ACTION_REMOVED = ] [ +remove-file+ ] }
-        { [ dup FILE_ACTION_MODIFIED = ] [ +modify-file+ ] }
-        { [ dup FILE_ACTION_RENAMED_OLD_NAME = ] [ +rename-file+ ] }
-        { [ dup FILE_ACTION_RENAMED_NEW_NAME = ] [ +rename-file+ ] }
-        { [ t ] [ +modify-file+ ] }
-    } cond nip ;
+        { \ FILE_ACTION_ADDED [ +add-file+ ] }
+        { \ FILE_ACTION_REMOVED [ +remove-file+ ] }
+        { \ FILE_ACTION_MODIFIED [ +modify-file+ ] }
+        { \ FILE_ACTION_RENAMED_OLD_NAME [ +rename-file+ ] }
+        { \ FILE_ACTION_RENAMED_NEW_NAME [ +rename-file+ ] }
+        [ drop +modify-file+ ]
+    } case ;
 
 : memory>u16-string ( alien len -- string )
     [ memory>byte-array ] keep 2/ c-ushort-array> >string ;
@@ -82,6 +84,6 @@ M: winnt <monitor> ( path recursive? -- monitor )
     [ 2drop ] [ swap <displaced-alien> (changed-files) ] if ;
 
 M: win32-monitor fill-queue ( monitor -- )
-    dup buffer-ptr over read-changes
+    dup buffer>> buffer-ptr over read-changes
     [ zero? [ drop ] [ (changed-files) ] if ] H{ } make-assoc
     swap set-monitor-queue ;
index 36acaac992a481af0b6be909b107ac34db9ae8fa..c0dc0afd0610251268318c09e74b5873b66ba4dd 100755 (executable)
@@ -122,7 +122,7 @@ TUPLE: AcceptEx-args port
 M: winnt (accept) ( server -- addrspec handle )
     [
         [
-            dup check-server-port
+            check-server-port
             \ AcceptEx-args construct-empty
             [ init-accept ] keep
             [ ((accept)) ] keep
@@ -159,7 +159,7 @@ TUPLE: WSARecvFrom-args port
 : init-WSARecvFrom ( datagram WSARecvFrom -- )
     [ set-WSARecvFrom-args-port ] 2keep
     [
-        >r delegate port-handle delegate win32-file-handle r>
+        >r handle>> handle>> r>
         set-WSARecvFrom-args-s*
     ] 2keep [
         >r datagram-port-addr sockaddr-type heap-size r>
@@ -192,7 +192,7 @@ TUPLE: WSARecvFrom-args port
 
 M: winnt receive ( datagram -- packet addrspec )
     [
-        dup check-datagram-port
+        check-datagram-port
         \ WSARecvFrom-args construct-empty
         [ init-WSARecvFrom ] keep
         [ call-WSARecvFrom ] keep
@@ -244,7 +244,7 @@ USE: io.sockets
 
 M: winnt send ( packet addrspec datagram -- )
     [
-        3dup check-datagram-send
+        check-datagram-send
         \ WSASendTo-args construct-empty
         [ init-WSASendTo ] keep
         [ call-WSASendTo ] keep
index 7755f111c657001ac65bb00501b859f2b4962a73..89a78f1f74d4d065c62281450b717f822b8a60c1 100755 (executable)
@@ -32,7 +32,8 @@ M: windows normalize-directory ( string -- string )
 
 : default-security-attributes ( -- obj )
     "SECURITY_ATTRIBUTES" <c-object>
-    "SECURITY_ATTRIBUTES" heap-size over set-SECURITY_ATTRIBUTES-nLength ;
+    "SECURITY_ATTRIBUTES" heap-size
+    over set-SECURITY_ATTRIBUTES-nLength ;
 
 : security-attributes-inherit ( -- obj )
     default-security-attributes
@@ -47,8 +48,8 @@ M: win32-file close-handle ( handle -- )
 ! Clean up resources (open handle) if add-completion fails
 : open-file ( path access-mode create-mode flags -- handle )
     [
-        >r >r
-        share-mode security-attributes-inherit r> r> CreateFile-flags f CreateFile
+        >r >r share-mode security-attributes-inherit r> r>
+        CreateFile-flags f CreateFile
         dup invalid-handle? dup close-later
         dup add-completion
     ] with-destructors ;
@@ -91,19 +92,20 @@ M: win32-file close-handle ( handle -- )
     ] when drop ;
 
 : open-append ( path -- handle length )
-    [ dup file-info file-info-size ] [ drop 0 ] recover
+    [ dup file-info size>> ] [ drop 0 ] recover
     >r (open-append) r> 2dup set-file-pointer ;
 
 TUPLE: FileArgs
-    hFile lpBuffer nNumberOfBytesToRead lpNumberOfBytesRet lpOverlapped ;
+    hFile lpBuffer nNumberOfBytesToRead
+    lpNumberOfBytesRet lpOverlapped ;
 
 C: <FileArgs> FileArgs
 
 : make-FileArgs ( port -- <FileArgs> )
     [ port-handle win32-file-handle ] keep
-    [ delegate ] keep
+    [ buffer>> ] keep
     [
-        buffer-length
+        buffer>> buffer-length
         "DWORD" <c-object>
     ] keep FileArgs-overlapped <FileArgs> ;
 
@@ -150,11 +152,10 @@ M: windows delete-directory ( path -- )
 
 HOOK: WSASocket-flags io-backend ( -- DWORD )
 
-TUPLE: win32-socket ;
+TUPLE: win32-socket < win32-file ;
 
 : <win32-socket> ( handle -- win32-socket )
-    f <win32-file>
-    \ win32-socket construct-delegate ;
+    f win32-file construct-boa ;
 
 : open-socket ( family type -- socket )
     0 f 0 WSASocket-flags WSASocket dup socket-error ;
@@ -195,4 +196,3 @@ M: windows addrinfo-error ( n -- )
 
 : tcp-socket ( addrspec -- socket )
     protocol-family SOCK_STREAM open-socket ;
-
index 8a39846fc4553f0b73f3f8bd00205cb1e32ddaee..27f82b25eb116f445f6c785ae064d9a6bcc6b1f2 100755 (executable)
 ! Copyright (C) 2007 Doug Coleman, Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: arrays calendar io io.sockets kernel match namespaces
-sequences splitting strings continuations threads ascii
-io.encodings.utf8 ;
+USING: arrays calendar combinators channels concurrency.messaging fry io
+       io.encodings.8-bit io.sockets kernel math namespaces sequences
+       sequences.lib splitting strings threads
+       continuations classes.tuple ascii accessors ;
 IN: irc
 
+! utils
+: split-at-first ( seq separators -- before after )
+    dupd '[ , member? ] find
+        [ cut 1 tail ]
+        [ swap ]
+    if ;
+
+: spawn-server-linked ( quot name -- thread )
+    >r '[ , [ ] [ ] while ] r>
+    spawn-linked ;
+! ---
+
+! Default irc port
+: irc-port 6667 ;
+
+! Message used when the client isn't running anymore
+SINGLETON: irc-end
+
 ! "setup" objects
-TUPLE: profile server port nickname password default-channels ;
-C: <profile> profile
+TUPLE: irc-profile server port nickname password default-channels  ;
+C: <irc-profile> irc-profile
 
-TUPLE: channel-profile name password auto-rejoin ;
-C: <channel-profile> channel-profile
+TUPLE: irc-channel-profile name password auto-rejoin ;
+C: <irc-channel-profile> irc-channel-profile
 
 ! "live" objects
-TUPLE: irc-client profile nick stream stream-process controller-process ;
-C: <irc-client> irc-client
-
 TUPLE: nick name channels log ;
 C: <nick> nick
 
-TUPLE: channel name topic members log attributes ;
-C: <channel> channel
+TUPLE: irc-client profile nick stream stream-channel controller-channel
+       listeners is-running ;
+: <irc-client> ( profile -- irc-client )
+    f V{ } clone V{ } clone <nick>
+    f <channel> <channel> V{ } clone f irc-client construct-boa ;
+
+USE: prettyprint
+TUPLE: irc-listener channel ;
+! FIXME: spawn-server-linked con manejo de excepciones, mandar un mensaje final (ya se maneja esto al recibir mensajes del channel? )
+! tener la opción de dejar de correr un client??
+: <irc-listener> ( quot -- irc-listener )
+    <channel> irc-listener construct-boa swap
+    [
+        [ channel>> '[ , from ] ]
+        [ '[ , curry f spawn drop ] ]
+        bi* compose "irc-listener" spawn-server-linked drop
+    ] [ drop ] 2bi ;
+
+! TUPLE: irc-channel name topic members log attributes ;
+! C: <irc-channel> irc-channel
 
 ! the delegate of all irc messages
-TUPLE: irc-message timestamp ;
+TUPLE: irc-message line prefix command parameters trailing timestamp ;
 C: <irc-message> irc-message
 
 ! "irc message" objects
-TUPLE: logged-in name text ;
+TUPLE: logged-in < irc-message name ;
 C: <logged-in> logged-in
 
-TUPLE: ping name ;
+TUPLE: ping < irc-message ;
 C: <ping> ping
 
-TUPLE: join name channel ;
-C: <join> join
+TUPLE: join_ < irc-message ;
+C: <join> join_
 
-TUPLE: part name channel text ;
+TUPLE: part < irc-message name channel ;
 C: <part> part
 
-TUPLE: quit text ;
+TUPLE: quit ;
 C: <quit> quit
 
-TUPLE: privmsg name text ;
+TUPLE: privmsg < irc-message name ;
 C: <privmsg> privmsg
 
-TUPLE: kick channel er ee text ;
+TUPLE: kick < irc-message channel who ;
 C: <kick> kick
 
-TUPLE: roomlist channel names ;
+TUPLE: roomlist < irc-message channel names ;
 C: <roomlist> roomlist
 
-TUPLE: nick-in-use name ;
+TUPLE: nick-in-use < irc-message name ;
 C: <nick-in-use> nick-in-use
 
-TUPLE: notice type text ;
+TUPLE: notice < irc-message type ;
 C: <notice> notice
 
-TUPLE: mode name channel mode text ;
+TUPLE: mode < irc-message name channel mode ;
 C: <mode> mode
-! TUPLE: members
 
-TUPLE: unhandled text ;
+TUPLE: unhandled < irc-message ;
 C: <unhandled> unhandled
 
-! "control message" objects
-TUPLE: command sender ;
-TUPLE: service predicate quot enabled? ;
-TUPLE: chat-command from to text ;
-TUPLE: join-command channel password ;
-TUPLE: part-command channel text ;
-
 SYMBOL: irc-client
-: irc-stream> ( -- stream ) irc-client get irc-client-stream ;
-: trim-: ( seq -- seq ) [ CHAR: : = ] left-trim ;
+: irc-client> ( -- irc-client ) irc-client get ;
+: irc-stream> ( -- stream ) irc-client> stream>> ;
+
+: remove-heading-: ( seq -- seq ) dup ":" head? [ 1 tail ] when ;
+
 : parse-name ( string -- string )
-    trim-: "!" split first ;
-: irc-split ( string -- seq )
-    1 swap [ [ CHAR: : = ] find* ] keep
-    swap [ swap cut trim-: ] [ nip f ] if >r [ blank? ] trim trim-:
-    " " split r> [ 1array append ] when* ;
+    remove-heading-: "!" split-at-first drop ;
+
+: sender>> ( obj -- string )
+    prefix>> parse-name ;
+
+: split-prefix ( string -- string/f string )
+    dup ":" head?
+        [ remove-heading-: " " split1 ]
+        [ f swap ]
+    if ;
+
+: split-trailing ( string -- string string/f )
+    ":" split1 ;
+
+: string>irc-message ( string -- object )
+    dup split-prefix split-trailing
+    [ [ blank? ] trim " " split unclip swap ] dip
+    now <irc-message> ;
+
 : me? ( name -- ? )
-    irc-client get irc-client-nick nick-name = ;
+    irc-client> nick>> name>> = ;
 
 : irc-write ( s -- )
     irc-stream> stream-write ;
@@ -89,123 +132,155 @@ SYMBOL: irc-client
 : irc-print ( s -- )
     irc-stream> [ stream-print ] keep stream-flush ;
 
-: nick ( nick -- )
+! Irc commands    
+
+: NICK ( nick -- )
     "NICK " irc-write irc-print ;
 
-: login ( nick -- )
-    dup nick
+: LOGIN ( nick -- )
+    dup NICK
     "USER " irc-write irc-write
     " hostname servername :irc.factor" irc-print ;
 
-: connect* ( server port -- )
-    <inet> utf8 <client> irc-client get set-irc-client-stream ;
-
-: connect ( server -- ) 6667 connect* ;
+: CONNECT ( server port -- stream )
+    <inet> latin1 <client> ;
 
-: join ( channel password -- )
+: JOIN ( channel password -- )
     "JOIN " irc-write
-    [ >r " :" r> 3append ] when* irc-print ;
+    [ " :" swap 3append ] when* irc-print ;
 
-: part ( channel text -- )
-    >r "PART " irc-write irc-write r>
+: PART ( channel text -- )
+    [ "PART " irc-write irc-write ] dip
     " :" irc-write irc-print ;
 
-: say ( line nick -- )
-    "PRIVMSG " irc-write irc-write " :" irc-write irc-print ;
+: KICK ( channel who -- )
+    [ "KICK " irc-write irc-write ] dip
+    " " irc-write irc-print ;
+    
+: PRIVMSG ( nick line -- )
+    [ "PRIVMSG " irc-write irc-write ] dip
+    " :" irc-write irc-print ;
+
+: SAY ( nick line -- )
+    PRIVMSG ;
 
-: quit ( text -- )
+: ACTION ( nick line -- )
+    [ 1 , "ACTION " % % 1 , ] "" make PRIVMSG ;
+
+: QUIT ( text -- )
     "QUIT :" irc-write irc-print ;
 
+: join-channel ( channel-profile -- )
+    [ name>> ] keep password>> JOIN ;
 
+: irc-connect ( irc-client -- )
+    [ profile>> [ server>> ] keep port>> CONNECT ] keep
+    swap >>stream t >>is-running drop ;
+    
 GENERIC: handle-irc ( obj -- )
 
 M: object handle-irc ( obj -- )
-    "Unhandled irc object" print drop ;
+    drop ;
 
 M: logged-in handle-irc ( obj -- )
-    logged-in-name irc-client get [ irc-client-nick set-nick-name ] keep
-    
-    irc-client-profile profile-default-channels
-    [
-        [ channel-profile-name ] keep
-        channel-profile-password join
-    ] each ;
+    name>>
+    irc-client> [ nick>> swap >>name drop ] keep 
+    profile>> default-channels>> [ join-channel ] each ;
 
 M: ping handle-irc ( obj -- )
     "PONG " irc-write
-    ping-name irc-print ;
+    trailing>> irc-print ;
 
 M: nick-in-use handle-irc ( obj -- )
-    nick-in-use-name "_" append nick ;
-
-: delegate-timestamp ( obj -- obj )
-    now <irc-message> over set-delegate ;
-
-MATCH-VARS: ?name ?name2 ?channel ?text ?mode ;
-SYMBOL: line
-: match-irc ( string -- )
-    dup line set
-    dup print flush
-    irc-split
-    {
-        { { "PING" ?name }
-          [ ?name <ping> ] }
-        { { ?name "001" ?name2 ?text }
-          [ ?name2 ?text <logged-in> ] }
-        { { ?name "433" _ ?name2 "Nickname is already in use." }
-          [ ?name2 <nick-in-use> ] }
-
-        { { ?name "JOIN" ?channel }
-          [ ?name ?channel <join> ] }
-        { { ?name "PART" ?channel ?text }
-          [ ?name ?channel ?text <part> ] }
-        { { ?name "PRIVMSG" ?channel ?text }
-          [ ?name ?channel ?text <privmsg> ] }
-        { { ?name "QUIT" ?text }
-          [ ?name ?text <quit> ] }
-
-        { { "NOTICE" ?name ?text }
-          [ ?name ?text <notice> ] }
-        { { ?name "MODE" ?channel ?mode ?text }
-          [ ?name ?channel ?mode ?text <mode> ] }
-        { { ?name "KICK" ?channel ?name2 ?text }
-          [  ?channel ?name ?name2 ?text <kick> ] }
-
-        ! { { ?name "353" ?name2 _ ?channel ?text }
-         ! [ ?text ?channel ?name2 make-member-list ] }
-        { _ [ line get <unhandled> ] }
-    } match-cond
-    delegate-timestamp handle-irc flush ;
-
-: irc-loop ( -- )
-    irc-stream> stream-readln
-    [ match-irc irc-loop ] when* ;
-
+    name>> "_" append NICK ;
+
+: parse-irc-line ( string -- message )
+    string>irc-message
+    dup command>> {
+        { "PING" [ \ ping ] }
+        { "NOTICE" [ \ notice ] }
+        { "001" [ \ logged-in ] }
+        { "433" [ \ nick-in-use ] }
+        { "JOIN" [ \ join_ ] }
+        { "PART" [ \ part ] }
+        { "PRIVMSG" [ \ privmsg ] }
+        { "QUIT" [ \ quit ] }
+        { "MODE" [ \ mode ] }
+        { "KICK" [ \ kick ] }
+        [ drop \ unhandled ]
+    } case
+    [ [ tuple-slots ] [ parameters>> ] bi append ] dip prefix >tuple ;
+
+! Reader
+: handle-reader-message ( irc-client irc-message -- )
+    dup handle-irc swap stream-channel>> to ;
+
+: reader-loop ( irc-client -- )
+    dup stream>> stream-readln [
+        dup print parse-irc-line handle-reader-message
+    ] [
+        f >>is-running
+        dup stream>> dispose
+        irc-end over controller-channel>> to
+        stream-channel>> irc-end swap to
+    ] if* ;
+
+! Controller commands
+GENERIC: handle-command ( obj -- )
+
+M: object handle-command ( obj -- )
+    . ;
+
+TUPLE: send-message to text ;
+C: <send-message> send-message
+M: send-message handle-command ( obj -- )
+    dup to>> swap text>> SAY ;
+
+TUPLE: send-action to text ;
+C: <send-action> send-action
+M: send-action handle-command ( obj -- )
+    dup to>> swap text>> ACTION ;
+
+TUPLE: send-quit text ;
+C: <send-quit> send-quit
+M: send-quit handle-command ( obj -- )
+    text>> QUIT ;
+
+: irc-listen ( irc-client quot -- )
+    [ listeners>> ] [ <irc-listener> ] bi* swap push ;
+
+! Controller loop
+: controller-loop ( irc-client -- )
+    controller-channel>> from handle-command ;
+
+! Multiplexer
+: multiplex-message ( irc-client message -- )
+    swap listeners>> [ channel>> ] map
+    [ '[ , , to ] "message" spawn drop ] each-with ;
+
+: multiplexer-loop ( irc-client -- )
+    dup stream-channel>> from multiplex-message ;
+
+! process looping and starting
+: (spawn-irc-loop) ( irc-client quot name -- )
+    [ over >r curry r> '[ @ , is-running>> ] ] dip
+    spawn-server-linked drop ;
+
+: spawn-irc-loop ( irc-client quot name -- )
+    '[ , , , [ (spawn-irc-loop) receive ] [ print ] recover ]
+    f spawn drop ;
+
+: spawn-irc ( irc-client -- )
+    [ [ reader-loop ] "reader-loop" spawn-irc-loop ]
+    [ [ controller-loop ] "controller-loop" spawn-irc-loop ]
+    [ [ multiplexer-loop ] "multiplexer-loop" spawn-irc-loop ]
+    tri ;
+    
 : do-irc ( irc-client -- )
-    dup irc-client set
-    dup irc-client-profile profile-server
-    over irc-client-profile profile-port connect*
-    dup irc-client-profile profile-nickname login
-    [ irc-loop ] [ irc-stream> dispose ] [ ] cleanup ;
-
-: with-infinite-loop ( quot timeout -- quot timeout )
-    "looping" print flush
-    over [ drop ] recover dup sleep with-infinite-loop ;
-
-: start-irc ( irc-client -- )
-    ! [ [ do-irc ] curry 3000 with-infinite-loop ] with-scope ;
-    [ do-irc ] curry 3000 with-infinite-loop ;
-
-
-! For testing
-: make-factorbot
-    "irc.freenode.org" 6667 "factorbot" f
-    [
-        "#concatenative-flood" f f <channel-profile> ,
-    ] { } make <profile>
-    f V{ } clone V{ } clone <nick>
-    f f f <irc-client> ;
-
-: test-factorbot
-    make-factorbot start-irc ;
-
+    irc-client [
+        irc-client>
+        [ irc-connect ]
+        [ profile>> nickname>> LOGIN ]
+        [ spawn-irc ]
+        tri
+    ] with-variable ;
\ No newline at end of file
index add37173b753a043aee9d1e5e0cee917f8640540..e3c2997d0b5ebc3bb2414d767ad2b9373b214fd8 100755 (executable)
@@ -15,7 +15,7 @@ IN: koszul
         { [ dup number? ] [ { } associate ] }
         { [ dup array? ] [ 1 swap associate ] }
         { [ dup hashtable? ] [ ] }
-        { [ t ] [ 1array >alt ] }
+        [ 1array >alt ]
     } cond ;
 
 : canonicalize
@@ -31,10 +31,10 @@ SYMBOL: terms
 ! Printing elements
 : num-alt. ( n -- str )
     {
-        { [ dup 1 = ] [ drop " + " ] }
-        { [ dup -1 = ] [ drop " - " ] }
-        { [ t ] [ number>string " + " prepend ] }
-    } cond ;
+        { 1 [ " + " ] }
+        { -1 [ " - " ] }
+        [ number>string " + " prepend ]
+    } case ;
 
 : (alt.) ( basis n -- str )
     over empty? [
index f642d8881c99323df14a2c77b3af56d3f5cec2b5..ebd2fe9f2e2030e76cf083b683e1962ccaf8c9b7 100644 (file)
@@ -78,7 +78,7 @@ M: lazy-cons nil? ( lazy-cons -- bool )
   swap [ cdr ] times car ;
 
 : (llength) ( list acc -- n )
-  over nil? [ nip ] [ >r cdr r> 1+ (llength) ] if ;
+  over nil? [ nip ] [ [ cdr ] dip 1+ (llength) ] if ;
 
 : llength ( list -- n )
   0 (llength) ;
@@ -273,7 +273,7 @@ M: lazy-from-by car ( lazy-from-by -- car )
 
 M: lazy-from-by cdr ( lazy-from-by -- cdr )
   [ lazy-from-by-n ] keep
-  lazy-from-by-quot dup >r call r> lfrom-by ;
+  lazy-from-by-quot dup slip lfrom-by ;
 
 M: lazy-from-by nil? ( lazy-from-by -- bool )
   drop f ;
@@ -321,7 +321,7 @@ M: sequence-cons nil? ( sequence-cons -- bool )
   {
     { [ dup sequence? ] [ 0 swap seq>list ] }
     { [ dup list?     ] [ ] }
-    { [ t ] [ "Could not convert object to a list" throw ] }
+    [ "Could not convert object to a list" throw ]
   } cond ;
 
 TUPLE: lazy-concat car cdr ;
@@ -370,10 +370,10 @@ M: lazy-concat nil? ( lazy-concat -- bool )
   ] if ;
 
 : lcomp ( list quot -- result )
-  >r lcartesian-product* r> lmap ;
+  [ lcartesian-product* ] dip lmap ;
 
 : lcomp* ( list guards quot -- result )
-  >r >r lcartesian-product* r> [ lsubset ] each r> lmap ;
+  [ [ lcartesian-product* ] dip [ lsubset ] each ] dip lmap ;
 
 DEFER: lmerge
 
@@ -382,7 +382,7 @@ DEFER: lmerge
   [
     dup [ car ] curry -rot
     [
-      >r cdr r> cdr lmerge
+      [ cdr ] bi@ lmerge
     ] 2curry lazy-cons
   ] 2curry lazy-cons ;
 
@@ -419,7 +419,7 @@ M: lazy-io cdr ( lazy-io -- cdr )
     [ lazy-io-stream ] keep
     [ lazy-io-quot ] keep
     car [
-      >r f f r> <lazy-io> [ swap set-lazy-io-cdr ] keep
+      [ f f ] dip <lazy-io> [ swap set-lazy-io-cdr ] keep
     ] [
       3drop nil
     ] if
index fe4bd65c149bbcaaf59f11e09c8b4696a391cb32..a961dec3bde2916a710120bdd68a0c460ec172bd 100755 (executable)
@@ -3,9 +3,8 @@
 USING: kernel namespaces sequences sequences.private assocs math
 inference.transforms parser words quotations debugger macros
 arrays macros splitting combinators prettyprint.backend
-definitions prettyprint hashtables combinators.lib
-prettyprint.sections sequences.private effects generic
-compiler.units accessors ;
+definitions prettyprint hashtables prettyprint.sections
+sequences.private effects generic compiler.units accessors ;
 IN: locals
 
 ! Inspired by
index 015861501ecdfd18345479eeb4f75db5b14012ff..c6b073e50199d2215bc20e779f63b8819acd194a 100755 (executable)
@@ -66,7 +66,7 @@ MEMO: 'log-line' ( -- parser )
             parse-log-line {\r
                 { [ dup malformed? ] [ malformed-line ] }\r
                 { [ dup multiline? ] [ add-multiline ] }\r
-                { [ t ] [ , ] }\r
+                [ , ]\r
             } cond\r
         ] each\r
     ] { } make ;\r
index bed6a2fec33345e244b94e014f78f07dc7147f1b..c6aee034cc75f99b9727a940302ac129ccfee3a1 100755 (executable)
@@ -40,10 +40,10 @@ SYMBOL: log-files
     rot [ empty? not ] subset {\r
         { [ dup empty? ] [ 3drop ] }\r
         { [ dup length 1 = ] [ first -rot f (write-message) ] }\r
-        { [ t ] [\r
+        [\r
             [ first -rot f (write-message) ] 3keep\r
             1 tail -rot [ t (write-message) ] 2curry each\r
-        ] }\r
+        ]\r
     } cond ;\r
 \r
 : (log-message) ( msg -- )\r
index 825d58c7c2c2d43e29c369d6574f168c1a3a221e..e559ebc60d3e78eda47d94a297b0ddf17a90d65a 100755 (executable)
@@ -58,7 +58,7 @@ MACRO: match-cond ( assoc -- )
         { [ dup match-var? ] [ get ] }
         { [ dup sequence? ] [ [ replace-patterns ] map ] }
         { [ dup tuple? ] [ tuple>array replace-patterns >tuple ] }
-        { [ t ] [ ] }
+        [ ]
     } cond ;
 
 : match-replace ( object pattern1 pattern2 -- result )
index 77c7d9247dda521e994a4ac7ef3747dcb6f936ea..b3cfba8650ff810b6863fd803a120897fbf0cc3a 100755 (executable)
@@ -99,7 +99,7 @@ M: real absq sq ;
         { [ pick fp-nan? pick fp-nan? or ] [ 3drop f ] }
         { [ dup zero? ] [ drop number= ] }
         { [ dup 0 < ] [ ~rel ] }
-        { [ t ] [ ~abs ] }
+        [ ~abs ]
     } cond ;
 
 : power-of-2? ( n -- ? )
index ea7f02829dc7c85ee9110fd0c09c8b0afeaaf352..c8a21512ecb81d36098a4f765765cd1ba600f60f 100755 (executable)
@@ -55,7 +55,7 @@ TUPLE: miller-rabin-bounds ;
         { [ dup 1 <= ] [ 3drop f ] }
         { [ dup 2 = ] [ 3drop t ] }
         { [ dup even? ] [ 3drop f ] }
-        { [ t ] [ [ drop trials set t (miller-rabin) ] with-scope ] }
+        [ [ drop trials set t (miller-rabin) ] with-scope ]
     } cond ;
 
 : miller-rabin ( n -- ? ) 10 miller-rabin* ;
diff --git a/extra/math/points/points.factor b/extra/math/points/points.factor
new file mode 100644 (file)
index 0000000..5efd6e0
--- /dev/null
@@ -0,0 +1,22 @@
+
+USING: kernel arrays math.vectors ;
+
+IN: math.points
+
+<PRIVATE
+
+: X ( x -- point )      0   0 3array ;
+: Y ( y -- point ) 0 swap   0 3array ;
+: Z ( z -- point ) 0    0 rot 3array ;
+
+PRIVATE>
+
+: v+x ( seq x -- seq ) X v+ ;
+: v-x ( seq x -- seq ) X v- ;
+
+: v+y ( seq y -- seq ) Y v+ ;
+: v-y ( seq y -- seq ) Y v- ;
+
+: v+z ( seq z -- seq ) Z v+ ;
+: v-z ( seq z -- seq ) Z v- ;
+
index 685124e4e989183ffa7fdc3c75ad3efe6986c82e..edad69fffc650b94a12a5af5c1842640cc08e894 100644 (file)
@@ -38,14 +38,13 @@ PRIVATE>
     { [ dup 2 < ] [ drop { } ] }
     { [ dup 1000003 < ]
       [ primes-under-million [ [ <=> ] binsearch 1+ 0 swap ] keep <slice> ] }
-    { [ t ]
-      [ primes-under-million 1000003 lprimes-from
-        rot [ <= ] curry lwhile list>array append ] }
+    [ primes-under-million 1000003 lprimes-from
+        rot [ <= ] curry lwhile list>array append ]
   } cond ; foldable
 
 : primes-between ( low high -- seq )
   primes-upto
-  >r 1- next-prime r>
+  [ 1- next-prime ] dip
   [ [ <=> ] binsearch ] keep [ length ] keep <slice> ; foldable
 
 : coprime? ( a b -- ? ) gcd nip 1 = ; foldable
diff --git a/extra/multi-methods/multi-methods-tests.factor b/extra/multi-methods/multi-methods-tests.factor
deleted file mode 100755 (executable)
index 8910e64..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-IN: multi-methods.tests
-USING: multi-methods tools.test kernel math arrays sequences
-prettyprint strings classes hashtables assocs namespaces
-debugger continuations ;
-
-[ { 1 2 3 4 5 6 } ] [
-    { 6 4 5 1 3 2 } [ <=> ] topological-sort
-] unit-test
-
-[ -1 ] [
-    { fixnum array } { number sequence } classes<
-] unit-test
-
-[ 0 ] [
-    { number sequence } { number sequence } classes<
-] unit-test
-
-[ 1 ] [
-    { object object } { number sequence } classes<
-] unit-test
-
-[
-    {
-        { { object integer } [ 1 ] }
-        { { object object } [ 2 ] }
-        { { POSTPONE: f POSTPONE: f } [ 3 ] }
-    }
-] [
-    {
-        { { integer } [ 1 ] }
-        { { } [ 2 ] }
-        { { f f } [ 3 ] }
-    } congruify-methods
-] unit-test
-
-GENERIC: first-test
-
-[ t ] [ \ first-test generic? ] unit-test
-
-MIXIN: thing
-
-TUPLE: paper ;    INSTANCE: paper thing
-TUPLE: scissors ; INSTANCE: scissors thing
-TUPLE: rock ;     INSTANCE: rock thing
-
-GENERIC: beats?
-
-METHOD: beats? { paper scissors } t ;
-METHOD: beats? { scissors rock } t ;
-METHOD: beats? { rock paper } t ;
-METHOD: beats? { thing thing } f ;
-
-: play ( obj1 obj2 -- ? ) beats? 2nip ;
-
-[ { } 3 play ] must-fail
-[ t ] [ error get no-method? ] unit-test
-[ ] [ error get error. ] unit-test
-[ t ] [ T{ paper } T{ scissors } play ] unit-test
-[ f ] [ T{ scissors } T{ paper } play ] unit-test
-
-[ t ] [ { beats? paper scissors } method-spec? ] unit-test
-[ ] [ { beats? paper scissors } see ] unit-test
-
-GENERIC: legacy-test
-
-M: integer legacy-test sq ;
-M: string legacy-test " hey" append ;
-
-[ 25 ] [ 5 legacy-test ] unit-test
-[ "hello hey" ] [ "hello" legacy-test ] unit-test
-
-SYMBOL: some-var
-
-HOOK: hook-test some-var
-
-[ t ] [ \ hook-test hook-generic? ] unit-test
-
-METHOD: hook-test { array array } reverse ;
-METHOD: hook-test { array } class ;
-METHOD: hook-test { hashtable number } assoc-size ;
-
-{ 1 2 3 } some-var set
-[ { f t t } ] [ { t t f } hook-test ] unit-test
-[ fixnum ] [ 3 hook-test ] unit-test
-5.0 some-var set
-[ 0 ] [ H{ } hook-test ] unit-test
-
-MIXIN: busted
-
-TUPLE: busted-1 ;
-TUPLE: busted-2 ; INSTANCE: busted-2 busted
-TUPLE: busted-3 ;
-
-GENERIC: busted-sort
-
-METHOD: busted-sort { busted-1 busted-2 } ;
-METHOD: busted-sort { busted-2 busted-3 } ;
-METHOD: busted-sort { busted busted } ;
index 5ea19bc95747341531dc00de3d940e94864e0147..dd6fc7dfff6014c43d473894f141130c7bf2fd25 100755 (executable)
@@ -3,13 +3,74 @@
 USING: kernel math sequences vectors classes classes.algebra
 combinators arrays words assocs parser namespaces definitions
 prettyprint prettyprint.backend quotations arrays.lib
-debugger io compiler.units kernel.private effects ;
+debugger io compiler.units kernel.private effects accessors
+hashtables sorting shuffle ;
 IN: multi-methods
 
-GENERIC: generic-prologue ( combination -- quot )
+! PART I: Converting hook specializers
+: canonicalize-specializer-0 ( specializer -- specializer' )
+    [ \ f or ] map ;
 
-GENERIC: method-prologue ( combination -- quot )
+SYMBOL: args
 
+SYMBOL: hooks
+
+SYMBOL: total
+
+: canonicalize-specializer-1 ( specializer -- specializer' )
+    [
+        [ class? ] subset
+        [ length <reversed> [ 1+ neg ] map ] keep zip
+        [ length args [ max ] change ] keep
+    ]
+    [
+        [ pair? ] subset
+        [ keys [ hooks get push-new ] each ] keep
+    ] bi append ;
+
+: canonicalize-specializer-2 ( specializer -- specializer' )
+    [
+        >r
+        {
+            { [ dup integer? ] [ ] }
+            { [ dup word? ] [ hooks get index ] }
+        } cond args get + r>
+    ] assoc-map ;
+
+: canonicalize-specializer-3 ( specializer -- specializer' )
+    >r total get object <array> dup <enum> r> update ;
+
+: canonicalize-specializers ( methods -- methods' hooks )
+    [
+        [ >r canonicalize-specializer-0 r> ] assoc-map
+
+        0 args set
+        V{ } clone hooks set
+
+        [ >r canonicalize-specializer-1 r> ] assoc-map
+
+        hooks [ natural-sort ] change
+
+        [ >r canonicalize-specializer-2 r> ] assoc-map
+
+        args get hooks get length + total set
+
+        [ >r canonicalize-specializer-3 r> ] assoc-map
+
+        hooks get
+    ] with-scope ;
+
+: drop-n-quot ( n -- quot ) \ drop <repetition> >quotation ;
+
+: prepare-method ( method n -- quot )
+    [ 1quotation ] [ drop-n-quot ] bi* prepend ;
+
+: prepare-methods ( methods -- methods' prologue )
+    canonicalize-specializers
+    [ length [ prepare-method ] curry assoc-map ] keep
+    [ [ get ] curry ] map concat [ ] like ;
+
+! Part II: Topologically sorting specializers
 : maximal-element ( seq quot -- n elt )
     dupd [
         swapd [ call 0 < ] 2curry subset empty?
@@ -28,10 +89,14 @@ GENERIC: method-prologue ( combination -- quot )
             { [ 2dup [ class< ] 2keep swap class< and ] [ 0 ] }
             { [ 2dup class< ] [ -1 ] }
             { [ 2dup swap class< ] [ 1 ] }
-            { [ t ] [ 0 ] }
+            [ 0 ]
         } cond 2nip
     ] 2map [ zero? not ] find nip 0 or ;
 
+: sort-methods ( alist -- alist' )
+    [ [ first ] bi@ classes< ] topological-sort ;
+
+! PART III: Creating dispatch quotation
 : picker ( n -- quot )
     {
         { 0 [ [ dup ] ] }
@@ -52,206 +117,164 @@ GENERIC: method-prologue ( combination -- quot )
         unclip [ swap [ f ] \ if 3array append [ ] like ] reduce
     ] if ;
 
+: argument-count ( methods -- n )
+    keys 0 [ length max ] reduce ;
+
+ERROR: no-method arguments generic ;
+
+: make-default-method ( methods generic -- quot )
+    >r argument-count r> [ >r narray r> no-method ] 2curry ;
+
+: multi-dispatch-quot ( methods generic -- quot )
+    [ make-default-method ]
+    [ drop [ >r multi-predicate r> ] assoc-map reverse ]
+    2bi alist>quot ;
+
+! Generic words
+PREDICATE: generic < word
+    "multi-methods" word-prop >boolean ;
+
 : methods ( word -- alist )
     "multi-methods" word-prop >alist ;
 
-: make-method-def ( quot classes generic -- quot )
+: make-generic ( generic -- quot )
     [
-        swap [ declare ] curry %
-        "multi-combination" word-prop method-prologue %
-        %
+        [ methods prepare-methods % sort-methods ] keep
+        multi-dispatch-quot %
     ] [ ] make ;
 
-TUPLE: method word def classes generic loc ;
+: update-generic ( word -- )
+    dup make-generic define ;
 
+! Methods
 PREDICATE: method-body < word
-    "multi-method" word-prop >boolean ;
+    "multi-method-generic" word-prop >boolean ;
 
 M: method-body stack-effect
-    "multi-method" word-prop method-generic stack-effect ;
+    "multi-method-generic" word-prop stack-effect ;
+
+M: method-body crossref?
+    drop t ;
+
+: method-word-name ( specializer generic -- string )
+    [ word-name % "-" % unparse % ] "" make ;
 
-: method-word-name ( classes generic -- string )
+: method-word-props ( specializer generic -- assoc )
     [
-        word-name %
-        "-(" % [ "," % ] [ word-name % ] interleave ")" %
-    ] "" make ;
-
-: <method-word> ( quot classes generic -- word )
-    #! We xref here because the "multi-method" word-prop isn't
-    #! set yet so crossref? yields f.
-    [ make-method-def ] 2keep
+        "multi-method-generic" set
+        "multi-method-specializer" set
+    ] H{ } make-assoc ;
+
+: <method> ( specializer generic -- word )
+    [ method-word-props ] 2keep
     method-word-name f <word>
-    dup rot define
-    dup xref ;
+    [ set-word-props ] keep ;
 
-: <method> ( quot classes generic -- method )
-    [ <method-word> ] 3keep f \ method construct-boa
-    dup method-word over "multi-method" set-word-prop ;
+: with-methods ( word quot -- )
+    over >r >r "multi-methods" word-prop
+    r> call r> update-generic ; inline
 
-TUPLE: no-method arguments generic ;
+: reveal-method ( method classes generic -- )
+    [ set-at ] with-methods ;
 
-: no-method ( argument-count generic -- * )
-    >r narray r> \ no-method construct-boa throw ; inline
+: method ( classes word -- method )
+    "multi-methods" word-prop at ;
 
-: argument-count ( methods -- n )
-    dup assoc-empty? [ drop 0 ] [
-        keys [ length ] map supremum
+: create-method ( classes generic -- method )
+    2dup method dup [
+        2nip
+    ] [
+        drop [ <method> dup ] 2keep reveal-method
     ] if ;
 
-: multi-dispatch-quot ( methods generic -- quot )
-    >r [
-        [
-            >r multi-predicate r> method-word 1quotation
-        ] assoc-map
-    ] keep argument-count
-    r> [ no-method ] 2curry
-    swap reverse alist>quot ;
-
-: congruify-methods ( alist -- alist' )
-    dup argument-count [
-        swap >r object pad-left [ \ f or ] map r>
-    ] curry assoc-map ;
-
-: sorted-methods ( alist -- alist' )
-    [ [ first ] bi@ classes< ] topological-sort ;
-
 : niceify-method [ dup \ f eq? [ drop f ] when ] map ;
 
 M: no-method error.
     "Type check error" print
     nl
-    "Generic word " write dup no-method-generic pprint
+    "Generic word " write dup generic>> pprint
     " does not have a method applicable to inputs:" print
-    dup no-method-arguments short.
+    dup arguments>> short.
     nl
     "Inputs have signature:" print
-    dup no-method-arguments [ class ] map niceify-method .
+    dup arguments>> [ class ] map niceify-method .
     nl
-    "Defined methods in topological order: " print
-    no-method-generic
-    methods congruify-methods sorted-methods keys
-    [ niceify-method ] map stack. ;
-
-TUPLE: standard-combination ;
-
-M: standard-combination method-prologue drop [ ] ;
-
-M: standard-combination generic-prologue drop [ ] ;
-
-: make-generic ( generic -- quot )
-    dup "multi-combination" word-prop generic-prologue swap
-    [ methods congruify-methods sorted-methods ] keep
-    multi-dispatch-quot append ;
-
-TUPLE: hook-combination var ;
-
-M: hook-combination method-prologue
-    drop [ drop ] ;
+    "Available methods: " print
+    generic>> methods canonicalize-specializers drop sort-methods
+    keys [ niceify-method ] map stack. ;
 
-M: hook-combination generic-prologue
-    hook-combination-var [ get ] curry ;
+: forget-method ( specializer generic -- )
+    [ delete-at ] with-methods ;
 
-: update-generic ( word -- )
-    dup make-generic define ;
+: method>spec ( method -- spec )
+    [ "multi-method-specializer" word-prop ]
+    [ "multi-method-generic" word-prop ] bi prefix ;
 
-: define-generic ( word combination -- )
-    over "multi-combination" word-prop over = [
-        2drop
+: define-generic ( word -- )
+    dup "multi-methods" word-prop [
+        drop
     ] [
-        dupd "multi-combination" set-word-prop
-        dup H{ } clone "multi-methods" set-word-prop
-        update-generic
+        [ H{ } clone "multi-methods" set-word-prop ]
+        [ update-generic ]
+        bi
     ] if ;
 
-: define-standard-generic ( word -- )
-    T{ standard-combination } define-generic ;
-
+! Syntax
 : GENERIC:
-    CREATE define-standard-generic ; parsing
-
-: define-hook-generic ( word var -- )
-    hook-combination construct-boa define-generic ;
-
-: HOOK:
-    CREATE scan-word define-hook-generic ; parsing
-
-: method ( classes word -- method )
-    "multi-methods" word-prop at ;
-
-: with-methods ( word quot -- )
-    over >r >r "multi-methods" word-prop
-    r> call r> update-generic ; inline
+    CREATE define-generic ; parsing
 
-: define-method ( quot classes generic -- )
-    >r [ bootstrap-word ] map r>
-    [ <method> ] 2keep
-    [ set-at ] with-methods ;
+: parse-method ( -- quot classes generic )
+    parse-definition [ 2 tail ] [ second ] [ first ] tri ;
 
-: forget-method ( classes generic -- )
-    [ delete-at ] with-methods ;
+: create-method-in ( specializer generic -- method )
+    create-method dup save-location f set-word ;
 
-: method>spec ( method -- spec )
-    dup method-classes swap method-generic prefix ;
+: CREATE-METHOD
+    scan-word scan-object swap create-method-in ;
 
-: parse-method ( -- quot classes generic )
-    parse-definition dup 2 tail over second rot first ;
+: (METHOD:) CREATE-METHOD parse-definition ;
 
-: METHOD:
-    location
-    >r parse-method [ define-method ] 2keep prefix r>
-    remember-definition ; parsing
+: METHOD: (METHOD:) define ; parsing
 
 ! For compatibility
 : M:
-    scan-word 1array scan-word parse-definition
-    -rot define-method ; parsing
+    scan-word 1array scan-word create-method-in
+    parse-definition
+    define ; parsing
 
 ! Definition protocol. We qualify core generics here
 USE: qualified
 QUALIFIED: syntax
 
-PREDICATE: generic < word
-    "multi-combination" word-prop >boolean ;
-
-PREDICATE: standard-generic < word
-    "multi-combination" word-prop standard-combination? ;
-
-PREDICATE: hook-generic < word
-    "multi-combination" word-prop hook-combination? ;
+syntax:M: generic definer drop \ GENERIC: f ;
 
-syntax:M: standard-generic definer drop \ GENERIC: f ;
-
-syntax:M: standard-generic definition drop f ;
-
-syntax:M: hook-generic definer drop \ HOOK: f ;
-
-syntax:M: hook-generic definition drop f ;
-
-syntax:M: hook-generic synopsis*
-    dup definer.
-    dup seeing-word
-    dup pprint-word
-    dup "multi-combination" word-prop
-    hook-combination-var pprint-word stack-effect. ;
+syntax:M: generic definition drop f ;
 
 PREDICATE: method-spec < array
     unclip generic? >r [ class? ] all? r> and ;
 
 syntax:M: method-spec where
-    dup unclip method [ method-loc ] [ second where ] ?if ;
+    dup unclip method [ ] [ first ] ?if where ;
 
 syntax:M: method-spec set-where
-    unclip method set-method-loc ;
+    unclip method set-where ;
 
 syntax:M: method-spec definer
-    drop \ METHOD: \ ; ;
+    unclip method definer ;
 
 syntax:M: method-spec definition
-    unclip method dup [ method-def ] when ;
+    unclip method definition ;
 
 syntax:M: method-spec synopsis*
-    dup definer.
-    unclip pprint* pprint* ;
+    unclip method synopsis* ;
 
 syntax:M: method-spec forget*
-    unclip forget-method ;
+    unclip method forget* ;
+
+syntax:M: method-body definer
+    drop \ METHOD: \ ; ;
+
+syntax:M: method-body synopsis*
+    dup definer.
+    [ "multi-method-generic" word-prop pprint-word ]
+    [ "multi-method-specializer" word-prop pprint* ] bi ;
diff --git a/extra/multi-methods/tests/canonicalize.factor b/extra/multi-methods/tests/canonicalize.factor
new file mode 100644 (file)
index 0000000..d5baf49
--- /dev/null
@@ -0,0 +1,66 @@
+IN: multi-methods.tests
+USING: multi-methods tools.test math sequences namespaces system
+kernel strings ;
+
+[ { POSTPONE: f integer } ] [ { f integer } canonicalize-specializer-0 ] unit-test
+
+: setup-canon-test
+    0 args set
+    V{ } clone hooks set ;
+
+: canon-test-1
+    { integer { cpu x86 } sequence } canonicalize-specializer-1 ;
+
+[ { { -2 integer } { -1 sequence } { cpu x86 } } ] [
+    [
+        setup-canon-test
+        canon-test-1
+    ] with-scope
+] unit-test
+
+[ { { 0 integer } { 1 sequence } { 2 x86 } } ] [
+    [
+        setup-canon-test
+        canon-test-1
+        canonicalize-specializer-2
+    ] with-scope
+] unit-test
+
+[ { integer sequence x86 } ] [
+    [
+        setup-canon-test
+        canon-test-1
+        canonicalize-specializer-2
+        args get hooks get length + total set
+        canonicalize-specializer-3
+    ] with-scope
+] unit-test
+
+: example-1
+    {
+        { { { cpu x86 } { os linux } } "a" }
+        { { { cpu ppc } } "b" }
+        { { string { os windows } } "c" }
+    } ;
+
+[
+    {
+        { { object x86 linux } "a"  }
+        { { object ppc object } "b" }
+        { { string object windows } "c" }
+    }
+    V{ cpu os }
+] [
+    example-1 canonicalize-specializers
+] unit-test
+
+[
+    {
+        { { object x86 linux } [ drop drop "a" ] }
+        { { object ppc object } [ drop drop "b" ] }
+        { { string object windows } [ drop drop "c" ] }
+    }
+    [ \ cpu get \ os get ]
+] [
+    example-1 prepare-methods
+] unit-test
diff --git a/extra/multi-methods/tests/definitions.factor b/extra/multi-methods/tests/definitions.factor
new file mode 100644 (file)
index 0000000..c112a67
--- /dev/null
@@ -0,0 +1,32 @@
+IN: multi-methods.tests
+USING: multi-methods tools.test math sequences namespaces system
+kernel strings words compiler.units quotations ;
+
+\ GENERIC: must-infer
+\ create-method-in must-infer
+
+DEFER: fake
+\ fake H{ } clone "multi-methods" set-word-prop
+
+[ "fake-{ }" ] [ { } \ fake method-word-name ] unit-test
+
+[ H{ { "multi-method-generic" fake } { "multi-method-specializer" { } } } ]
+[ { } \ fake method-word-props ] unit-test
+
+[ t ] [ { } \ fake <method> method-body? ] unit-test
+
+[
+    [ { } [ ] ] [ \ fake methods prepare-methods >r sort-methods r> ] unit-test
+
+    [ t ] [ { } \ fake multi-dispatch-quot callable? ] unit-test
+
+    [ t ] [ \ fake make-generic quotation? ] unit-test
+
+    [ ] [ \ fake update-generic ] unit-test
+
+    DEFER: testing
+
+    [ ] [ \ testing define-generic ] unit-test
+
+    [ t ] [ \ testing generic? ] unit-test
+] with-compilation-unit
diff --git a/extra/multi-methods/tests/legacy.factor b/extra/multi-methods/tests/legacy.factor
new file mode 100644 (file)
index 0000000..f4bd0a0
--- /dev/null
@@ -0,0 +1,10 @@
+IN: multi-methods.tests
+USING: math strings sequences tools.test ;
+
+GENERIC: legacy-test
+
+M: integer legacy-test sq ;
+M: string legacy-test " hey" append ;
+
+[ 25 ] [ 5 legacy-test ] unit-test
+[ "hello hey" ] [ "hello" legacy-test ] unit-test
diff --git a/extra/multi-methods/tests/syntax.factor b/extra/multi-methods/tests/syntax.factor
new file mode 100644 (file)
index 0000000..597a1ce
--- /dev/null
@@ -0,0 +1,64 @@
+IN: multi-methods.tests
+USING: multi-methods tools.test math sequences namespaces system
+kernel strings definitions prettyprint debugger arrays
+hashtables continuations classes assocs accessors ;
+
+GENERIC: first-test
+
+[ t ] [ \ first-test generic? ] unit-test
+
+MIXIN: thing
+
+SINGLETON: paper    INSTANCE: paper thing
+SINGLETON: scissors INSTANCE: scissors thing
+SINGLETON: rock     INSTANCE: rock thing
+
+GENERIC: beats?
+
+METHOD: beats? { paper scissors } t ;
+METHOD: beats? { scissors rock } t ;
+METHOD: beats? { rock paper } t ;
+METHOD: beats? { thing thing } f ;
+
+: play ( obj1 obj2 -- ? ) beats? 2nip ;
+
+[ { } 3 play ] must-fail
+[ t ] [ error get no-method? ] unit-test
+[ ] [ error get error. ] unit-test
+[ { { } 3 } ] [ error get arguments>> ] unit-test
+[ t ] [ paper scissors play ] unit-test
+[ f ] [ scissors paper play ] unit-test
+
+[ t ] [ { beats? paper scissors } method-spec? ] unit-test
+[ ] [ { beats? paper scissors } see ] unit-test
+
+SYMBOL: some-var
+
+GENERIC: hook-test
+
+METHOD: hook-test { array { some-var array } } reverse ;
+METHOD: hook-test { { some-var array } } class ;
+METHOD: hook-test { hashtable { some-var number } } assoc-size ;
+
+{ 1 2 3 } some-var set
+[ { f t t } ] [ { t t f } hook-test ] unit-test
+[ fixnum ] [ 3 hook-test ] unit-test
+5.0 some-var set
+[ 0 ] [ H{ } hook-test ] unit-test
+
+"error" some-var set
+[ H{ } hook-test ] must-fail
+[ t ] [ error get no-method? ] unit-test
+[ { H{ } "error" } ] [ error get arguments>> ] unit-test
+
+MIXIN: busted
+
+TUPLE: busted-1 ;
+TUPLE: busted-2 ; INSTANCE: busted-2 busted
+TUPLE: busted-3 ;
+
+GENERIC: busted-sort
+
+METHOD: busted-sort { busted-1 busted-2 } ;
+METHOD: busted-sort { busted-2 busted-3 } ;
+METHOD: busted-sort { busted busted } ;
diff --git a/extra/multi-methods/tests/topological-sort.factor b/extra/multi-methods/tests/topological-sort.factor
new file mode 100644 (file)
index 0000000..ed8bece
--- /dev/null
@@ -0,0 +1,18 @@
+IN: multi-methods.tests
+USING: kernel multi-methods tools.test math arrays sequences ;
+
+[ { 1 2 3 4 5 6 } ] [
+    { 6 4 5 1 3 2 } [ <=> ] topological-sort
+] unit-test
+
+[ -1 ] [
+    { fixnum array } { number sequence } classes<
+] unit-test
+
+[ 0 ] [
+    { number sequence } { number sequence } classes<
+] unit-test
+
+[ 1 ] [
+    { object object } { number sequence } classes<
+] unit-test
index 53cda66dfc2ed689d2e1fe8133ee80081aae3462..3df3b3ed054ad00ef96ded915ce31b464c22f5b2 100644 (file)
 
-USING: kernel sequences assocs qualified ;
+USING: kernel sequences assocs qualified circular ;
+
+USING: math multi-methods ;
 
 QUALIFIED: sequences
+QUALIFIED: assocs
+QUALIFIED: circular
 
 IN: newfx
 
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 ! Now, we can see a new world coming into view.
 ! A world in which there is the very real prospect of a new world order.
 !
 !    - George Herbert Walker Bush
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+GENERIC: at ( col key -- val )
+GENERIC: of ( key col -- val )
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+GENERIC: grab ( col key -- col val )
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+GENERIC: is ( col key val -- col )
+GENERIC: as ( col val key -- col )
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+GENERIC: is-of ( key val col -- col )
+GENERIC: as-of ( val key col -- col )
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+GENERIC: mutate-at ( col key val -- )
+GENERIC: mutate-as ( col val key -- )
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+GENERIC: at-mutate ( key val col -- )
+GENERIC: as-mutate ( val key col -- )
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+! sequence
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+METHOD: at { sequence number  } swap nth ;
+METHOD: of { number  sequence }      nth ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-: nth-at ( seq i -- val ) swap nth ;
-: nth-of ( i seq -- val )      nth ;
+METHOD: grab { sequence number } dupd swap nth ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-: nth-is ( seq   i val -- seq ) swap pick set-nth ;
-: is-nth ( seq val   i -- seq )      pick set-nth ;
+METHOD: is { sequence number object  } swap pick set-nth ;
+METHOD: as { sequence object  number }      pick set-nth ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-: mutate-nth    ( seq i val -- ) swap rot set-nth ;
-: mutate-at-nth ( seq val i -- )      rot set-nth ;
+METHOD: is-of { number object  sequence } dup >r swapd set-nth r> ;
+METHOD: as-of { object  number sequence } dup >r       set-nth r> ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-: mutate-nth-of    (   i val seq -- ) swapd set-nth ;
-: mutate-at-nth-of ( val   i seq -- )       set-nth ;
+METHOD: mutate-at { sequence number object  } swap rot set-nth ;
+METHOD: mutate-as { sequence object  number }      rot set-nth ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-: at-key ( tbl key -- val ) swap at ;
-: key-of ( key tbl -- val )      at ;
+METHOD: at-mutate { number object  sequence } swapd set-nth ;
+METHOD: as-mutate { object  number sequence }       set-nth ;
 
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+! assoc
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-: key-is ( tbl key val -- tbl ) swap pick set-at ;
-: is-key ( tbl val key -- tbl )      pick set-at ;
+METHOD: at { assoc object } swap assocs:at ;
+METHOD: of { object assoc }      assocs:at ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-: mutate-key    ( tbl key val -- ) swap rot set-at ;
-: mutate-at-key ( tbl val key -- )      rot set-at ;
+METHOD: grab { assoc object } dupd swap assocs:at ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-: mutate-key-of    ( key val tbl -- ) swapd set-at ;
-: mutate-at-key-of ( val key tbl -- )       set-at ;
+METHOD: is { assoc object object } swap pick set-at ;
+METHOD: as { assoc object object }      pick set-at ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-: push    ( seq obj -- seq ) over sequences:push ;
-: push-on ( obj seq -- seq ) tuck sequences:push ;
+METHOD: is-of { object object assoc } dup >r swapd set-at r> ;
+METHOD: as-of { object object assoc } dup >r       set-at r> ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+METHOD: mutate-at { assoc object object } swap rot set-at ;
+METHOD: mutate-as { assoc object object }      rot set-at ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+METHOD: at-mutate { object object assoc } swapd set-at ;
+METHOD: as-mutate { object object assoc }       set-at ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: push      ( seq obj -- seq ) over sequences:push ;
+: push-on   ( obj seq -- seq ) tuck sequences:push ;
+: pushed    ( seq obj --     ) swap sequences:push ;
+: pushed-on ( obj seq --     )      sequences:push ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
@@ -63,6 +124,33 @@ IN: newfx
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
+: delete      ( seq elt -- seq ) over sequences:delete ;
+: delete-from ( elt seq -- seq ) tuck sequences:delete ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: deleted      ( seq elt -- ) swap sequences:delete ;
+: deleted-from ( elt seq -- )      sequences:delete ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: remove      ( seq obj -- seq ) swap sequences:remove ;
+: remove-from ( obj seq -- seq )      sequences:remove ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: subset-of ( quot seq -- seq ) swap subset ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: map-over ( quot seq -- seq ) swap map ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: push-circular ( seq elt -- seq ) over circular:push-circular ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
 ! A note about the 'mutate' qualifier. Other words also technically mutate
 ! their primary object. However, the 'mutate' qualifier is supposed to
 ! indicate that this is the main objective of the word, as a side effect.
\ No newline at end of file
index ca97eab3bc8b455696e18e681f57f9f758c3663c..a809c611b5c8792ff15d4586cf9bd0d25a047589 100644 (file)
@@ -88,38 +88,38 @@ SYMBOL: SQL-TYPE-UNKNOWN
 \r
 : convert-sql-type ( number -- symbol )\r
   {\r
-    { [ dup 1 = ] [ drop SQL-CHAR ] }\r
-    { [ dup 12 = ] [ drop SQL-VARCHAR ] }\r
-    { [ dup -1 = ] [ drop SQL-LONGVARCHAR ] }\r
-    { [ dup -8 = ] [ drop SQL-WCHAR ] }\r
-    { [ dup -9 = ] [ drop SQL-WCHARVAR ] }\r
-    { [ dup -10 = ] [ drop SQL-WLONGCHARVAR ] }\r
-    { [ dup 3 = ] [ drop SQL-DECIMAL ] }\r
-    { [ dup 5 = ] [ drop SQL-SMALLINT ] }\r
-    { [ dup 2 = ] [ drop SQL-NUMERIC ] }\r
-    { [ dup 4 = ] [ drop SQL-INTEGER ] }\r
-    { [ dup 7 = ] [ drop SQL-REAL ] }\r
-    { [ dup 6 = ] [ drop SQL-FLOAT ] }\r
-    { [ dup 8 = ] [ drop SQL-DOUBLE ] }\r
-    { [ dup -7 = ] [ drop SQL-BIT ] }\r
-    { [ dup -6 = ] [ drop SQL-TINYINT ] }\r
-    { [ dup -5 = ] [ drop SQL-BIGINT ] }\r
-    { [ dup -2 = ] [ drop SQL-BINARY ] }\r
-    { [ dup -3 = ] [ drop SQL-VARBINARY ] }   \r
-    { [ dup -4 = ] [ drop SQL-LONGVARBINARY ] }\r
-    { [ dup 91 = ] [ drop SQL-TYPE-DATE ] }\r
-    { [ dup 92 = ] [ drop SQL-TYPE-TIME ] }\r
-    { [ dup 93 = ] [ drop SQL-TYPE-TIMESTAMP ] }\r
-    { [ t ] [ drop SQL-TYPE-UNKNOWN ] }\r
-  } cond ;\r
+    { 1 [ SQL-CHAR ] }\r
+    { 12  [ SQL-VARCHAR ] }\r
+    { -1  [ SQL-LONGVARCHAR ] }\r
+    { -8  [ SQL-WCHAR ] }\r
+    { -9  [ SQL-WCHARVAR ] }\r
+    { -10 [ SQL-WLONGCHARVAR ] }\r
+    { 3 [ SQL-DECIMAL ] }\r
+    { 5 [ SQL-SMALLINT ] }\r
+    { 2 [ SQL-NUMERIC ] }\r
+    { 4 [ SQL-INTEGER ] }\r
+    { 7 [ SQL-REAL ] }\r
+    { 6 [ SQL-FLOAT ] }\r
+    { 8 [ SQL-DOUBLE ] }\r
+    { -7 [ SQL-BIT ] }\r
+    { -6 [ SQL-TINYINT ] }\r
+    { -5 [ SQL-BIGINT ] }\r
+    { -2 [ SQL-BINARY ] }\r
+    { -3 [ SQL-VARBINARY ] }   \r
+    { -4 [ SQL-LONGVARBINARY ] }\r
+    { 91 [ SQL-TYPE-DATE ] }\r
+    { 92 [ SQL-TYPE-TIME ] }\r
+    { 93 [ SQL-TYPE-TIMESTAMP ] }\r
+    [ drop SQL-TYPE-UNKNOWN ]\r
+  } case ;\r
 \r
 : succeeded? ( n -- bool )\r
   #! Did the call succeed (SQL-SUCCESS or SQL-SUCCESS-WITH-INFO)\r
   {\r
-    { [ dup SQL-SUCCESS = ] [ drop t ] }\r
-    { [ dup SQL-SUCCESS-WITH-INFO = ] [ drop t ] }\r
-    { [ t ] [ drop f ] }\r
-  } cond ;  \r
+    { \ SQL-SUCCESS [ t ] }\r
+    { \ SQL-SUCCESS-WITH-INFO [ t ] }\r
+    [ drop f ]\r
+  } case ;  \r
 \r
 FUNCTION: SQLRETURN SQLAllocHandle ( SQLSMALLINT handleType, SQLHANDLE inputHandle, SQLHANDLE* outputHandlePtr ) ;\r
 FUNCTION: SQLRETURN SQLSetEnvAttr ( SQLHENV environmentHandle, SQLINTEGER attribute, SQLPOINTER valuePtr, SQLINTEGER stringLength ) ;\r
@@ -213,21 +213,21 @@ C: <column> column
 \r
 : dereference-type-pointer ( byte-array column -- object )\r
   column-type {\r
-    { [ dup SQL-CHAR = ] [ drop alien>char-string ] }\r
-    { [ dup SQL-VARCHAR = ] [ drop alien>char-string ] }\r
-    { [ dup SQL-LONGVARCHAR = ] [ drop alien>char-string ] }\r
-    { [ dup SQL-WCHAR = ] [ drop alien>char-string ] }\r
-    { [ dup SQL-WCHARVAR = ] [ drop alien>char-string ] }\r
-    { [ dup SQL-WLONGCHARVAR = ] [ drop alien>char-string ] }\r
-    { [ dup SQL-SMALLINT = ] [ drop *short ] }\r
-    { [ dup SQL-INTEGER = ] [ drop *long ] }\r
-    { [ dup SQL-REAL = ] [ drop *float ] }\r
-    { [ dup SQL-FLOAT = ] [ drop *double ] }\r
-    { [ dup SQL-DOUBLE = ] [ drop *double ] }\r
-    { [ dup SQL-TINYINT = ] [ drop *char  ] }\r
-    { [ dup SQL-BIGINT = ] [ drop *longlong ] }\r
-    { [ t ] [ nip [ "Unknown SQL Type: " % word-name % ] "" make ] }    \r
-  } cond ;\r
+    { SQL-CHAR [ alien>char-string ] }\r
+    { SQL-VARCHAR [ alien>char-string ] }\r
+    { SQL-LONGVARCHAR [ alien>char-string ] }\r
+    { SQL-WCHAR [ alien>char-string ] }\r
+    { SQL-WCHARVAR [ alien>char-string ] }\r
+    { SQL-WLONGCHARVAR [ alien>char-string ] }\r
+    { SQL-SMALLINT [ *short ] }\r
+    { SQL-INTEGER [ *long ] }\r
+    { SQL-REAL [ *float ] }\r
+    { SQL-FLOAT [ *double ] }\r
+    { SQL-DOUBLE [ *double ] }\r
+    { SQL-TINYINT [ *char  ] }\r
+    { SQL-BIGINT [ *longlong ] }\r
+    [ nip [ "Unknown SQL Type: " % word-name % ] "" make ]    \r
+  } case ;\r
 \r
 TUPLE: field value column ;\r
 \r
@@ -267,4 +267,4 @@ C: <field> field
     dup odbc-execute\r
     dup odbc-get-all-rows\r
     swap odbc-free-statement\r
-  ] keep odbc-disconnect ;
\ No newline at end of file
+  ] keep odbc-disconnect ;\r
index 2a685eccd1cd3a836f6094d6b76fab5a13b5b84b..d4ad11311fa2264f08bcfaee8c723da9234d884f 100755 (executable)
@@ -179,7 +179,7 @@ HINTS: yuv>rgb byte-array byte-array ;
     num-audio-buffers-processed {\r
         { [ over player-buffers length 1 = over zero? and ] [ drop append-new-audio-buffer t ] }\r
         { [ over player-buffers length 2 = over zero? and ] [ yield drop f ] }\r
-        { [ t ] [ fill-processed-audio-buffer t ] }\r
+        [ fill-processed-audio-buffer t ]\r
     } cond ;\r
 \r
 : start-audio ( player -- player bool )\r
@@ -284,7 +284,7 @@ HINTS: yuv>rgb byte-array byte-array ;
         decode-packet {\r
             { [ is-vorbis-packet? ] [ handle-initial-vorbis-header ] }\r
             { [ is-theora-packet? ] [ handle-initial-theora-header ] }\r
-            { [ t ]                 [ handle-initial-unknown-header ] }\r
+            [ handle-initial-unknown-header ]\r
         } cond t\r
     ] [\r
         f\r
index b0a683dac64abba6597c6fce51273c2b70d23456..739ad203a19825f39c951d14c4a447e67f7e0300 100644 (file)
@@ -1,15 +1,15 @@
 USING: alien alien.syntax combinators kernel parser sequences
-system words namespaces hashtables init math arrays assocs 
-sequences.lib continuations ;
+system words namespaces hashtables init math arrays assocs
+continuations ;
+IN: opengl.gl.extensions
 
 ERROR: unknown-gl-platform ;
 << {
     { [ os windows? ] [ "opengl.gl.windows" ] }
     { [ os macosx? ]  [ "opengl.gl.macosx" ] }
     { [ os unix? ] [ "opengl.gl.unix" ] }
-    { [ t ] [ unknown-gl-platform ] }
+    [ unknown-gl-platform ]
 } cond use+ >>
-IN: opengl.gl.extensions
 
 SYMBOL: +gl-function-number-counter+
 SYMBOL: +gl-function-pointers+
@@ -30,7 +30,7 @@ reset-gl-function-number-counter
 : gl-function-pointer ( names n -- funptr )
     gl-function-context 2array dup +gl-function-pointers+ get-global at
     [ 2nip ] [
-        >r [ gl-function-address ] attempt-each 
+        >r [ gl-function-address ] map [ ] find nip
         dup [ "OpenGL function not available" throw ] unless
         dup r>
         +gl-function-pointers+ get-global set-at
index 5b1ee0d565ed43c9ce9e39de50eee1ddbe959ce6..2788ebdfc2d72fe5c8e22e6ef723ca50ec6f6336 100644 (file)
@@ -1,5 +1,5 @@
 USING: help.markup help.syntax io kernel math quotations
-opengl.gl multiline assocs vocabs.loader sequences ;
+opengl.gl assocs vocabs.loader sequences ;
 IN: opengl
 
 HELP: gl-color
index 1f5453798d283441c5741a65817c5622857abc85..a726095eb109bd225bd20c4fb4da298f1116d201 100755 (executable)
@@ -149,7 +149,7 @@ SYMBOL: node-count
                     { [ dup "intrinsics" word-prop over "if-intrinsics" word-prop or ] [ intrinsics-called ] }
                     { [ dup generic? ] [ generics-called ] }
                     { [ dup method-body? ] [ methods-called ] }
-                    { [ t ] [ words-called ] }
+                    [ words-called ]
                 } cond 1 -rot get at+
             ] [
                 drop
index a30ce648542d6bc95c7b21518bffcaf02f9c3c72..441abd928eb5bc54c36e3c6ff158dbaecc2bf47a 100644 (file)
@@ -35,20 +35,20 @@ C: <connection> connection
 
 : check-result ( result -- )
     {
-        { [ dup OCI_SUCCESS = ] [ drop ] }
-        { [ dup OCI_ERROR = ] [ err get get-oci-error ] }
-        { [ dup OCI_INVALID_HANDLE = ] [ "invalid handle" throw ] }
-        { [ t ] [ "operation failed" throw ] }
-    } cond ;
+        { \ OCI_SUCCESS [ ] }
+        { \ OCI_ERROR [ err get get-oci-error ] }
+        { \ OCI_INVALID_HANDLE [ "invalid handle" throw ] }
+        [ "operation failed" throw ]
+    } case ;
 
 : check-status ( status -- bool )
     {
-        { [ dup OCI_SUCCESS = ] [ drop t ] }
-        { [ dup OCI_ERROR = ] [ err get get-oci-error ] }
-        { [ dup OCI_INVALID_HANDLE = ] [ "invalid handle" throw ] }
-        { [ dup OCI_NO_DATA = ] [ drop f ] }
-        { [ t ] [ "operation failed" throw ] }
-    } cond ;
+        { \ OCI_SUCCESS [ t ] }
+        { \ OCI_ERROR [ err get get-oci-error ] }
+        { \ OCI_INVALID_HANDLE [ "invalid handle" throw ] }
+        { \ OCI_NO_DATA [ f ] }
+        [ "operation failed" throw ]
+    } case ;
 
 ! =========================================================
 ! Initialization and handle-allocation routines
@@ -153,19 +153,19 @@ C: <connection> connection
     >r stm get err get r> dup length swap malloc-char-string swap
     OCI_NTV_SYNTAX OCI_DEFAULT OCIStmtPrepare check-result ;
 
-: calculate-size ( type -- size object )
+: calculate-size ( type -- size )
     {
-        { [ dup SQLT_INT = ] [ "int" heap-size ] }
-        { [ dup SQLT_FLT = ] [ "float" heap-size ] }
-        { [ dup SQLT_CHR = ] [ "char" heap-size ] }
-        { [ dup SQLT_NUM = ] [ "int" heap-size 10 * ] }
-        { [ dup SQLT_STR = ] [ 64 ] }
-        { [ dup SQLT_ODT = ] [ 256 ] }
-    } cond ;
+        { \ SQLT_INT [ "int" heap-size ] }
+        { \ SQLT_FLT [ "float" heap-size ] }
+        { \ SQLT_CHR [ "char" heap-size ] }
+        { \ SQLT_NUM [ "int" heap-size 10 * ] }
+        { \ SQLT_STR [ 64 ] }
+        { \ SQLT_ODT [ 256 ] }
+    } case ;
 
 : define-by-position ( position type -- )
     >r >r stm get f <void*> err get
-    r> r> calculate-size swap >r [ "char" malloc-array dup buf set ] keep 1+
+    r> r> dup calculate-size >r [ "char" malloc-array dup buf set ] keep 1+
     r> f f f OCI_DEFAULT OCIDefineByPos check-result ;
 
 : execute-statement ( -- bool )
index f5ba0fd11defd38f7afed143cbb94727756b0383..65912244dd190a45fccbd387b914142e28a33faf 100755 (executable)
@@ -1,8 +1,7 @@
 USING: alien alien.c-types arrays assocs byte-arrays inference
-inference.transforms io io.binary io.streams.string kernel
-math math.parser namespaces parser prettyprint
-quotations sequences strings vectors
-words macros math.functions ;
+inference.transforms io io.binary io.streams.string kernel math
+math.parser namespaces parser prettyprint quotations sequences
+strings vectors words macros math.functions math.bitfields.lib ;
 IN: pack
 
 SYMBOL: big-endian
index e5787e6cf88af1d0f09abd975cb0f0c2d3cf66ab..8bf0475da54d4b3098040e0eed905fa4d6f6b388 100644 (file)
@@ -318,11 +318,11 @@ M: object build-locals ( code ast -- )
    \r
 M: ebnf-action (transform) ( ast -- parser )\r
   [ parser>> (transform) ] [ code>> ] [ parser>> ] tri build-locals \r
-  string-lines [ parse-lines ] with-compilation-unit action ;\r
+  string-lines parse-lines action ;\r
 \r
 M: ebnf-semantic (transform) ( ast -- parser )\r
   [ parser>> (transform) ] [ code>> ] [ parser>> ] tri build-locals \r
-  string-lines [ parse-lines ] with-compilation-unit semantic ;\r
+  string-lines parse-lines semantic ;\r
 \r
 M: ebnf-var (transform) ( ast -- parser )\r
   parser>> (transform) ;\r
@@ -361,7 +361,11 @@ M: ebnf-non-terminal (transform) ( ast -- parser )
   [ compiled-parse ] curry [ with-scope ] curry ;\r
 \r
 : replace-escapes ( string -- string )\r
-  "\\t" token [ drop "\t" ] action  "\\n" token [ drop "\n" ] action 2choice replace ;\r
+  [\r
+    "\\t" token [ drop "\t" ] action ,\r
+    "\\n" token [ drop "\n" ] action ,\r
+    "\\r" token [ drop "\r" ] action ,\r
+  ] choice* replace ;\r
 \r
 : [EBNF "EBNF]" parse-multiline-string replace-escapes ebnf>quot nip parsed ; parsing\r
 \r
index d49f1158dd60bb764676dad88e860f2d74f63303..d71fdaea3b06f7b7a0cbc3faf89839f0f580d84f 100755 (executable)
@@ -173,7 +173,7 @@ HELP: range-pattern
 "of characters separated with a dash (-) represents the "
 "range of characters from the first to the second, inclusive."
 { $examples
-    { $example "USING: peg peg.parsers prettyprint ;" "\"a\" \"_a-zA-Z\" range-pattern parse parse-result-ast 1string ." "\"a\"" } 
-    { $example "USING: peg peg.parsers prettyprint ;" "\"0\" \"^0-9\" range-pattern parse ." "f" } 
+    { $example "USING: peg peg.parsers prettyprint strings ;" "\"a\" \"_a-zA-Z\" range-pattern parse parse-result-ast 1string ." "\"a\"" } 
+    { $example "USING: peg peg.parsers prettyprint ;\n\"0\" \"^0-9\" range-pattern parse ." "f" } 
 }
 }  ;
index 49035ea43c48f4147eb1cfde64c7add34845d699..3bbb61b8466e63bb9b41488ecb847fc5b9b99c12 100755 (executable)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2007, 2008 Chris Double, Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel sequences strings namespaces math assocs shuffle 
-     vectors arrays combinators.lib math.parser match
+     vectors arrays combinators.lib math.parser 
      unicode.categories sequences.deep peg peg.private 
      peg.search math.ranges words memoize ;
 IN: peg.parsers
index 5f200be78ec7844e345eb9245d56c1e473b3b6c2..10e05a2512aa629916b05f19deba4259fe1f1895 100644 (file)
@@ -104,8 +104,8 @@ HELP: semantic
     "Returns a parser that succeeds if the 'p1' parser succeeds and the quotation called with "\r
     "the AST produced by 'p1' on the stack returns true." }\r
 { $examples \r
-  { $example "\"A\" [ drop t ] satisfy [ 66 > ] semantic parse" "f" } \r
-  { $example "\"C\" [ drop t ] satisfy [ 66 > ] semantic parse parse-result-ast " "67" } \r
+  { $example "USING: kernel math peg prettyprint ;" "\"A\" [ drop t ] satisfy [ 66 > ] semantic parse ." "f" } \r
+  { $example "USING: kernel math peg prettyprint ;" "\"C\" [ drop t ] satisfy [ 66 > ] semantic parse parse-result-ast ." "67" } \r
 } ;\r
 \r
 HELP: ensure\r
index 217805ce4763dd83e5fb807daa11477f110ce5a2..7390c15684e58703e2d9ebbe1369f918a928b7ef 100755 (executable)
@@ -1,9 +1,9 @@
 ! Copyright (C) 2007, 2008 Chris Double.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel sequences strings namespaces math assocs shuffle 
-       vectors arrays combinators.lib math.parser match
-       unicode.categories sequences.lib compiler.units parser
-       words quotations effects memoize accessors locals effects ;
+USING: kernel sequences strings fry namespaces math assocs shuffle 
+       vectors arrays math.parser 
+       unicode.categories compiler.units parser
+       words quotations effects memoize accessors locals effects splitting ;
 IN: peg
 
 USE: prettyprint
@@ -30,6 +30,9 @@ SYMBOL: fail
 SYMBOL: lrstack
 SYMBOL: heads
 
+: failed? ( obj -- ? )
+  fail = ;
+
 : delegates ( -- cache )
   \ delegates get-global [ H{ } clone dup \ delegates set-global ] unless* ;
 
@@ -66,21 +69,18 @@ C: <head> peg-head
   #! that maps the position to the parser result.
   id>> packrat get [ drop H{ } clone ] cache ;
 
+: process-rule-result ( p result -- result )
+  [
+    nip [ ast>> ] [ remaining>> ] bi input-from pos set    
+  ] [ 
+    pos set fail
+  ] if* ; 
+
 : eval-rule ( rule -- ast )
   #! Evaluate a rule, return an ast resulting from it.
   #! Return fail if the rule failed. The rule has
   #! stack effect ( input -- parse-result )
-  pos get swap 
-  execute 
-!  drop f f <parse-result>
-  [
-    nip
-    [ ast>> ] [ remaining>> ] bi
-    input-from pos set    
-  ] [ 
-    pos set   
-    fail
-  ] if* ; inline
+  pos get swap execute process-rule-result ; inline
 
 : memo ( pos rule -- memo-entry )
   #! Return the result from the memo cache. 
@@ -90,21 +90,29 @@ C: <head> peg-head
   #! Store an entry in the cache
   rule-parser input-cache set-at ;
 
-:: (grow-lr) ( r p m h -- )
-  p pos set
-  h involved-set>> clone h (>>eval-set)
+: update-m ( ast m -- )
+  swap >>ans pos get >>pos drop ;
+
+: stop-growth? ( ast m -- ? )
+  [ failed? pos get ] dip 
+  pos>> <= or ;
+
+: setup-growth ( h p -- )
+  pos set dup involved-set>> clone >>eval-set drop ;
+
+:: (grow-lr) ( h p r m -- )
+  h p setup-growth
   r eval-rule
-  dup fail = pos get m pos>> <= or [
+  dup m stop-growth? [
     drop
   ] [
-    m (>>ans)
-    pos get m (>>pos)
-    r p m h (grow-lr)
+    m update-m
+     h p r m (grow-lr)
   ] if ; inline
  
-:: grow-lr ( r p m h -- ast )
+:: grow-lr ( h p r m -- ast )
   h p heads get set-at
-  r p m h (grow-lr) 
+  h p r m (grow-lr) 
   p heads get delete-at
   m pos>> pos set m ans>>
   ; inline
@@ -128,10 +136,10 @@ C: <head> peg-head
         |
     h rule>> r eq? [
       m ans>> seed>> m (>>ans)
-      m ans>> fail = [
+      m ans>> failed? [
         fail
       ] [
-        r p m h grow-lr
+        h p r m grow-lr
       ] if
     ] [
       m ans>> seed>>
@@ -150,8 +158,7 @@ C: <head> peg-head
         r h eval-set>> member? [
           h [ r swap remove ] change-eval-set drop
           r eval-rule
-          m (>>ans)
-          pos get m (>>pos)
+          m update-m
           m
         ] [ 
           m
@@ -179,25 +186,20 @@ C: <head> peg-head
     ] if
   ] ; inline
 
-:: apply-memo-rule ( r m -- ast )
-  m pos>> pos set 
-  m ans>> left-recursion? [ 
-    r m ans>> setup-lr
-    m ans>> seed>>
+: apply-memo-rule ( r m -- ast )
+  [ ans>> ] [ pos>> ] bi pos set
+  dup left-recursion? [ 
+    [ setup-lr ] keep seed>>
   ] [
-    m ans>>
-  ] if ;
+    nip
+  ] if ; 
 
-:: apply-rule ( r p -- ast )
-  [let* |
-          m [ r p recall ]
-        | 
-    m [
-      r m apply-memo-rule
-    ] [
-      r p apply-non-memo-rule
-    ] if 
-  ] ; inline
+: apply-rule ( r p -- ast )
+   2dup recall [
+     nip apply-memo-rule
+   ] [
+     apply-non-memo-rule
+   ] if* ; inline
 
 : with-packrat ( input quot -- result )
   #! Run the quotation with a packrat cache active.
@@ -212,20 +214,18 @@ C: <head> peg-head
 
 GENERIC: (compile) ( parser -- quot )
 
+: execute-parser ( word -- result )
+  pos get apply-rule dup failed? [ 
+    drop f 
+  ] [
+    input-slice swap <parse-result>
+  ] if ; inline
 
-:: parser-body ( parser -- quot )
+: parser-body ( parser -- quot )
   #! Return the body of the word that is the compiled version
   #! of the parser.
-  [let* | rule [ gensym dup parser (compile) 0 1 <effect> define-declared dup parser "peg" set-word-prop ] 
-        |
-    [
-      rule pos get apply-rule dup fail = [ 
-        drop f 
-      ] [
-        input-slice swap <parse-result>
-      ] if
-    ] 
-  ] ;
+  gensym 2dup swap (compile) 0 1 <effect> define-declared swap dupd "peg" set-word-prop
+  [ execute-parser ] curry ;
 
 : compiled-parser ( parser -- word )
   #! Look to see if the given parser has been compiled.
@@ -246,7 +246,7 @@ GENERIC: (compile) ( parser -- quot )
 : compiled-parse ( state word -- result )
   swap [ execute ] with-packrat ; inline 
 
-: parse ( state parser -- result )
+: parse ( input parser -- result )
   dup word? [ compile ] unless compiled-parse ;
 
 <PRIVATE
@@ -270,210 +270,166 @@ SYMBOL: id
 
 TUPLE: token-parser symbol ;
 
-MATCH-VARS: ?token ;
-
 : parse-token ( input string -- result )
   #! Parse the string, returning a parse result
-  2dup head? [
-    dup >r length tail-slice r> <parse-result>
+  dup >r ?head-slice [
+    r> <parse-result> 
   ] [
-    2drop f
+    r> 2drop f
   ] if ;
 
 M: token-parser (compile) ( parser -- quot )
-  [ \ input-slice , symbol>> , \ parse-token , ] [ ] make ;
+  symbol>> '[ input-slice , parse-token ] ;
    
 TUPLE: satisfy-parser quot ;
 
-MATCH-VARS: ?quot ;
+: parse-satisfy ( input quot -- result )
+  swap dup empty? [
+    2drop f 
+  ] [
+    unclip-slice rot dupd call [
+      <parse-result>
+    ] [  
+      2drop f
+    ] if
+  ] if ; inline
 
-: satisfy-pattern ( -- quot )
-  [
-    input-slice dup empty? [
-      drop f 
-    ] [
-      unclip-slice dup ?quot call [  
-        <parse-result>
-      ] [
-        2drop f
-      ] if
-    ] if 
-  ] ;
 
 M: satisfy-parser (compile) ( parser -- quot )
-  quot>> \ ?quot satisfy-pattern match-replace ;
+  quot>> '[ input-slice , parse-satisfy ] ;
 
 TUPLE: range-parser min max ;
 
-MATCH-VARS: ?min ?max ;
-
-: range-pattern ( -- quot )
-  [
-    input-slice dup empty? [
+: parse-range ( input min max -- result )
+  pick empty? [ 
+    3drop f 
+  ] [
+    pick first -rot between? [
+      unclip-slice <parse-result>
+    ] [ 
       drop f
-    ] [
-      0 over nth dup 
-      ?min ?max between? [
-         [ 1 tail-slice ] dip <parse-result>
-      ] [
-        2drop f
-      ] if
-    ] if 
-  ] ;
+    ] if
+  ] if ;
 
 M: range-parser (compile) ( parser -- quot )
-  T{ range-parser _ ?min ?max } range-pattern match-replace ;
+  [ min>> ] [ max>> ] bi '[ input-slice , , parse-range ] ;
 
 TUPLE: seq-parser parsers ;
 
-: seq-pattern ( -- quot )
+: ignore? ( ast -- bool )
+  ignore = ;
+
+: calc-seq-result ( prev-result current-result -- next-result )
   [
-    dup [
-      ?quot [
-        [ remaining>> swap (>>remaining) ] 2keep
-        ast>> dup ignore = [ 
-          drop  
-        ] [ 
-          swap [ ast>> push ] keep 
-        ] if
-      ] [
-        drop f 
-      ] if*
+    [ remaining>> swap (>>remaining) ] 2keep
+    ast>> dup ignore? [  
+      drop
     ] [
-      drop f
-    ] if  
-  ] ;
+      swap [ ast>> push ] keep
+    ] if
+  ] [
+    drop f
+  ] if* ;
+
+: parse-seq-element ( result quot -- result )
+  over [
+    call calc-seq-result
+  ] [
+    2drop f
+  ] if ; inline
 
 M: seq-parser (compile) ( parser -- quot )
   [
     [ input-slice V{ } clone <parse-result> ] %
-    parsers>> [ compiled-parser \ ?quot seq-pattern match-replace % ] each 
+    parsers>> [ compiled-parser 1quotation , \ parse-seq-element , ] each 
   ] [ ] make ;
 
 TUPLE: choice-parser parsers ;
 
-: choice-pattern ( -- quot )
-  [
-    [ ?quot ] unless* 
-  ] ;
-
 M: choice-parser (compile) ( parser -- quot )
   [ 
     f ,
-    parsers>> [ compiled-parser \ ?quot choice-pattern match-replace % ] each
+    parsers>> [ compiled-parser 1quotation , \ unless* , ] each
   ] [ ] make ;
 
 TUPLE: repeat0-parser p1 ;
 
-: (repeat0) ( quot result -- result )
+: (repeat) ( quot result -- result )
   over call [
     [ remaining>> swap (>>remaining) ] 2keep 
     ast>> swap [ ast>> push ] keep
-    (repeat0
- ] [
+    (repeat) 
 ] [
     nip
   ] if* ; inline
 
-: repeat0-pattern ( -- quot )
-  [
-    [ ?quot ] swap (repeat0) 
-  ] ;
-
 M: repeat0-parser (compile) ( parser -- quot )
-  [
-    [ input-slice V{ } clone <parse-result> ] %
-    p1>> compiled-parser \ ?quot repeat0-pattern match-replace %        
-  ] [ ] make ;
+  p1>> compiled-parser 1quotation '[ 
+    input-slice V{ } clone <parse-result> , swap (repeat) 
+  ] ; 
 
 TUPLE: repeat1-parser p1 ;
 
-: repeat1-pattern ( -- quot )
+: repeat1-empty-check ( result -- result )
   [
-    [ ?quot ] swap (repeat0) [
-      dup ast>> empty? [
-        drop f
-      ] when  
-    ] [
-      f 
-    ] if*
-  ] ;
+    dup ast>> empty? [ drop f ] when
+  ] [
+    f
+  ] if* ;
 
 M: repeat1-parser (compile) ( parser -- quot )
-  [
-    [ input-slice V{ } clone <parse-result> ] %
-    p1>> compiled-parser \ ?quot repeat1-pattern match-replace % 
-  ] [ ] make ;
+  p1>> compiled-parser 1quotation '[ 
+    input-slice V{ } clone <parse-result> , swap (repeat) repeat1-empty-check  
+  ] ; 
 
 TUPLE: optional-parser p1 ;
 
-: optional-pattern ( -- quot )
-  [
-    ?quot [ input-slice f <parse-result> ] unless* 
-  ] ;
+: check-optional ( result -- result )
+  [ input-slice f <parse-result> ] unless* ;
 
 M: optional-parser (compile) ( parser -- quot )
-  p1>> compiled-parser \ ?quot optional-pattern match-replace ;
+  p1>> compiled-parser 1quotation '[ @ check-optional ] ;
 
 TUPLE: semantic-parser p1 quot ;
 
-MATCH-VARS: ?parser ;
-
-: semantic-pattern ( -- quot )
-  [
-    ?parser [
-      dup parse-result-ast ?quot call [ drop f ] unless
-    ] [
-      f
-    ] if*
-  ] ;
+: check-semantic ( result quot -- result )
+  over [
+    over ast>> swap call [ drop f ] unless
+  ] [
+    drop
+  ] if ; inline
 
 M: semantic-parser (compile) ( parser -- quot )
-  [ p1>> compiled-parser ] [ quot>> ] bi  
-  2array { ?parser ?quot } semantic-pattern match-replace ;
+  [ p1>> compiled-parser 1quotation ] [ quot>> ] bi  
+  '[ @ , check-semantic ] ;
 
 TUPLE: ensure-parser p1 ;
 
-: ensure-pattern ( -- quot )
-  [
-    input-slice ?quot [
-      ignore <parse-result>
-    ] [
-      drop f
-    ] if
-  ] ;
+: check-ensure ( old-input result -- result )
+  [ ignore <parse-result> ] [ drop f ] if ;
 
 M: ensure-parser (compile) ( parser -- quot )
-  p1>> compiled-parser \ ?quot ensure-pattern match-replace ;
+  p1>> compiled-parser 1quotation '[ input-slice @ check-ensure ] ;
 
 TUPLE: ensure-not-parser p1 ;
 
-: ensure-not-pattern ( -- quot )
-  [
-    input-slice ?quot [
-      drop f
-    ] [
-      ignore <parse-result>
-    ] if
-  ] ;
+: check-ensure-not ( old-input result -- result )
+  [ drop f ] [ ignore <parse-result> ] if ;
 
 M: ensure-not-parser (compile) ( parser -- quot )
-  p1>> compiled-parser \ ?quot ensure-not-pattern match-replace ;
+  p1>> compiled-parser 1quotation '[ input-slice @ check-ensure-not ] ;
 
 TUPLE: action-parser p1 quot ;
 
-MATCH-VARS: ?action ;
-
-: action-pattern ( -- quot )
-  [
-    ?quot dup [ 
-      dup ast>> ?action call
-      >>ast
-    ] when 
-  ] ;
+: check-action ( result quot -- result )
+  over [
+    over ast>> swap call >>ast
+  ] [
+    drop
+  ] if ; inline
 
 M: action-parser (compile) ( parser -- quot )
-  [ p1>> compiled-parser ] [ quot>> ] bi  
-  2array { ?quot ?action } action-pattern match-replace ;
+  [ p1>> compiled-parser 1quotation ] [ quot>> ] bi '[ @ , check-action ] ;
 
 : left-trim-slice ( string -- string )
   #! Return a new string without any leading whitespace
@@ -485,9 +441,9 @@ M: action-parser (compile) ( parser -- quot )
 TUPLE: sp-parser p1 ;
 
 M: sp-parser (compile) ( parser -- quot )
-  [
-    \ input-slice , \ left-trim-slice , \ input-from , \ pos , \ set , p1>> compiled-parser , 
-  ] [ ] make ;
+  p1>> compiled-parser 1quotation '[ 
+    input-slice left-trim-slice input-from pos set @ 
+  ] ;
 
 TUPLE: delay-parser quot ;
 
@@ -495,11 +451,7 @@ M: delay-parser (compile) ( parser -- quot )
   #! For efficiency we memoize the quotation.
   #! This way it is run only once and the 
   #! parser constructed once at run time.
-  [
-    quot>> % \ compile ,
-  ] [ ] make 
-  { } { "word" } <effect> memoize-quot 
-  [ % \ execute , ] [ ] make ;
+  quot>> '[ @ compile ] { } { "word" } <effect> memoize-quot '[ @ execute ] ; 
 
 TUPLE: box-parser quot ;
 
index fec3163e2f484077f60715bb35894191460ad557..81820e0152801d685c89bbe8353f5468049c113e 100644 (file)
@@ -60,7 +60,7 @@ USING: kernel math parser sequences combinators splitting ;
         { [ 1 over consonant-end? not ] [ drop f ] }
         { [ 2 over consonant-end? ] [ drop f ] }
         { [ 3 over consonant-end? not ] [ drop f ] }
-        { [ t ] [ "wxy" last-is? not ] }
+        [ "wxy" last-is? not ]
     } cond ;
 
 : r ( str oldsuffix newsuffix -- str )
@@ -75,7 +75,7 @@ USING: kernel math parser sequences combinators splitting ;
             { [ "ies" ?tail ] [ "i" append ] }
             { [ dup "ss" tail? ] [ ] }
             { [ "s" ?tail ] [ ] }
-            { [ t ] [ ] }
+            [ ]
         } cond
     ] when ;
 
@@ -114,11 +114,11 @@ USING: kernel math parser sequences combinators splitting ;
                 {
                     { [ "ed" ?tail ] [ -ed ] }
                     { [ "ing" ?tail ] [ -ing ] }
-                    { [ t ] [ f ] }
+                    [ f ]
                 } cond
             ] [ -ed/ing ]
         }
-        { [ t ] [ ] }
+        [ ]
     } cond ;
 
 : step1c ( str -- newstr )
@@ -149,7 +149,7 @@ USING: kernel math parser sequences combinators splitting ;
         { [ "iviti"   ?tail ] [ "iviti"   "ive"  r ] }
         { [ "biliti"  ?tail ] [ "biliti"  "ble"  r ] }
         { [ "logi"    ?tail ] [ "logi"    "log"  r ] }
-        { [ t ] [ ] }
+        [ ]
     } cond ;
 
 : step3 ( str -- newstr )
@@ -161,7 +161,7 @@ USING: kernel math parser sequences combinators splitting ;
         { [ "ical"  ?tail ] [ "ical"  "ic" r ] }
         { [ "ful"   ?tail ] [ "ful"   ""   r ] }
         { [ "ness"  ?tail ] [ "ness"  ""   r ] }
-        { [ t ] [ ] }
+        [ ]
     } cond ;
 
 : -ion ( str -- newstr )
@@ -192,7 +192,7 @@ USING: kernel math parser sequences combinators splitting ;
         { [ "ous"   ?tail ] [ ] }
         { [ "ive"   ?tail ] [ ] }
         { [ "ize"   ?tail ] [ ] }
-        { [ t ] [ ] }
+        [ ]
     } cond dup consonant-seq 1 > [ nip ] [ drop ] if ;
 
 : remove-e? ( str -- ? )
@@ -210,7 +210,7 @@ USING: kernel math parser sequences combinators splitting ;
         { [ dup peek CHAR: l = not ] [ ] }
         { [ dup length 1- over double-consonant? not ] [ ] }
         { [ dup consonant-seq 1 > ] [ butlast ] }
-        { [ t ] [ ] }
+        [ ]
     } cond ;
 
 : step5 ( str -- newstr ) remove-e ll->l ;
diff --git a/extra/processing/color/color.factor b/extra/processing/color/color.factor
new file mode 100644 (file)
index 0000000..50d20fc
--- /dev/null
@@ -0,0 +1,22 @@
+
+USING: kernel sequences ;
+
+IN: processing.color
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+TUPLE: rgba red green blue alpha ;
+
+C: <rgba> rgba
+
+: <rgb> ( r g b -- rgba ) 1 <rgba> ;
+
+: <gray> ( gray -- rgba ) dup dup 1 <rgba> ;
+
+: {rgb} ( seq -- rgba ) first3 <rgb> ;
+
+! : hex>rgba ( hex -- rgba )
+
+! : set-gl-color ( color -- )
+!   { [ red>> ] [ green>> ] [ blue>> ] [ alpha>> ] } cleave glColor4d ;
+
diff --git a/extra/processing/gadget/gadget.factor b/extra/processing/gadget/gadget.factor
new file mode 100644 (file)
index 0000000..8b78c43
--- /dev/null
@@ -0,0 +1,80 @@
+
+USING: kernel namespaces combinators
+       ui.gestures qualified accessors ui.gadgets.frame-buffer ;
+
+IN: processing.gadget
+
+QUALIFIED: ui.gadgets
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+TUPLE: processing-gadget button-down button-up key-down key-up ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: set-gadget-delegate ( tuple gadget -- tuple )
+  over ui.gadgets:set-gadget-delegate ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: <processing-gadget> ( -- gadget )
+  processing-gadget construct-empty
+    <frame-buffer> set-gadget-delegate ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+SYMBOL: mouse-pressed-value
+SYMBOL: key-pressed-value
+
+SYMBOL: button-value
+SYMBOL: key-value
+
+: key-pressed?   ( -- ? ) key-pressed-value   get ;
+: mouse-pressed? ( -- ? ) mouse-pressed-value get ;
+
+: key    ( -- key ) key-value    get ;
+: button ( -- val ) button-value get ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+M: processing-gadget handle-gesture* ( gadget gesture delegate -- ? )
+   rot drop swap         ! delegate gesture
+   {
+     {
+       [ dup key-down? ]
+       [
+         key-down-sym key-value set
+         key-pressed-value on
+         key-down>> dup [ call ] [ drop ] if
+         t
+       ]
+     }
+     {
+       [ dup key-up?   ]
+       [
+         key-pressed-value off
+         drop
+         key-up>> dup [ call ] [ drop ] if
+         t
+       ] }
+     {
+       [ dup button-down? ]
+       [
+         button-down-# button-value set
+         mouse-pressed-value on
+         button-down>> dup [ call ] [ drop ] if
+         t
+       ]
+     }
+     {
+       [ dup button-up? ]
+       [
+         mouse-pressed-value off
+         drop
+         button-up>> dup [ call ] [ drop ] if
+         t
+       ]
+     }
+     { [ t ] [ 2drop t ] }
+   }
+   cond ;
\ No newline at end of file
diff --git a/extra/processing/gallery/trails/trails.factor b/extra/processing/gallery/trails/trails.factor
new file mode 100644 (file)
index 0000000..dc191bc
--- /dev/null
@@ -0,0 +1,47 @@
+
+USING: kernel arrays sequences math qualified
+       sequences.lib circular processing ui newfx ;
+
+IN: processing.gallery.trails
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+! Example 33-15 from the Processing book
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: point-list ( n -- seq ) [ drop 0 0 2array ] map <circular> ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: dot ( pos percent -- ) 1 swap - 25 * 5 max circle ;
+
+: step ( seq -- )
+
+  no-stroke
+  { 1 0.4 } fill
+
+  0 background
+
+  mouse push-circular
+    [ dot ]
+  each-percent ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: go* ( -- )
+
+  500 500 size*
+
+  [
+    100 point-list
+      [ step ]
+    curry
+      draw
+  ] setup
+
+  run ;
+
+: go ( -- ) [ go* ] with-ui ;
+
+MAIN: go
\ No newline at end of file
diff --git a/extra/processing/processing.factor b/extra/processing/processing.factor
new file mode 100644 (file)
index 0000000..e089b15
--- /dev/null
@@ -0,0 +1,407 @@
+
+USING: kernel namespaces threads combinators sequences arrays
+       math math.functions math.ranges random
+       opengl.gl opengl.glu vars multi-methods shuffle
+       ui
+       ui.gestures
+       ui.gadgets
+       combinators
+       combinators.lib
+       combinators.cleave
+       rewrite-closures fry accessors newfx
+       processing.color
+       processing.gadget ;
+       
+IN: processing
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: 2random ( a b -- num ) 2dup swap - 100 / <range> random ;
+
+: 1random ( b -- num ) 0 swap 2random ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: chance ( fraction -- ? ) 0 1 2random > ;
+
+: percent-chance ( percent -- ? ) 100 / chance ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+! : at-fraction ( seq fraction -- val ) over length 1- * nth-at ;
+
+: at-fraction ( seq fraction -- val ) over length 1- * at ;
+
+: at-fraction-of ( fraction seq -- val ) swap at-fraction ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+VAR: fill-color
+VAR: stroke-color
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+GENERIC: set-color ( value -- )
+
+METHOD: set-color { number } dup dup glColor3d ;
+
+METHOD: set-color { array }
+   dup length
+   {
+     { 2 [ first2 >r dup dup r> glColor4d ] }
+     { 3 [ first3 glColor3d ] }
+     { 4 [ first4 glColor4d ] }
+   }
+   case ;
+
+METHOD: set-color { rgba }
+  { [ red>> ] [ green>> ] [ blue>> ] [ alpha>> ] } cleave glColor4d ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: fill   ( value -- )  >fill-color ;
+: stroke ( value -- ) >stroke-color ;
+
+: no-fill ( -- )
+  fill-color>
+    {
+      { [ dup number? ] [ 0 2array fill ] }
+      { [ t           ]
+        [
+          [ drop 0 ] [ length 1- ] [ ] tri set-nth
+        ] }
+    }
+  cond ;
+
+: no-stroke ( -- )
+  stroke-color>
+    {
+      { [ dup number? ] [ 0 2array stroke ] }
+      { [ t           ]
+        [
+          [ drop 0 ] [ length 1- ] [ ] tri set-nth
+        ] }
+    }
+  cond ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: stroke-weight ( w -- ) glLineWidth ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: point* ( x y -- )
+  stroke-color> set-color
+  GL_POINTS glBegin
+    glVertex2d
+  glEnd ;
+
+: point ( seq -- ) first2 point* ;
+
+: line ( x1 y1 x2 y2 -- )
+  stroke-color> set-color
+  GL_LINES glBegin
+    glVertex2d
+    glVertex2d
+  glEnd ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: triangle ( x1 y1 x2 y2 x3 y3 -- )
+
+  GL_FRONT_AND_BACK GL_FILL glPolygonMode
+  fill-color> set-color
+
+  6 ndup
+  
+  GL_TRIANGLES glBegin
+    glVertex2d
+    glVertex2d
+    glVertex2d
+  glEnd
+
+  GL_FRONT_AND_BACK GL_LINE glPolygonMode
+  stroke-color> set-color
+
+  GL_TRIANGLES glBegin
+    glVertex2d
+    glVertex2d
+    glVertex2d
+  glEnd ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: quad-vertices ( x1 y1 x2 y2 x3 y3 x4 y4 -- )
+  GL_POLYGON glBegin
+    glVertex2d
+    glVertex2d
+    glVertex2d
+    glVertex2d
+  glEnd ;
+
+: quad ( x1 y1 x2 y2 x3 y3 x4 y4 -- )
+
+  8 ndup
+
+  GL_FRONT_AND_BACK GL_FILL glPolygonMode
+  fill-color> set-color
+
+  quad-vertices
+  
+  GL_FRONT_AND_BACK GL_LINE glPolygonMode
+  stroke-color> set-color
+
+  quad-vertices ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: rect-vertices ( x y width height -- )
+  GL_POLYGON glBegin
+    [ 2drop                      glVertex2d ] 4keep
+    [ drop swap >r + 1- r>       glVertex2d ] 4keep
+    [ >r swap >r + 1- r> r> + 1- glVertex2d ] 4keep
+    [ nip + 1-                   glVertex2d ] 4keep
+    4drop
+  glEnd ;
+
+: rect ( x y width height -- )
+
+  4dup
+
+  GL_FRONT_AND_BACK GL_FILL glPolygonMode
+  fill-color> set-color
+
+  rect-vertices
+
+  GL_FRONT_AND_BACK GL_LINE glPolygonMode
+  stroke-color> set-color
+
+  rect-vertices ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: ellipse-disk ( x y width height -- )
+  glPushMatrix
+    >r >r
+    0 glTranslated
+    r> r> 1 glScaled
+    gluNewQuadric
+      dup 0 0.5 20 1 gluDisk
+    gluDeleteQuadric
+  glPopMatrix ;
+
+: ellipse-center ( x y width height -- )
+
+  4dup
+
+  GL_FRONT_AND_BACK GL_FILL glPolygonMode
+  stroke-color> set-color
+
+  ellipse-disk
+
+  GL_FRONT_AND_BACK GL_FILL glPolygonMode
+  fill-color> set-color
+
+  [ 2 - ] bi@ ! [ stroke-width 1+ - ] bi@
+
+  ellipse-disk ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+SYMBOL: CENTER
+SYMBOL: RADIUS
+SYMBOL: CORNER
+SYMBOL: CORNERS
+
+SYMBOL: ellipse-mode-value
+
+: ellipse-mode ( val -- ) ellipse-mode-value set ;
+
+: ellipse-radius ( x y hori vert -- ) [ 2 * ] bi@ ellipse-center ;
+
+: ellipse-corner ( x y width height -- )
+  [ drop nip     2 / + ] 4keep
+  [ nip rot drop 2 / + ] 4keep
+  [ >r >r 2drop r> r>  ] 4keep
+  4drop
+  ellipse-center ;
+
+: ellipse-corners ( x1 y1 x2 y2 -- )
+  [ drop nip     + 2 /    ] 4keep
+  [ nip rot drop + 2 /    ] 4keep
+  [ drop nip     - abs 1+ ] 4keep
+  [ nip rot drop - abs 1+ ] 4keep
+  4drop
+  ellipse-center ;
+
+: ellipse ( a b c d -- )
+  ellipse-mode-value get
+    {
+      { CENTER  [ ellipse-center ] }
+      { RADIUS  [ ellipse-radius ] }
+      { CORNER  [ ellipse-corner ] }
+      { CORNERS [ ellipse-corners ] }
+    }
+  case ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: circle ( pos size -- ) [ first2 ] [ dup ] bi* ellipse ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+USING: multi-methods ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+GENERIC: background ( value -- )
+
+METHOD: background { number }
+   dup dup 1 glClearColor
+   GL_COLOR_BUFFER_BIT glClear ;
+
+METHOD: background { array }
+   dup length
+   {
+     { 2 [ first2 >r dup dup r> glClearColor GL_COLOR_BUFFER_BIT glClear ] }
+     { 3 [ first3 1             glClearColor GL_COLOR_BUFFER_BIT glClear ] }
+     { 4 [ first4               glClearColor GL_COLOR_BUFFER_BIT glClear ] }
+   }
+   case ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: translate ( x y -- ) 0 glTranslated ;
+
+: rotate ( angle -- ) 0 0 1 glRotated ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: mouse ( -- point ) hand-loc get ;
+
+: mouse-x mouse first  ;
+: mouse-y mouse second ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+VAR: frame-rate-value
+
+: frame-rate ( fps -- ) 1000 swap / >frame-rate-value ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+! VAR: slate
+
+VAR: loop-flag
+
+: defaults ( -- )
+  0.8    background
+  0      >stroke-color
+  1      >fill-color
+  CENTER ellipse-mode
+  60 frame-rate ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+SYMBOL: size-val
+
+: size ( seq -- ) size-val set ;
+
+: size* ( width height -- ) 2array size-val set ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+SYMBOL: setup-action
+SYMBOL: draw-action
+
+! : setup ( quot -- ) closed-quot setup-action set ;
+! : draw  ( quot -- ) closed-quot draw-action  set ;
+
+: setup ( quot -- ) setup-action set ;
+: draw  ( quot -- ) draw-action  set ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+SYMBOL: key-down-action
+SYMBOL: key-up-action
+
+: key-down ( quot -- ) closed-quot key-down-action set ;
+: key-up   ( quot -- ) closed-quot key-up-action   set ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+SYMBOL: button-down-action
+SYMBOL: button-up-action
+
+: button-down ( quot -- ) closed-quot button-down-action set ;
+: button-up   ( quot -- ) closed-quot button-up-action   set ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: start-processing-thread ( -- )
+  loop-flag get not
+    [
+      loop-flag on
+      [
+        [ loop-flag get ]
+        processing-gadget get frame-rate-value> '[ , relayout-1 , sleep ]
+        [ ]
+        while
+      ]
+      in-thread
+    ]
+  when ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: get-size ( -- size ) processing-gadget get rect-dim ;
+
+: width  ( -- width  ) get-size first ;
+: height ( -- height ) get-size second ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+SYMBOL: setup-called
+
+: setup-called? ( -- ? ) setup-called get ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: run ( -- )
+
+  loop-flag off
+
+  500 sleep
+
+  <processing-gadget>
+    size-val get >>dim
+    dup "Processing" open-window
+
+    500 sleep
+
+    defaults
+
+    setup-called off
+
+    [
+      setup-called? not
+        [
+          setup-action get call
+          setup-called on
+        ]
+        [
+          draw-action get call
+        ]
+      if
+    ]
+      closed-quot >>action
+    
+    key-down-action get >>key-down
+    key-up-action   get >>key-up
+
+    button-down-action get >>button-down
+    button-up-action   get >>button-up
+    
+  processing-gadget set
+
+  start-processing-thread ;
\ No newline at end of file
index 61645bf50b4ddf0fa18bf34e5c9462b2519b2246..973e50748c0f79bb7e1b1e3b833443ca83a2f39b 100644 (file)
@@ -30,7 +30,7 @@ MEMO: fn ( n -- x )
     {
         { [ dup 2 < ]  [ drop 1 ] }
         { [ dup odd? ] [ 2/ fn ] }
-        { [ t ]        [ 2/ [ fn ] keep 1- fn + ] }
+        [ 2/ [ fn ] [ 1- fn + ] bi + ]
     } cond ;
 
 : euler169 ( -- result )
index e6b4acc8c080f2a476318542dbb7f1fd153eeffd..853bf9a10f1b7c28841ee68da0ea9579cd52b3cb 100644 (file)
@@ -44,7 +44,7 @@ IN: project-euler.175
     {
         { [ dup integer? ] [ 1- 0 add-bits ] }
         { [ dup 1 < ] [ 1 over - / dupd compute 1 1 add-bits ] }
-        { [ t ] [ [ 1 mod compute ] 2keep >integer 0 add-bits ] }
+        [ [ 1 mod compute ] 2keep >integer 0 add-bits ]
     } cond ;
 
 PRIVATE>
index f7eac4c32db6f603d7c48327b7cbaa4e09a1c08c..5ca2c79afe8fa771b9f3c472a9a0270c4b382e62 100755 (executable)
@@ -52,11 +52,6 @@ IN: random-tester.safe-words
         >r r>
     } ;
 
-: method-words
-    {
-        forget-word
-    } ;
-
 : stateful-words
     {
         counter
@@ -82,7 +77,6 @@ IN: random-tester.safe-words
         bignum-words %
         initialization-words %
         stack-words %
-        method-words %
         stateful-words %
         exit-words %
         foo-words %
diff --git a/extra/random/blum-blum-shub/blum-blum-shub-tests.factor b/extra/random/blum-blum-shub/blum-blum-shub-tests.factor
new file mode 100644 (file)
index 0000000..a92f256
--- /dev/null
@@ -0,0 +1,28 @@
+USING: kernel math tools.test namespaces random
+random.blum-blum-shub ;
+IN: blum-blum-shub.tests
+
+[ 887708070 ] [
+    T{ blum-blum-shub f 590695557939 811977232793 } random-32*
+] unit-test
+
+
+[ 887708070 ] [
+    T{ blum-blum-shub f 590695557939 811977232793 } [
+        32 random-bits
+    ] with-random
+] unit-test
+
+[ 5726770047455156646 ] [
+    T{ blum-blum-shub f 590695557939 811977232793 } [
+        64 random-bits
+    ] with-random
+] unit-test
+
+[ 3716213681 ]
+[
+    100 T{ blum-blum-shub f 200352954495 846054538649 } tuck [
+        random-32* drop
+    ] curry times
+    random-32*
+] unit-test
index 017ef402c016a5ef12f31d3060299573499bddcf..5644cf6d08a784f91920641b26d942a667fa82ee 100755 (executable)
@@ -3,34 +3,26 @@ math.miller-rabin combinators.lib
 math.functions accessors random ;
 IN: random.blum-blum-shub
 
-! TODO: take (log log M) bits instead of 1 bit
-! Blum Blum Shub, M = pq
+! Blum Blum Shub, n = pq, x_i+1 = x_i ^ 2 mod n
+! return low bit of x+1
 TUPLE: blum-blum-shub x n ;
 
-C: <blum-blum-shub> blum-blum-shub
+<PRIVATE
 
 : generate-bbs-primes ( numbits -- p q )
-    #! two primes congruent to 3 (mod 4)
     [ [ random-prime ] curry [ 4 mod 3 = ] generate ] dup bi ;
 
-IN: crypto
 : <blum-blum-shub> ( numbits -- blum-blum-shub )
-    #! returns a Blum-Blum-Shub tuple
     generate-bbs-primes *
     [ find-relative-prime ] keep
     blum-blum-shub construct-boa ;
 
-! 256 make-bbs blum-blum-shub set-global
-
 : next-bbs-bit ( bbs -- bit )
-    #! x = x^2 mod n, return low bit of calculated x
-    [ [ x>> 2 ] [ n>> ] bi ^mod ]
-    [ [ >>x ] keep x>> 1 bitand ] bi ;
+    [ [ x>> 2 ] [ n>> ] bi ^mod ] keep
+    over >>x drop 1 bitand ;
 
-IN: crypto
-! : random ( n -- n )
-    ! ! #! Cryptographically secure random number using Blum-Blum-Shub 256
-    ! [ log2 1+ random-bits ] keep dupd >= [ -1 shift ] when ;
+PRIVATE>
 
 M: blum-blum-shub random-32* ( bbs -- r )
-    ;
+    0 32 rot
+    [ next-bbs-bit swap 1 shift bitor ] curry times ;
index 6921d1223ab162d03985ec8fb1b010dad095f4f5..c3b7311714eaa33079ff9d79543610d5e87b8c9c 100755 (executable)
@@ -113,7 +113,7 @@ M: array noise [ noise ] map vsum ;
     noise first2 {\r
         { [ over 4 <= ] [ >r drop 0 r> ] }\r
         { [ over 15 >= ] [ >r 2 * r> ] }\r
-        { [ t ] [ ] }\r
+        [ ]\r
     } cond\r
     {\r
         ! short words are easier to read\r
@@ -123,7 +123,7 @@ M: array noise [ noise ] map vsum ;
         { [ dup 25 >= ] [ >r 2 * r> 20 max ] }\r
         { [ dup 20 >= ] [ >r 5/3 * r> ] }\r
         { [ dup 15 >= ] [ >r 3/2 * r> ] }\r
-        { [ t ] [ ] }\r
+        [ ]\r
     } cond noise-factor ;\r
 \r
 GENERIC: word-noise-factor ( word -- factor )\r
index bf5105f334647ad6b48d4ced966532bcb59cd767..6663381522aeb2fbcde56cd4f2b526184c1cd0f7 100644 (file)
@@ -9,7 +9,7 @@ IN: rot13
     {
         { [ dup letter? ] [ CHAR: a rotate ] }
         { [ dup LETTER? ] [ CHAR: A rotate ] }
-        { [ t ] [ ] }
+        [ ]
     } cond ;
 
 : rot13 ( string -- string ) [ rot-letter ] map ;
index 945ba1a3b79db6f5390da6541d9a6d7fb9034739..0221d9b99ab9807e07a6ee483be451cbb97aa2bd 100755 (executable)
@@ -4,7 +4,7 @@
 USING: combinators.lib kernel sequences math namespaces assocs 
 random sequences.private shuffle math.functions mirrors
 arrays math.parser math.private sorting strings ascii macros
-assocs.lib quotations ;
+assocs.lib quotations hashtables ;
 IN: sequences.lib
 
 : each-withn ( seq quot n -- ) nwith each ; inline
@@ -37,6 +37,16 @@ MACRO: firstn ( n -- )
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
+: each-percent ( seq quot -- )
+  >r
+  dup length
+  dup [ / ] curry
+  [ 1+ ] swap compose
+  r> compose
+  2each ;                       inline
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
 : sigma ( seq quot -- n )
     [ rot slip + ] curry 0 swap reduce ; inline
 
@@ -221,7 +231,7 @@ PRIVATE>
     [ swap nth ] with map ;
 
 : replace ( str oldseq newseq -- str' )
-    H{ } 2seq>assoc substitute ;
+    zip >hashtable substitute ;
 
 : remove-nth ( seq n -- seq' )
     cut-slice 1 tail-slice append ;
index 7a2fbfae9e6c4a93d650a585e095d39362d00d69..280ce3b43ed98e632610714a5bad3b7979f98aec 100755 (executable)
@@ -65,7 +65,7 @@ GENERIC: (serialize) ( obj -- )
     read1 {
         { [ dup HEX: ff = ] [ drop deserialize-cell read be> ] }
         { [ dup HEX: 80 >= ] [ HEX: 80 bitxor ] }
-        { [ t ] [ read be> ] }
+        [ read be> ]
     } cond ;
 
 : serialize-shared ( obj quot -- )
@@ -183,7 +183,7 @@ M: word (serialize) ( obj -- )
     {
         { [ dup t eq? ] [ serialize-true ] }
         { [ dup word-vocabulary not ] [ serialize-gensym ] }
-        { [ t ] [ serialize-word ] }
+        [ serialize-word ]
     } cond ;
 
 M: wrapper (serialize) ( obj -- )
index 14957ceca2e4fe8589dfe6bc851c996a9b9a0bf3..f3db1cdf0988ba4037120655fe67ca67e3519a3b 100755 (executable)
@@ -56,9 +56,9 @@ SYMBOL: data-mode
             "220 OK\r\n" write flush t
           ] }
         { [ data-mode get ] [ dup global [ print ] bind t ] }
-        { [ t ] 
+        [ 
             "500 ERROR\r\n" write flush t
-          ] }
+        ]
     } cond nip [ process ] when ;
 
 : mock-smtp-server ( port -- )
index ee2b021329f20e393da26a90b8469f48958a3327..844857d1db5911f431dc8d0b2a6a04800c919929 100755 (executable)
@@ -70,7 +70,7 @@ LOG: smtp-response DEBUG
         { [ dup "50" head? ] [ smtp-response "syntax error" throw ] }
         { [ dup "53" head? ] [ smtp-response "invalid authentication data" throw ] }
         { [ dup "55" head? ] [ smtp-response "fatal error" throw ] }
-        { [ t ] [ "unknown error" throw ] }
+        [ "unknown error" throw ]
     } cond ;
 
 : multiline? ( response -- boolean )
index d66ffdc66e075d95739160857d73fa32d4c0e2e0..200257b31c53ef442a1aa502be553ca3191288e4 100755 (executable)
@@ -306,7 +306,7 @@ M: invaders-gadget draw-gadget* ( gadget -- )
     { [ dup 184 238 within pick 0 223 within and ] [ 2drop green ] }
     { [ dup 240 247 within pick 16 133 within and ] [ 2drop green ] }
     { [ dup 247 215 - 247 184 - within pick 0 223 within and ] [ 2drop red ] }
-    { [ t ] [ 2drop white ] }
+    [ 2drop white ]
   } cond ;
 
 : plot-bitmap-bits ( bitmap point byte bit -- )
index 764c4d92f0271f0d3e1ffa0b25026fddee79347e..b0ba85c97f55dea438a78ea3d4445947e298a720 100644 (file)
@@ -32,7 +32,7 @@ DEFER: search
         { [ 3dup nip row-contains? ] [ 3drop ] }
         { [ 3dup drop col-contains? ] [ 3drop ] }
         { [ 3dup box-contains? ] [ 3drop ] }
-        { [ t ] [ assume ] }
+        [ assume ]
     } cond ;
 
 : solve ( x y -- ) 9 [ 1+ 2over attempt ] each 2drop ;
@@ -62,7 +62,7 @@ DEFER: search
         { [ over 9 = ] [ >r drop 0 r> 1+ search ] }
         { [ over 0 = over 9 = and ] [ 2drop solution. ] }
         { [ 2dup board> ] [ >r 1+ r> search ] }
-        { [ t ] [ solve ] }
+        [ solve ]
     } cond ;
 
 : sudoku ( board -- )
index 99af06b80ff5a42a2567c6f15c049b19b90a51fd..038078969d04e86c886efe4cebe03ffd3fe3961c 100755 (executable)
@@ -1,7 +1,7 @@
 USING: combinators io io.files io.streams.duplex
 io.streams.string kernel math math.parser continuations
 namespaces pack prettyprint sequences strings system
-hexdump io.encodings.binary ;
+hexdump io.encodings.binary inspector accessors ;
 IN: tar
 
 : zero-checksum 256 ;
@@ -79,87 +79,67 @@ SYMBOL: filename
         ] keep
     ] if ;
 
-TUPLE: unknown-typeflag str ;
-: <unknown-typeflag> ( ch -- obj )
-    1string \ unknown-typeflag construct-boa ;
-
-TUPLE: unimplemented-typeflag header ;
-: <unimplemented-typeflag> ( header -- obj )
-    global [ "Unimplemented typeflag: " print dup . flush ] bind
-    tar-header-typeflag
-    1string \ unimplemented-typeflag construct-boa ;
+ERROR: unknown-typeflag ch ;
+M: unknown-typeflag summary ( obj -- str )
+    ch>> 1string
+    "Unknown typeflag: " prepend ;
 
 : tar-append-path ( path -- newpath )
     base-dir get prepend-path ;
 
 ! Normal file
 : typeflag-0
-  tar-header-name tar-append-path binary <file-writer>
+  name>> tar-append-path binary <file-writer>
   [ read-data-blocks ] keep dispose ;
 
 ! Hard link
-: typeflag-1 ( header -- )
-   <unimplemented-typeflag> throw ;
+: typeflag-1 ( header -- ) unknown-typeflag ;
 
 ! Symlink
-: typeflag-2 ( header -- )
-    <unimplemented-typeflag> throw ;
+: typeflag-2 ( header -- ) unknown-typeflag ;
 
 ! character special
-: typeflag-3 ( header -- )
-    <unimplemented-typeflag> throw ;
+: typeflag-3 ( header -- ) unknown-typeflag ;
 
 ! Block special
-: typeflag-4 ( header -- )
-    <unimplemented-typeflag> throw ;
+: typeflag-4 ( header -- ) unknown-typeflag ;
 
 ! Directory
 : typeflag-5 ( header -- )
     tar-header-name tar-append-path make-directories ;
 
 ! FIFO
-: typeflag-6 ( header -- )
-    <unimplemented-typeflag> throw ;
+: typeflag-6 ( header -- ) unknown-typeflag ;
 
 ! Contiguous file
-: typeflag-7 ( header -- )
-    <unimplemented-typeflag> throw ;
+: typeflag-7 ( header -- ) unknown-typeflag ;
 
 ! Global extended header
-: typeflag-8 ( header -- )
-    <unimplemented-typeflag> throw ;
+: typeflag-8 ( header -- ) unknown-typeflag ;
 
 ! Extended header
-: typeflag-9 ( header -- )
-    <unimplemented-typeflag> throw ;
+: typeflag-9 ( header -- ) unknown-typeflag ;
 
 ! Global POSIX header
-: typeflag-g ( header -- )
-    <unimplemented-typeflag> throw ;
+: typeflag-g ( header -- ) unknown-typeflag ;
 
 ! Extended POSIX header
-: typeflag-x ( header -- )
-    <unimplemented-typeflag> throw ;
+: typeflag-x ( header -- ) unknown-typeflag ;
 
 ! Solaris access control list
-: typeflag-A ( header -- )
-    <unimplemented-typeflag> throw ;
+: typeflag-A ( header -- ) unknown-typeflag ;
 
 ! GNU dumpdir
-: typeflag-D ( header -- )
-    <unimplemented-typeflag> throw ;
+: typeflag-D ( header -- ) unknown-typeflag ;
 
 ! Solaris extended attribute file
-: typeflag-E ( header -- )
-    <unimplemented-typeflag> throw ;
+: typeflag-E ( header -- ) unknown-typeflag ;
 
 ! Inode metadata
-: typeflag-I ( header -- )
-    <unimplemented-typeflag> throw ;
+: typeflag-I ( header -- ) unknown-typeflag ;
 
 ! Long link name
-: typeflag-K ( header -- )
-    <unimplemented-typeflag> throw ;
+: typeflag-K ( header -- ) unknown-typeflag ;
 
 ! Long file name
 : typeflag-L ( header -- )
@@ -169,24 +149,19 @@ TUPLE: unimplemented-typeflag header ;
     filename get tar-append-path make-directories ;
 
 ! Multi volume continuation entry
-: typeflag-M ( header -- )
-    <unimplemented-typeflag> throw ;
+: typeflag-M ( header -- ) unknown-typeflag ;
 
 ! GNU long file name
-: typeflag-N ( header -- )
-    <unimplemented-typeflag> throw ;
+: typeflag-N ( header -- ) unknown-typeflag ;
 
 ! Sparse file
-: typeflag-S ( header -- )
-    <unimplemented-typeflag> throw ;
+: typeflag-S ( header -- ) unknown-typeflag ;
 
 ! Volume header
-: typeflag-V ( header -- )
-    <unimplemented-typeflag> throw ;
+: typeflag-V ( header -- ) unknown-typeflag ;
 
 ! Vendor extended header type
-: typeflag-X ( header -- )
-    <unimplemented-typeflag> throw ;
+: typeflag-X ( header -- ) unknown-typeflag ;
 
 : (parse-tar) ( -- )
     512 read 
@@ -218,7 +193,7 @@ TUPLE: unimplemented-typeflag header ;
             { CHAR: S [ typeflag-S ] }
             { CHAR: V [ typeflag-V ] }
             { CHAR: X [ typeflag-X ] }
-            [ <unknown-typeflag> throw ]
+            [ unknown-typeflag ]
         } case
         ! dup tar-header-size zero? [
             ! out-stream get [ dispose ] when
@@ -237,7 +212,7 @@ TUPLE: unimplemented-typeflag header ;
 
 : parse-tar ( path -- obj )
     binary [
-        "tar-test" resource-path base-dir set
+        "resource:tar-test" base-dir set
         global [ nl nl nl "Starting to parse .tar..." print flush ] bind
         global [ "Expanding to: " write base-dir get . flush ] bind
         (parse-tar)
index 07038ceadff85c45ef78e35097703483b7278808..ef710ea57db034d1a5ae215197d0ad49a18dcee1 100755 (executable)
@@ -2,10 +2,16 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel words parser io inspector quotations sequences
 prettyprint continuations effects definitions compiler.units
-namespaces assocs tools.walker ;
+namespaces assocs tools.walker generic ;
 IN: tools.annotations
 
-: reset ( word -- )
+GENERIC: reset ( word -- )
+
+M: generic reset
+    [ call-next-method ]
+    [ subwords [ reset ] each ] bi ;
+
+M: word reset
     dup "unannotated-def" word-prop [
         [
             dup dup "unannotated-def" word-prop define
@@ -60,8 +66,16 @@ IN: tools.annotations
 : watch-vars ( word vars -- )
     dupd [ (watch-vars) ] 2curry annotate ;
 
+GENERIC# annotate-methods 1 ( word quot -- )
+
+M: generic annotate-methods
+    >r "methods" word-prop values r> [ annotate ] curry each ;
+
+M: word annotate-methods
+    annotate ;
+
 : breakpoint ( word -- )
-    [ add-breakpoint ] annotate ;
+    [ add-breakpoint ] annotate-methods ;
 
 : breakpoint-if ( word quot -- )
-    [ [ [ break ] when ] rot 3append ] curry annotate ;
+    [ [ [ break ] when ] rot 3append ] curry annotate-methods ;
index 16bde2100f059fe693eee31bf653e0a98ab7784a..b9c37c065661ad65c10d4b360886809109078851 100755 (executable)
@@ -35,7 +35,7 @@ unicode.categories ;
         { [ 2dup length 1- number= ] [ 2drop 4 ] }
         { [ 2dup >r 1- r> nth Letter? not ] [ 2drop 10 ] }
         { [ 2dup >r 1+ r> nth Letter? not ] [ 2drop 4 ] }
-        { [ t ] [ 2drop 1 ] }
+        [ 2drop 1 ]
     } cond ;
 
 : score ( full fuzzy -- n )
index e11d16c4ecb29c20a4c54c92e1d269095a4eeb95..b8386542488b6f459e253410de9c999faa85c226 100755 (executable)
@@ -22,9 +22,8 @@ IN: tools.deploy.backend
         +stdout+ >>stderr
         +closed+ >>stdin
         +low-priority+ >>priority
-    utf8 <process-stream>
-    dup copy-lines
-    process>> wait-for-process zero? [
+    utf8 <process-stream*>
+    >r copy-lines r> wait-for-process zero? [
         "Deployment failed" throw
     ] unless ;
 
index f104fb0210310e3b79bb6ac625f7e51ffa55123d..37689f749f30ea2c2a3d8c2c64aacacc420ce96c 100755 (executable)
@@ -1,7 +1,7 @@
 IN: tools.deploy.tests\r
 USING: tools.test system io.files kernel tools.deploy.config\r
 tools.deploy.backend math sequences io.launcher arrays\r
-namespaces continuations layouts ;\r
+namespaces continuations layouts accessors ;\r
 \r
 : shake-and-bake ( vocab -- )\r
     [ "test.image" temp-file delete-file ] ignore-errors\r
@@ -12,7 +12,7 @@ namespaces continuations layouts ;
     ] with-directory ;\r
 \r
 : small-enough? ( n -- ? )\r
-    >r "test.image" temp-file file-info file-info-size r> <= ;\r
+    >r "test.image" temp-file file-info size>> r> <= ;\r
 \r
 [ ] [ "hello-world" shake-and-bake ] unit-test\r
 \r
@@ -23,7 +23,7 @@ namespaces continuations layouts ;
 [ ] [ "sudoku" shake-and-bake ] unit-test\r
 \r
 [ t ] [\r
-    1500000 small-enough?\r
+    cell 8 = 30 15 ? 100000 * small-enough?\r
 ] unit-test\r
 \r
 [ ] [ "hello-ui" shake-and-bake ] unit-test\r
@@ -34,13 +34,13 @@ namespaces continuations layouts ;
 ] unit-test\r
 \r
 [ t ] [\r
-    2000000 small-enough?\r
+    cell 8 = 40 20 ? 100000 * small-enough?\r
 ] unit-test\r
 \r
 [ ] [ "bunny" shake-and-bake ] unit-test\r
 \r
 [ t ] [\r
-    3000000 small-enough?\r
+    cell 8 = 50 30 ? 100000 * small-enough?\r
 ] unit-test\r
 \r
 [ ] [\r
index 3a7f8e5d03b48f4cd2f9b5abb68c09cc888f6a6d..3121866d94f3d6d5bc231712e7636c4a0c2f3905 100755 (executable)
@@ -3,7 +3,8 @@
 USING: io io.files kernel namespaces sequences
 system tools.deploy.backend tools.deploy.config assocs
 hashtables prettyprint io.unix.backend cocoa io.encodings.utf8
-cocoa.application cocoa.classes cocoa.plists qualified ;
+io.backend cocoa.application cocoa.classes cocoa.plists
+qualified ;
 IN: tools.deploy.macosx
 
 : bundle-dir ( -- dir )
@@ -20,23 +21,21 @@ IN: tools.deploy.macosx
     "fonts/" resource-path
     swap "Contents/Resources/" append-path copy-tree-into ;
 
-: app-plist ( executable bundle-name -- string )
+: app-plist ( executable bundle-name -- assoc )
     [
-        namespace {
-            { "CFBundleInfoDictionaryVersion" "6.0" }
-            { "CFBundlePackageType" "APPL" }
-        } update
+        "6.0" "CFBundleInfoDictionaryVersion" set
+        "APPL" "CFBundlePackageType" set
 
         file-name "CFBundleName" set
 
-        dup "CFBundleExecutable" set
-        "org.factor." prepend "CFBundleIdentifier" set
-    ] H{ } make-assoc plist>string ;
+        [ "CFBundleExecutable" set ]
+        [ "org.factor." prepend "CFBundleIdentifier" set ] bi
+    ] H{ } make-assoc ;
 
-: create-app-plist ( vocab bundle-name -- )
+: create-app-plist ( executable bundle-name -- )
     [ app-plist ] keep
     "Contents/Info.plist" append-path
-    utf8 set-file-contents ;
+    write-plist ;
 
 : create-app-dir ( vocab bundle-name -- vm )
     dup "Frameworks" copy-bundle-dir
@@ -64,6 +63,6 @@ M: macosx deploy* ( vocab -- )
             [ bundle-name create-app-dir ] keep
             [ bundle-name deploy.app-image ] keep
             namespace make-deploy-image
-            bundle-name show-in-finder
+            bundle-name normalize-path show-in-finder
         ] bind
     ] with-directory ;
index ee9c2b9fab1cb21f95db282c336aa73ad2e89374..72e1c33a26e88aef7cfdeab966216b997aaa5f3a 100755 (executable)
@@ -6,6 +6,7 @@ memory kernel.private continuations io prettyprint
 vocabs.loader debugger system strings ;
 QUALIFIED: bootstrap.stage2
 QUALIFIED: classes
+QUALIFIED: command-line
 QUALIFIED: compiler.errors.private
 QUALIFIED: compiler.units
 QUALIFIED: continuations
@@ -139,14 +140,17 @@ IN: tools.deploy.shaker
             { } { "cpu" } strip-vocab-globals %
 
             {
+                gensym
                 classes:class-and-cache
                 classes:class-not-cache
                 classes:class-or-cache
                 classes:class<-cache
                 classes:classes-intersect-cache
                 classes:update-map
+                command-line:main-vocab-hook
                 compiled-crossref
                 compiler.units:recompile-hook
+                compiler.units:update-tuples-hook
                 definitions:crossref
                 interactive-vocabs
                 layouts:num-tags
@@ -186,6 +190,11 @@ IN: tools.deploy.shaker
         deploy-ui? get [
             "ui-error-hook" "ui.gadgets.worlds" lookup ,
         ] when
+
+        "<computer>" "inference.dataflow" lookup [ , ] when*
+
+        "windows-messages" "windows.messages" lookup [ , ] when*
+
     ] { } make ;
 
 : strip-globals ( stripped-globals -- )
index 33ab877ee19d9ccb25cd94c598c8026cbd2c7925..68b106663c1fca4957a11f9d55e5b2863d2b606e 100755 (executable)
@@ -31,6 +31,6 @@ M: winnt deploy*
             [ deploy-name get create-exe-dir ] keep
             [ deploy-name get image-name ] keep
             [ namespace make-deploy-image ] keep
-            open-in-explorer
+            (normalize-path) open-in-explorer
         ] bind
     ] with-directory ;
index 5b835cd52f2c97add83df607ad96c9ee6a81b607..39ee85b07a343eb4871191a9fe59d50b2d719935 100755 (executable)
@@ -26,8 +26,7 @@ M: pair make-disassemble-cmd
 M: method-spec make-disassemble-cmd
     first2 method make-disassemble-cmd ;
 
-: gdb-binary ( -- string )
-    os freebsd? "gdb66" "gdb" ? ;
+: gdb-binary ( -- string ) "gdb" ;
 
 : run-gdb ( -- lines )
     <process>
index 11bb8d859b789d2bd7aa332280ea8649f299c889..28c219ee4d5ebd040ad74ff241b3a76709b2f07e 100755 (executable)
@@ -15,8 +15,7 @@ ARTICLE: "tools.memory" "Object memory tools"
 "You can check an object's the heap memory usage:"
 { $subsection size }
 "The garbage collector can be invoked manually:"
-{ $subsection data-gc }
-{ $subsection code-gc }
+{ $subsection gc }
 { $see-also "images" } ;
 
 ABOUT: "tools.memory"
index 9efbf63f7f0d08254d08d5463c0d12b5ee8646fd..60b54c2a0dbec2f671679e3cbf8807a0510f5a40 100644 (file)
@@ -1,4 +1,8 @@
 USING: tools.test tools.memory ;
 IN: tools.memory.tests
 
+\ room. must-infer
+[ ] [ room. ] unit-test
+
+\ heap-stats. must-infer
 [ ] [ heap-stats. ] unit-test
index 2077ea497edbb27538f262471841c424f6e3f13b..b8fdcab280e310c741db6e6d2efcca28478defab 100644 (file)
@@ -1,22 +1,29 @@
-! Copyright (C) 2005, 2007 Slava Pestov.
+! Copyright (C) 2005, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel sequences vectors arrays generic assocs io math
 namespaces parser prettyprint strings io.styles vectors words
-system sorting splitting math.parser classes memory ;
+system sorting splitting math.parser classes memory combinators ;
 IN: tools.memory
 
+<PRIVATE
+
+: write-size ( n -- )
+    number>string
+    dup length 4 > [ 3 cut* "," swap 3append ] when
+    " KB" append write-cell ;
+
 : write-total/used/free ( free total str -- )
     [
         write-cell
-        dup number>string write-cell
-        over - number>string write-cell
-        number>string write-cell
+        dup write-size
+        over - write-size
+        write-size
     ] with-row ;
 
 : write-total ( n str -- )
     [
         write-cell
-        number>string write-cell
+        write-size
         [ ] with-cell
         [ ] with-cell
     ] with-row ;
@@ -25,26 +32,41 @@ IN: tools.memory
     [ [ write-cell ] each ] with-row ;
 
 : (data-room.) ( -- )
-    data-room 2 <groups> 0 [
-        "Generation " pick number>string append
-        >r first2 r> write-total/used/free 1+
-    ] reduce drop
+    data-room 2 <groups> dup length [
+        [ first2 ] [ number>string "Generation " prepend ] bi*
+        write-total/used/free
+    ] 2each
     "Cards" write-total ;
 
+: write-labelled-size ( n string -- )
+    [ write-cell write-size ] with-row ;
+
 : (code-room.) ( -- )
-    code-room "Code space" write-total/used/free ;
+    code-room {
+        [ "Size:" write-labelled-size ]
+        [ "Used:" write-labelled-size ]
+        [ "Total free space:" write-labelled-size ]
+        [ "Largest free block:" write-labelled-size ]
+    } spread ;
+
+: heap-stat-step ( counts sizes obj -- )
+    [ dup size swap class rot at+ ] keep
+    1 swap class rot at+ ;
+
+PRIVATE>
 
 : room. ( -- )
+    "==== DATA HEAP" print
     standard-table-style [
         { "" "Total" "Used" "Free" } write-headings
         (data-room.)
+    ] tabular-output
+    nl
+    "==== CODE HEAP" print
+    standard-table-style [
         (code-room.)
     ] tabular-output ;
 
-: heap-stat-step ( counts sizes obj -- )
-    [ dup size swap class rot at+ ] keep
-    1 swap class rot at+ ;
-
 : heap-stats ( -- counts sizes )
     H{ } clone H{ } clone
     [ >r 2dup r> heap-stat-step ] each-object ;
index e33201e22cb4091981cfd45364eeb58134ba5272..450a024a1e90d8fc8fed10b0d686555060c3d9a0 100755 (executable)
@@ -8,7 +8,7 @@ alien tools.profiler.private sequences ;
     \ length profile-counter =
 ] unit-test
 
-[ ] [ [ 10 [ data-gc ] times ] profile ] unit-test
+[ ] [ [ 10 [ gc ] times ] profile ] unit-test
 
 [ ] [ [ 1000 sleep ] profile ] unit-test 
 
index 552247e2c430484a36cd2d3ab0f3f613b487a73a..060377d1272a10ae3692c0420895cd074347c976 100755 (executable)
@@ -22,7 +22,7 @@ heaps.private system math math.parser ;
 : threads. ( -- )\r
     standard-table-style [\r
         [\r
-            { "ID" "Name" "Waiting on" "Remaining sleep" }\r
+            { "ID:" "Name:" "Waiting on:" "Remaining sleep:" }\r
             [ [ write ] with-cell ] each\r
         ] with-row\r
 \r
index 69ad9272a7616706f2d205cb8024c0d7b8dc8a4f..db1edbeb61bea21d4d706c7dc1eb02a56c1e9196 100755 (executable)
@@ -10,7 +10,7 @@ IN: tools.vocabs.browser
     {
         { [ dup not ] [ drop "" ] }
         { [ dup vocab-main ] [ drop "[Runnable]" ] }
-        { [ t ] [ drop "[Loaded]" ] }
+        [ drop "[Loaded]" ]
     } cond ;
 
 : write-status ( vocab -- )
@@ -79,7 +79,7 @@ C: <vocab-author> vocab-author
 
 : describe-help ( vocab -- )
     vocab-help [
-        "Documentation" $heading nl ($link)
+        "Documentation" $heading ($link)
     ] when* ;
 
 : describe-children ( vocab -- )
diff --git a/extra/tools/vocabs/monitor/monitor-tests.factor b/extra/tools/vocabs/monitor/monitor-tests.factor
new file mode 100644 (file)
index 0000000..f1eece9
--- /dev/null
@@ -0,0 +1,6 @@
+USING: tools.test tools.vocabs.monitor io.files ;
+IN: tools.vocabs.monitor.tests
+
+[ "kernel" ] [ "core/kernel/kernel.factor" path>vocab ] unit-test
+[ "kernel" ] [ "core/kernel/" path>vocab ] unit-test
+[ "kernel" ] [ "core/kernel/" resource-path path>vocab ] unit-test
index 071f1796769988e8d4f051afcf09f4af1e75c3fe..ab5e8c66b7ed8752d7a7453700e839f594b502c8 100755 (executable)
@@ -1,24 +1,53 @@
 ! Copyright (C) 2008 Slava Pestov.\r
 ! See http://factorcode.org/license.txt for BSD license.\r
 USING: threads io.files io.monitors init kernel\r
-vocabs.loader tools.vocabs namespaces continuations ;\r
+vocabs vocabs.loader tools.vocabs namespaces continuations\r
+sequences splitting assocs command-line ;\r
 IN: tools.vocabs.monitor\r
 \r
-! Use file system change monitoring to flush the tags/authors\r
-! cache\r
-SYMBOL: vocab-monitor\r
+: vocab-dir>vocab-name ( path -- vocab )\r
+    left-trim-separators right-trim-separators\r
+    { { CHAR: / CHAR: . } { CHAR: \\ CHAR: . } } substitute ;\r
+\r
+: path>vocab-name ( path -- vocab )\r
+    dup ".factor" tail? [ parent-directory ] when ;\r
+\r
+: chop-vocab-root ( path -- path' )\r
+    "resource:" prepend-path (normalize-path)\r
+    dup vocab-roots get\r
+    [ (normalize-path) ] map\r
+    [ head? ] with find nip\r
+    ?head drop ;\r
+\r
+: path>vocab ( path -- vocab )\r
+    chop-vocab-root path>vocab-name vocab-dir>vocab-name ;\r
+\r
+: monitor-loop ( monitor -- )\r
+    #! On OS X, monitors give us the full path, so we chop it\r
+    #! off if its there.\r
+    dup next-change drop path>vocab changed-vocab\r
+    reset-cache\r
+    monitor-loop ;\r
 \r
 : monitor-thread ( -- )\r
-    vocab-monitor get-global\r
-    next-change 2drop\r
-    t sources-changed? set-global reset-cache ;\r
+    [\r
+        [\r
+            "" resource-path t <monitor>\r
+            \r
+            H{ } clone changed-vocabs set-global\r
+            vocabs [ changed-vocab ] each\r
+            \r
+            monitor-loop\r
+        ] with-monitors\r
+    ] ignore-errors ;\r
 \r
-: start-monitor-thread\r
+: start-monitor-thread ( -- )\r
     #! Silently ignore errors during monitor creation since\r
     #! monitors are not supported on all platforms.\r
-    [\r
-        "" resource-path t <monitor> vocab-monitor set-global\r
-        [ monitor-thread t ] "Vocabulary monitor" spawn-server drop\r
-    ] ignore-errors ;\r
+    [ monitor-thread ] "Vocabulary monitor" spawn drop ;\r
 \r
-[ start-monitor-thread ] "tools.vocabs.monitor" add-init-hook\r
+[\r
+    "-no-monitors" cli-args member? [\r
+        start-monitor-thread\r
+    ] unless\r
+] "tools.vocabs.monitor" add-init-hook\r
diff --git a/extra/tools/vocabs/vocabs-tests.factor b/extra/tools/vocabs/vocabs-tests.factor
new file mode 100644 (file)
index 0000000..04e628d
--- /dev/null
@@ -0,0 +1,9 @@
+IN: tools.vocabs.tests
+USING: tools.test tools.vocabs namespaces continuations ;
+
+[ ] [
+    changed-vocabs get-global
+    f changed-vocabs set-global
+    [ t ] [ "kernel" changed-vocab? ] unit-test
+    [ "kernel" changed-vocab ] [ changed-vocabs set-global ] [ ] cleanup
+] unit-test
index 2f941ad2ce5a043168d09cfab217a5c1fa4c19bb..484d401769bd75e05a0e1c1b4cc953f516f2b54a 100755 (executable)
@@ -21,55 +21,25 @@ IN: tools.vocabs
 \r
 : vocab-tests ( vocab -- tests )\r
     [\r
-        dup vocab-tests-file [ , ] when*\r
-        vocab-tests-dir [ % ] when*\r
+        [ vocab-tests-file [ , ] when* ]\r
+        [ vocab-tests-dir [ % ] when* ] bi\r
     ] { } make ;\r
 \r
 : vocab-files ( vocab -- seq )\r
     [\r
-        dup vocab-source-path [ , ] when*\r
-        dup vocab-docs-path [ , ] when*\r
-        vocab-tests %\r
+        [ vocab-source-path [ , ] when* ]\r
+        [ vocab-docs-path [ , ] when* ]\r
+        [ vocab-tests % ] tri\r
     ] { } make ;\r
 \r
-: source-modified? ( path -- ? )\r
-    dup source-files get at [\r
-        dup source-file-path\r
-        dup exists? [\r
-            utf8 file-lines lines-crc32\r
-            swap source-file-checksum = not\r
-        ] [\r
-            2drop f\r
-        ] if\r
-    ] [\r
-        exists?\r
-    ] ?if ;\r
-\r
-: modified ( seq quot -- seq )\r
-    [ dup ] swap compose { } map>assoc\r
-    [ nip ] assoc-subset\r
-    [ nip source-modified? ] assoc-subset keys ; inline\r
-\r
-: modified-sources ( vocabs -- seq )\r
-    [ vocab-source-path ] modified ;\r
-\r
-: modified-docs ( vocabs -- seq )\r
-    [ vocab-docs-path ] modified ;\r
-\r
-: to-refresh ( prefix -- modified-sources modified-docs )\r
-    child-vocabs\r
-    dup modified-sources swap modified-docs ;\r
-\r
 : vocab-heading. ( vocab -- )\r
     nl\r
     "==== " write\r
-    dup vocab-name swap vocab write-object ":" print\r
+    [ vocab-name ] [ vocab write-object ] bi ":" print\r
     nl ;\r
 \r
 : load-error. ( triple -- )\r
-    dup first vocab-heading.\r
-    dup second print-error\r
-    drop ;\r
+    [ first vocab-heading. ] [ second print-error ] bi ;\r
 \r
 : load-failures. ( failures -- )\r
     [ load-error. nl ] each ;\r
@@ -88,31 +58,101 @@ SYMBOL: failures
         failures get\r
     ] with-compiler-errors ;\r
 \r
-: do-refresh ( modified-sources modified-docs -- )\r
-    2dup\r
-    [ f swap set-vocab-docs-loaded? ] each\r
-    [ f swap set-vocab-source-loaded? ] each\r
-    append prune require-all load-failures. ;\r
+: source-modified? ( path -- ? )\r
+    dup source-files get at [\r
+        dup source-file-path\r
+        dup exists? [\r
+            utf8 file-lines lines-crc32\r
+            swap source-file-checksum = not\r
+        ] [\r
+            2drop f\r
+        ] if\r
+    ] [\r
+        exists?\r
+    ] ?if ;\r
 \r
-: refresh ( prefix -- ) to-refresh do-refresh ;\r
+SYMBOL: changed-vocabs\r
+\r
+[ f changed-vocabs set-global ] "tools.vocabs" add-init-hook\r
 \r
-SYMBOL: sources-changed?\r
+: changed-vocab ( vocab -- )\r
+    dup vocab changed-vocabs get and\r
+    [ dup changed-vocabs get set-at ] [ drop ] if ;\r
 \r
-[ t sources-changed? set-global ] "tools.vocabs" add-init-hook\r
+: unchanged-vocab ( vocab -- )\r
+    changed-vocabs get delete-at ;\r
 \r
-: refresh-all ( -- )\r
-    "" refresh f sources-changed? set-global ;\r
+: unchanged-vocabs ( vocabs -- )\r
+    [ unchanged-vocab ] each ;\r
+\r
+: changed-vocab? ( vocab -- ? )\r
+    changed-vocabs get dup [ key? ] [ 2drop t ] if ;\r
+\r
+: filter-changed ( vocabs -- vocabs' )\r
+    [ changed-vocab? ] subset ;\r
+\r
+SYMBOL: modified-sources\r
+SYMBOL: modified-docs\r
+\r
+: (to-refresh) ( vocab variable loaded? path -- )\r
+    dup [\r
+        swap [\r
+            pick changed-vocab? [\r
+                source-modified? [ get push ] [ 2drop ] if\r
+            ] [ 3drop ] if\r
+        ] [ drop get push ] if\r
+    ] [ 2drop 2drop ] if ;\r
+\r
+: to-refresh ( prefix -- modified-sources modified-docs unchanged )\r
+    [\r
+        V{ } clone modified-sources set\r
+        V{ } clone modified-docs set\r
+\r
+        child-vocabs [\r
+            [\r
+                [\r
+                    [ modified-sources ]\r
+                    [ vocab-source-loaded? ]\r
+                    [ vocab-source-path ]\r
+                    tri (to-refresh)\r
+                ] [\r
+                    [ modified-docs ]\r
+                    [ vocab-docs-loaded? ]\r
+                    [ vocab-docs-path ]\r
+                    tri (to-refresh)\r
+                ] bi\r
+            ] each\r
+\r
+            modified-sources get\r
+            modified-docs get\r
+        ]\r
+        [ modified-sources get modified-docs get append swap seq-diff ] bi\r
+    ] with-scope ;\r
+\r
+: do-refresh ( modified-sources modified-docs unchanged -- )\r
+    unchanged-vocabs\r
+    [\r
+        [ [ f swap set-vocab-source-loaded? ] each ]\r
+        [ [ f swap set-vocab-docs-loaded? ] each ] bi*\r
+    ]\r
+    [\r
+        append prune\r
+        [ unchanged-vocabs ]\r
+        [ require-all load-failures. ] bi\r
+    ] 2bi ;\r
+\r
+: refresh ( prefix -- ) to-refresh do-refresh ;\r
 \r
-MEMO: (vocab-file-contents) ( path -- lines )\r
-    dup exists? [ utf8 file-lines ] [ drop f ] if ;\r
+: refresh-all ( -- ) "" refresh ;\r
 \r
-: vocab-file-contents ( vocab name -- seq )\r
-    vocab-append-path dup [ (vocab-file-contents) ] when ;\r
+MEMO: vocab-file-contents ( vocab name -- seq )\r
+    vocab-append-path dup\r
+    [ dup exists? [ utf8 file-lines ] [ drop f ] if ] when ;\r
 \r
 : set-vocab-file-contents ( seq vocab name -- )\r
     dupd vocab-append-path [\r
         utf8 set-file-lines\r
-        \ (vocab-file-contents) reset-memoized\r
+        \ vocab-file-contents reset-memoized\r
     ] [\r
         "The " swap vocab-name\r
         " vocabulary was not loaded from the file system"\r
@@ -215,7 +255,7 @@ MEMO: all-vocabs-seq ( -- seq )
         { [ ".test" ?tail ] [ t ] }\r
         { [ "raptor" ?head ] [ t ] }\r
         { [ dup "tools.deploy.app" = ] [ t ] }\r
-        { [ t ] [ f ] }\r
+        [ f ]\r
     } cond nip ;\r
 \r
 : filter-dangerous ( seq -- seq' )\r
@@ -261,7 +301,7 @@ MEMO: all-authors ( -- seq )
 \r
 : reset-cache ( -- )\r
     root-cache get-global clear-assoc\r
-    \ (vocab-file-contents) reset-memoized\r
+    \ vocab-file-contents reset-memoized\r
     \ all-vocabs-seq reset-memoized\r
     \ all-authors reset-memoized\r
     \ all-tags reset-memoized ;\r
index 6bd8ace877ef9142b78e6462a0d150dff243af36..8a5ab42767d3df122eeed021c52992fa4920821e 100755 (executable)
@@ -3,7 +3,8 @@
 USING: threads kernel namespaces continuations combinators
 sequences math namespaces.private continuations.private
 concurrency.messaging quotations kernel.private words
-sequences.private assocs models arrays accessors ;
+sequences.private assocs models arrays accessors
+generic generic.standard ;
 IN: tools.walker
 
 SYMBOL: show-walker-hook ! ( status continuation thread -- )
@@ -68,15 +69,13 @@ M: object add-breakpoint ;
 : (step-into-dispatch) nth (step-into-quot) ;
 
 : (step-into-execute) ( word -- )
-    dup "step-into" word-prop [
-        call
-    ] [
-        dup primitive? [
-            execute break
-        ] [
-            word-def (step-into-quot)
-        ] if
-    ] ?if ;
+    {
+        { [ dup "step-into" word-prop ] [ "step-into" word-prop call ] }
+        { [ dup standard-generic? ] [ effective-method (step-into-execute) ] }
+        { [ dup hook-generic? ] [ effective-method (step-into-execute) ] }
+        { [ dup primitive? ] [ execute break ] }
+        [ word-def (step-into-quot) ]
+    } cond ;
 
 \ (step-into-execute) t "step-into?" set-word-prop
 
@@ -155,7 +154,7 @@ SYMBOL: +stopped+
                 { [ dup quotation? ] [ add-breakpoint , \ break , ] }
                 { [ dup array? ] [ add-breakpoint , \ break , ] }
                 { [ dup word? ] [ literalize , \ (step-into-execute) , ] }
-                { [ t ] [ , \ break , ] }
+                [ , \ break , ]
             } cond %
         ] [ ] make
     ] change-frame ;
index 81628684bc0349fd8f7514ea741f324f9e747cd3..2fa3efcf7bf440a201777c1898bdd55b4479c7a7 100755 (executable)
@@ -29,7 +29,7 @@ TUPLE: avl-node balance ;
     avl-node-balance {
         { [ dup zero? ] [ 2drop 0 0 ] }
         { [ over = ] [ neg 0 ] }
-        { [ t ] [ 0 swap ] }
+        [ 0 swap ]
     } cond ;
 
 : double-rotate ( node -- node )
@@ -89,7 +89,7 @@ M: avl set-at ( value key node -- node )
     current-side get over avl-node-balance {
         { [ dup zero? ] [ drop neg over set-avl-node-balance f ] }
         { [ dupd = ] [ drop 0 over set-avl-node-balance t ] }
-        { [ t ] [ dupd neg change-balance rebalance-delete ] }
+        [ dupd neg change-balance rebalance-delete ]
     } cond ;
 
 : avl-replace-with-extremity ( to-replace node -- node shorter? )
index e59bbab1ed69aa5694e1cad1df54b0ee97f65e94..1648eeec3242d0818fcf8e62beb8fbdf11c81d1a 100755 (executable)
@@ -112,7 +112,7 @@ M: tree set-at ( value key tree -- )
           [ 2drop t ] }
         { [ >r 2nip r> [ tree-call ] 2keep rot ]
           [ drop [ node-key ] keep node-value t ] }
-        { [ t ] [ >r node-right r> find-node ] }
+        [ >r node-right r> find-node ]
     } cond ; inline
 
 M: tree-mixin assoc-find ( tree quot -- key value ? )
index 7e649b7ff7969e6088bb427720b5a17435f772b9..978e5d48e238c942ef9d741573307b0ff6dcde69 100755 (executable)
@@ -55,7 +55,7 @@ C: <button-paint> button-paint
         { [ dup button-pressed? ] [ drop button-paint-pressed ] }
         { [ dup button-selected? ] [ drop button-paint-selected ] }
         { [ dup button-rollover? ] [ drop button-paint-rollover ] }
-        { [ t ] [ drop button-paint-plain ] }
+        [ drop button-paint-plain ]
     } cond ;
 
 M: button-paint draw-interior
diff --git a/extra/ui/gadgets/frame-buffer/frame-buffer.factor b/extra/ui/gadgets/frame-buffer/frame-buffer.factor
new file mode 100644 (file)
index 0000000..4990254
--- /dev/null
@@ -0,0 +1,113 @@
+
+USING: kernel alien.c-types combinators sequences splitting
+       opengl.gl ui.gadgets ui.render
+       math math.vectors accessors ;
+
+IN: ui.gadgets.frame-buffer
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+TUPLE: frame-buffer action dim last-dim graft ungraft pixels ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: init-frame-buffer-pixels ( frame-buffer -- frame-buffer )
+  dup
+    rect-dim product "uint[4]" <c-array>
+  >>pixels ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: <frame-buffer> ( -- frame-buffer )
+  frame-buffer construct-gadget
+    [ ]         >>action
+    { 100 100 } >>dim
+    [ ]         >>graft
+    [ ]         >>ungraft ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: draw-pixels ( fb -- fb )
+  dup >r
+  dup >r
+  rect-dim first2 GL_RGBA GL_UNSIGNED_INT r> pixels>> glDrawPixels
+  r> ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: read-pixels ( fb -- fb )
+  dup >r
+  dup >r
+      >r
+  0 0 r> rect-dim first2 GL_RGBA GL_UNSIGNED_INT r> pixels>> glReadPixels
+  r> ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+M: frame-buffer pref-dim* dim>> ;
+M: frame-buffer graft*    graft>>   call ;
+M: frame-buffer ungraft*  ungraft>> call ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: copy-row ( old new -- )
+  2dup min-length swap >r head-slice 0 r> copy ;
+
+! : copy-pixels ( old-pixels old-width new-pixels new-width -- )
+!   [ group ] 2bi@
+!   [ copy-row ] 2each ;
+
+! : copy-pixels ( old-pixels old-width new-pixels new-width -- )
+!   [ 16 * group ] 2bi@
+!   [ copy-row ] 2each ;
+
+: copy-pixels ( old-pixels old-width new-pixels new-width -- )
+  [ 16 * <sliced-groups> ] 2bi@
+  [ copy-row ] 2each ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+M: frame-buffer layout* ( fb -- )
+   {
+     {
+       [ dup last-dim>> f = ]
+       [
+         init-frame-buffer-pixels
+         dup
+           rect-dim >>last-dim
+         drop
+       ]
+     }
+     {
+       [ dup [ rect-dim ] [ last-dim>> ] bi = not ]
+       [
+         dup [ pixels>> ] [ last-dim>> first ] bi
+
+         rot init-frame-buffer-pixels
+         dup rect-dim >>last-dim
+
+         [ pixels>> ] [ rect-dim first ] bi
+
+         copy-pixels
+       ]
+     }
+     { [ t ] [ drop ] }
+   }
+   cond ;
+   
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+M: frame-buffer draw-gadget* ( fb -- )
+
+   dup rect-dim { 0 1 } v* first2 glRasterPos2i
+
+   draw-pixels
+
+   dup action>> call
+
+   glFlush
+
+   read-pixels
+
+   drop ;
+
index c4f11f2e87b8a458c1d94c26c3934b87a8d4fcda..f4e5ca2a469386b453aa715f1d424b119df3f1c3 100755 (executable)
@@ -378,7 +378,7 @@ SYMBOL: in-layout?
     {
         { [ 2dup eq? ] [ 2drop t ] }
         { [ dup not ] [ 2drop f ] }
-        { [ t ] [ gadget-parent child? ] }
+        [ gadget-parent child? ]
     } cond ;
 
 GENERIC: focusable-child* ( gadget -- child/t )
@@ -396,10 +396,10 @@ M: gadget request-focus-on gadget-parent request-focus-on ;
 M: f request-focus-on 2drop ;
 
 : request-focus ( gadget -- )
-    dup focusable-child swap request-focus-on ;
+    [ focusable-child ] keep request-focus-on ;
 
 : focus-path ( world -- seq )
-    [ gadget-parent ] follow ;
+    [ gadget-focus ] follow ;
 
 : make-gadget ( quot gadget -- gadget )
     [ \ make-gadget rot with-variable ] keep ; inline
index e3f6e36050d6859f3e99eaa36d17ae9285bdf107..0263b15d71c1a2d4f0f4a1ef1358e99917d13928 100755 (executable)
@@ -1,8 +1,8 @@
 IN: ui.gadgets.panes.tests
 USING: alien ui.gadgets.panes ui.gadgets namespaces
-kernel sequences io io.streams.string tools.test prettyprint
-definitions help help.syntax help.markup splitting
-tools.test.ui models ;
+kernel sequences io io.styles io.streams.string tools.test
+prettyprint definitions help help.syntax help.markup
+help.stylesheet splitting tools.test.ui models math inspector ;
 
 : #children "pane" get gadget-children length ;
 
@@ -17,20 +17,79 @@ tools.test.ui models ;
 [ t ] [ #children "num-children" get = ] unit-test
 
 : test-gadget-text
-    dup make-pane gadget-text
-    swap with-string-writer "\n" ?tail drop "\n" ?tail drop = ;
+    dup make-pane gadget-text dup print "======" print
+    swap with-string-writer dup print "\n" ?tail drop "\n" ?tail drop = ;
 
 [ t ] [ [ "hello" write ] test-gadget-text ] unit-test
 [ t ] [ [ "hello" pprint ] test-gadget-text ] unit-test
+[ t ] [
+    [
+        H{ { wrap-margin 100 } } [ "hello" pprint ] with-nesting
+    ] test-gadget-text
+] unit-test
+[ t ] [
+    [
+        H{ { wrap-margin 100 } } [
+            H{ } [
+                "hello" pprint
+            ] with-style
+        ] with-nesting
+    ] test-gadget-text
+] unit-test
 [ t ] [ [ [ 1 2 3 ] pprint ] test-gadget-text ] unit-test
+[ t ] [ [ \ + describe ] test-gadget-text ] unit-test
 [ t ] [ [ \ = see ] test-gadget-text ] unit-test
 [ t ] [ [ \ = help ] test-gadget-text ] unit-test
 
-ARTICLE: "test-article" "This is a test article"
+[ t ] [
+    [
+        title-style get [
+                "Hello world" write
+        ] with-style
+    ] test-gadget-text
+] unit-test
+
+
+[ t ] [
+    [
+        title-style get [
+                "Hello world" write
+        ] with-nesting
+    ] test-gadget-text
+] unit-test
+
+[ t ] [
+    [
+        title-style get [
+            title-style get [
+                "Hello world" write
+            ] with-nesting
+        ] with-style
+    ] test-gadget-text
+] unit-test
+
+[ t ] [
+    [
+        title-style get [
+            title-style get [
+                [ "Hello world" write ] ($block)
+            ] with-nesting
+        ] with-style
+    ] test-gadget-text
+] unit-test
+
+ARTICLE: "test-article-1" "This is a test article"
+"Hello world, how are you today." ;
+
+[ t ] [ [ "test-article-1" $title ] test-gadget-text ] unit-test
+
+[ t ] [ [ "test-article-1" help ] test-gadget-text ] unit-test
+
+ARTICLE: "test-article-2" "This is a test article"
 "Hello world, how are you today."
 { $table { "a" "b" } { "c" "d" } } ;
 
-[ t ] [ [ "test-article" help ] test-gadget-text ] unit-test
+[ t ] [ [ "test-article-2" help ] test-gadget-text ] unit-test
 
 <pane> [ \ = see ] with-pane
 <pane> [ \ = help ] with-pane
index 91b7f0f2250ccb89402528d5d7653ffddb044492..439e93818672bc1fe63dc051c63996316e40a87f 100755 (executable)
@@ -88,7 +88,7 @@ C: <pane-stream> pane-stream
     dup gadget-children {
         { [ dup empty? ] [ 2drop "" <label> ] }
         { [ dup length 1 = ] [ nip first ] }
-        { [ t ] [ drop ] }
+        [ drop ]
     } cond ;
 
 : smash-pane ( pane -- gadget ) pane-output smash-line ;
@@ -166,7 +166,7 @@ M: pane-stream dispose drop ;
 M: pane-stream stream-flush drop ;
 
 M: pane-stream make-span-stream
-    <style-stream> <ignore-close-stream> ;
+    swap <style-stream> <ignore-close-stream> ;
 
 ! Character styles
 
index d4a189589438e520b91bc81f138ca04505af5a1e..396a494ef3a4dd6bde55a94c4884497412c9e81e 100755 (executable)
@@ -119,7 +119,7 @@ scroller H{
         { [ dup t eq? ] [ drop (scroll>bottom) ] }
         { [ dup rect? ] [ swap (scroll>rect) ] }
         { [ dup ] [ swap (scroll>gadget) ] }
-        { [ t ] [ drop dup scroller-value swap scroll ] }
+        [ drop dup scroller-value swap scroll ]
     } cond ;
 
 M: scroller layout*
index 412a61bcb55a690294e58cf8bd12566d35eb0ddc..7cbcbba241622228c688708fc493110b477ddfce 100755 (executable)
@@ -2,9 +2,8 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays assocs kernel math models namespaces
 sequences words strings system hashtables math.parser
-math.vectors classes.tuple classes ui.gadgets combinators.lib
-boxes
-calendar alarms symbols ;
+math.vectors classes.tuple classes ui.gadgets boxes
+calendar alarms symbols combinators ;
 IN: ui.gestures
 
 : set-gestures ( class hash -- ) "gestures" set-word-prop ;
@@ -188,11 +187,12 @@ SYMBOL: drag-timer
 
 : multi-click? ( button -- ? )
     {
-        [ multi-click-timeout? ]
-        [ multi-click-button? ]
-        [ multi-click-position? ]
-        [ multi-click-position? ]
-    } && nip ;
+        { [ multi-click-timeout?  not ] [ f ] }
+        { [ multi-click-button?   not ] [ f ] }
+        { [ multi-click-position? not ] [ f ] }
+        { [ multi-click-position? not ] [ f ] }
+        [ t ]
+    } cond nip ;
 
 : update-click# ( button -- )
     global [
index 152b1bff44535abdc7cd2af3956a6a22ded59a0e..cacd0a8d3ac89e6d086db3441a74d2a267faceba 100644 (file)
@@ -80,7 +80,7 @@ DEFER: draw-gadget
     {
         { [ dup gadget-visible? not ] [ drop ] }
         { [ dup gadget-clipped? not ] [ (draw-gadget) ] }
-        { [ t ] [ [ (draw-gadget) ] with-clipping ] }
+        [ [ (draw-gadget) ] with-clipping ]
     } cond ;
 
 ! Pen paint properties
index fe0a6542177994c847b5cb85d87b36762c8c9d41..94953f9c72b6a0710433b4d1f9a83e2d073b25b0 100755 (executable)
@@ -1,4 +1,27 @@
 IN: ui.tools.interactor.tests
-USING: ui.tools.interactor tools.test ;
+USING: ui.tools.interactor ui.gadgets.panes namespaces
+ui.gadgets.editors concurrency.promises threads listener
+tools.test kernel calendar ;
 
 \ <interactor> must-infer
+
+[ ] [ <pane> <pane-stream> <interactor> "interactor" set ] unit-test
+
+[ ] [ "[ 1 2 3" "interactor" get set-editor-string ] unit-test
+
+[ ] [ <promise> "promise" set ] unit-test
+
+[
+    "interactor" get stream-read-quot "promise" get fulfill
+] "Interactor test" spawn drop
+
+! This should not throw an exception
+[ ] [ "interactor" get evaluate-input ] unit-test
+
+[ ] [ [ "interactor" get interactor-busy? ] [ yield ] [ ] while ] unit-test
+
+[ ] [ "[ 1 2 3 ]" "interactor" get set-editor-string ] unit-test
+
+[ ] [ "interactor" get evaluate-input ] unit-test
+
+[ [ [ 1 2 3 ] ] ] [ "promise" get 5 seconds ?promise-timeout ] unit-test
index 06fc3c87a0c2778254ba87d76d121dac0a6761b6..3837ce2de164f73575c62f0da2f5cfbd0d7c769c 100755 (executable)
@@ -3,10 +3,11 @@
 USING: arrays assocs combinators continuations documents
  hashtables io io.styles kernel math
 math.vectors models namespaces parser prettyprint quotations
-sequences sequences.lib strings threads listener
+sequences strings threads listener
 classes.tuple ui.commands ui.gadgets ui.gadgets.editors
 ui.gadgets.presentations ui.gadgets.worlds ui.gestures
-definitions boxes calendar concurrency.flags ui.tools.workspace ;
+definitions boxes calendar concurrency.flags ui.tools.workspace
+accessors ;
 IN: ui.tools.interactor
 
 TUPLE: interactor history output flag thread help ;
@@ -104,7 +105,8 @@ M: interactor model-changed
     ] curry "input" suspend ;
 
 M: interactor stream-readln
-    [ interactor-yield ] keep interactor-finish ?first ;
+    [ interactor-yield ] keep interactor-finish
+    dup [ first ] when ;
 
 : interactor-call ( quot interactor -- )
     dup interactor-busy? [
@@ -123,12 +125,12 @@ M: interactor stream-read-partial
     stream-read ;
 
 : go-to-error ( interactor error -- )
-    dup parse-error-line 1- swap parse-error-col 2array
+    [ line>> 1- ] [ column>> ] bi 2array
     over set-caret
     mark>caret ;
 
 : handle-parse-error ( interactor error -- )
-    dup parse-error? [ 2dup go-to-error delegate ] when
+    dup parse-error? [ 2dup go-to-error error>> ] when
     swap find-workspace debugger-popup ;
 
 : try-parse ( lines interactor -- quot/error/f )
@@ -136,24 +138,26 @@ M: interactor stream-read-partial
         drop parse-lines-interactive
     ] [
         2nip
-        dup delegate unexpected-eof? [ drop f ] when
+        dup parse-error? [
+            dup error>> unexpected-eof? [ drop f ] when
+        ] when
     ] recover ;
 
 : handle-interactive ( lines interactor -- quot/f ? )
     tuck try-parse {
         { [ dup quotation? ] [ nip t ] }
         { [ dup not ] [ drop "\n" swap user-input f f ] }
-        { [ t ] [ handle-parse-error f f ] }
+        [ handle-parse-error f f ]
     } cond ;
 
 M: interactor stream-read-quot
     [ interactor-yield ] keep {
         { [ over not ] [ drop ] }
         { [ over callable? ] [ drop ] }
-        { [ t ] [
+        [
             [ handle-interactive ] keep swap
             [ interactor-finish ] [ nip stream-read-quot ] if
-        ] }
+        ]
     } cond ;
 
 M: interactor pref-dim*
index 13ce834df30f35cfd0895d6526b6261e2a107cea..cc218533d818996eda0eb82f75749d0e152f24bd 100755 (executable)
@@ -2,7 +2,7 @@ USING: continuations documents ui.tools.interactor
 ui.tools.listener hashtables kernel namespaces parser sequences
 tools.test ui.commands ui.gadgets ui.gadgets.editors
 ui.gadgets.panes vocabs words tools.test.ui slots.private
-threads ;
+threads arrays generic ;
 IN: ui.tools.listener.tests
 
 [ f ] [ "word" source-editor command-map empty? ] unit-test
@@ -13,11 +13,11 @@ IN: ui.tools.listener.tests
 
 "listener" get [
     [ "dup" ] [
-        \ dup "listener" get word-completion-string
+        \ dup word-completion-string
     ] unit-test
 
-    [ "USE: slots.private slot" ]
-    [ \ slot "listener" get word-completion-string ] unit-test
+    [ "equal?" ]
+    [ \ array \ equal? method word-completion-string ] unit-test
 
     <pane> <interactor> "i" set
 
index 7db0d63f45da367723fdcb8c622d91c06ca2b159..b900737e505a794d11088cacbf63f0490dbe79e4 100755 (executable)
@@ -1,4 +1,4 @@
-! Copyright (C) 2005, 2007 Slava Pestov.
+! Copyright (C) 2005, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: inspector ui.tools.interactor ui.tools.inspector
 ui.tools.workspace help.markup io io.streams.duplex io.styles
@@ -7,7 +7,7 @@ ui.gadgets ui.gadgets.editors ui.gadgets.labelled
 ui.gadgets.panes ui.gadgets.buttons ui.gadgets.scrollers
 ui.gadgets.tracks ui.gestures ui.operations vocabs words
 prettyprint listener debugger threads boxes concurrency.flags
-math arrays ;
+math arrays generic accessors combinators ;
 IN: ui.tools.listener
 
 TUPLE: listener-gadget input output stack ;
@@ -101,16 +101,32 @@ M: listener-operation invoke-command ( target command -- )
 : clear-stack ( listener -- )
     [ clear ] swap (call-listener) ;
 
-: word-completion-string ( word listener -- string )
-    >r dup word-name swap word-vocabulary dup vocab-words r>
-    listener-gadget-input interactor-use memq?
-    [ drop ] [ [ "USE: " % % " " % % ] "" make ] if ;
+GENERIC: word-completion-string ( word -- string )
+
+M: word word-completion-string
+    word-name ;
+
+M: method-body word-completion-string
+    "method-generic" word-prop word-completion-string ;
+
+USE: generic.standard.engines.tuple
+
+M: tuple-dispatch-engine-word word-completion-string
+    "engine-generic" word-prop word-completion-string ;
+
+: use-if-necessary ( word seq -- )
+    >r word-vocabulary vocab-words r>
+    {
+        { [ dup not ] [ 2drop ] }
+        { [ 2dup memq? ] [ 2drop ] }
+        [ push ]
+    } cond ;
 
 : insert-word ( word -- )
-    get-workspace
-    workspace-listener
-    [ word-completion-string ] keep
-    listener-gadget-input user-input ;
+    get-workspace workspace-listener input>>
+    [ >r word-completion-string r> user-input ]
+    [ interactor-use use-if-necessary ]
+    2bi ;
 
 : quot-action ( interactor -- lines )
     dup control-value
index dbd2ce15ac2299aecc6bc4c4055e83779ca43a56..42d0688ae7d223a4eb375bdd382be669377c559d 100755 (executable)
@@ -81,7 +81,7 @@ walker-gadget "toolbar" f {
     {
         { [ dup walker-gadget? not ] [ 2drop f ] }
         { [ dup walker-gadget-closing? ] [ 2drop f ] }
-        { [ t ] [ walker-gadget-thread eq? ] }
+        [ walker-gadget-thread eq? ]
     } cond ;
 
 : find-walker-window ( thread -- world/f )
index 72f1404ee5698b8208c1deec09b5b8827e7e39b8..395bca5c8a7db581f5fa61cebcc7ec1f6c54d9a5 100644 (file)
@@ -70,7 +70,7 @@ DEFER: (gadget-subtree)
         { [ pick empty? ] [ rot drop traverse-to-path ] }
         { [ over empty? ] [ nip traverse-from-path ] }
         { [ pick first pick first = ] [ traverse-child ] }
-        { [ t ] [ traverse-middle ] }
+        [ traverse-middle ]
     } cond ;
 
 : gadget-subtree ( frompath topath gadget -- seq )
index e0c9f24122d4e3b7ce297e684a439126d3410e7e..6229fc9a6555973b07c8f002c9b4590d41ceb938 100755 (executable)
@@ -7,7 +7,7 @@ vectors words windows.kernel32 windows.gdi32 windows.user32
 windows.opengl32 windows.messages windows.types windows.nt
 windows threads libc combinators continuations command-line
 shuffle opengl ui.render unicode.case ascii math.bitfields
-locals symbols ;
+locals symbols accessors ;
 IN: ui.windows
 
 SINGLETON: windows-ui-backend
@@ -203,8 +203,18 @@ SYMBOLS: msg-obj class-name-ptr mouse-captured ;
     wParam keystroke>gesture <key-up>
     hWnd window-focus send-gesture drop ;
 
+: set-window-active ( hwnd uMsg wParam lParam ? -- n )
+    >r 4dup r> 2nip nip
+    swap window set-world-active? DefWindowProc ;
+
 : handle-wm-syscommand ( hWnd uMsg wParam lParam -- n )
-    dup alpha? [ 4drop 0 ] [ DefWindowProc ] if ;
+    {
+        { [ over SC_MINIMIZE = ] [ f set-window-active ] }
+        { [ over SC_RESTORE = ] [ t set-window-active ] }
+        { [ over SC_MAXIMIZE = ] [ t set-window-active ] }
+        { [ dup alpha? ] [ 4drop 0 ] }
+        { [ t ] [ DefWindowProc ] }
+    } cond ;
 
 : cleanup-window ( handle -- )
     dup win-title [ free ] when*
@@ -381,11 +391,11 @@ SYMBOL: trace-messages?
         { [ windows get empty? ] [ drop ] }
         { [ dup peek-message? ] [ ui-wait event-loop ] }
         { [ dup MSG-message WM_QUIT = ] [ drop ] }
-        { [ t ] [
+        [
             dup TranslateMessage drop
             dup DispatchMessage drop
             event-loop
-        ] }
+        ]
     } cond ;
 
 : register-wndclassex ( -- class )
index 94454866561e008e51f1777a6fca048603580742..c04427185390bed4441730d029297eb76f9f1afa 100755 (executable)
@@ -4,8 +4,9 @@ USING: alien alien.c-types arrays ui ui.gadgets ui.gestures
 ui.backend ui.clipboards ui.gadgets.worlds assocs kernel math
 namespaces opengl sequences strings x11.xlib x11.events x11.xim
 x11.glx x11.clipboard x11.constants x11.windows io.encodings.string
-io.encodings.utf8 combinators debugger system command-line
+io.encodings.utf8 combinators debugger command-line qualified
 ui.render math.vectors classes.tuple opengl.gl threads ;
+QUALIFIED: system
 IN: ui.x11
 
 SINGLETON: x11-ui-backend
@@ -132,7 +133,7 @@ M: world selection-notify-event
     {
         { [ dup XA_PRIMARY = ] [ drop selection get ] }
         { [ dup XA_CLIPBOARD = ] [ drop clipboard get ] }
-        { [ t ] [ drop <clipboard> ] }
+        [ drop <clipboard> ]
     } cond ;
 
 : encode-clipboard ( string type -- bytes )
@@ -155,7 +156,7 @@ M: world selection-request-event
         { [ dup supported-type? ] [ drop dup set-selection-prop send-notify-success ] }
         { [ dup "TARGETS" x-atom = ] [ drop dup set-targets-prop send-notify-success ] }
         { [ dup "TIMESTAMP" x-atom = ] [ drop dup set-timestamp-prop send-notify-success ] }
-        { [ t ] [ drop send-notify-failure ] }
+        [ drop send-notify-failure ]
     } cond ;
 
 M: x11-ui-backend (close-window) ( handle -- )
@@ -261,5 +262,5 @@ M: x11-ui-backend ui ( -- )
 
 x11-ui-backend ui-backend set-global
 
-[ "DISPLAY" os-env "ui" "listener" ? ]
+[ "DISPLAY" system:os-env "ui" "listener" ? ]
 main-vocab-hook set-global
index 4c8c6491cabd6c32e66da124ba702b97da683b40..54bf766f52753dd272d575502d2c04176c61613c 100644 (file)
@@ -1,6 +1,6 @@
 USING: unicode.categories kernel math combinators splitting
 sequences math.parser io.files io assocs arrays namespaces
-combinators.lib assocs.lib math.ranges unicode.normalize
+math.ranges unicode.normalize
 unicode.syntax unicode.data compiler.units alien.syntax io.encodings.ascii ;
 IN: unicode.breaks
 
@@ -27,7 +27,7 @@ CATEGORY: grapheme-control Zl Zp Cc Cf ;
     [ "#" split1 drop ";" split1 drop trim-blank ] map
     [ empty? not ] subset
     [ ".." split1 [ dup ] unless* [ hex> ] bi@ [a,b] ] map
-    concat >set ;
+    concat [ dup ] H{ } map>assoc ;
 
 : other-extend-lines ( -- lines )
     "extra/unicode/PropList.txt" resource-path ascii file-lines ;
@@ -36,14 +36,14 @@ VALUE: other-extend
 
 CATEGORY: (extend) Me Mn ;
 : extend? ( ch -- ? )
-    [ (extend)? ] [ other-extend key? ] either ;
+    dup (extend)? [ ] [ other-extend key? ] ?if ;
 
 : grapheme-class ( ch -- class )
     {
         { [ dup jamo? ] [ jamo-class ] }
         { [ dup grapheme-control? ] [ control-class ] }
         { [ extend? ] [ Extend ] }
-        { [ t ] [ Any ] }
+        [ Any ]
     } cond ;
 
 : init-grapheme-table ( -- table )
index 092a2472048d3e611f75713761cf79120b4dd0cf..d0506a6a46f42295bb5d1a336822d9ba58de0aa9 100755 (executable)
@@ -1,8 +1,10 @@
 USING: kernel unicode.data sequences sequences.next namespaces
-assocs.lib unicode.normalize math unicode.categories combinators
+unicode.normalize math unicode.categories combinators
 assocs strings splitting ;
 IN: unicode.case
 
+: at-default ( key assoc -- value/key ) over >r at r> or ;
+
 : ch>lower ( ch -- lower ) simple-lower at-default ;
 : ch>upper ( ch -- upper ) simple-upper at-default ;
 : ch>title ( ch -- title ) simple-title at-default ;
@@ -49,7 +51,7 @@ SYMBOL: locale ! Just casing locale, or overall?
             drop dot-over =
             dup CHAR: i HEX: 131 ? ,
         ] }
-        { [ t ] [ , drop f ] }
+        [ , drop f ]
     } cond ;
 
 : turk>lower ( string -- lower-i )
index d8e1e8937a9220b7aa60bedf3ac62f511d2414d7..ba9c0370cce4e1f4a5d871dbf894cd175dc907c1 100755 (executable)
@@ -1,5 +1,5 @@
 USING: assocs math kernel sequences io.files hashtables
-quotations splitting arrays math.parser combinators.lib hash2
+quotations splitting arrays math.parser hash2
 byte-arrays words namespaces words compiler.units parser io.encodings.ascii  ;
 IN: unicode.data
 
@@ -44,7 +44,7 @@ IN: unicode.data
     dup [ swap (chain-decomposed) ] curry assoc-map ;
 
 : first* ( seq -- ? )
-    second [ empty? ] [ first ] either ;
+    second dup empty? [ ] [ first ] ?if ;
 
 : (process-decomposed) ( data -- alist )
     5 swap (process-data)
index d62beb1a2cc0498c7680cb74978ebe0dad7b6627..951430b2b5c246d4e58e6b52649f08a5681ac25f 100644 (file)
@@ -1,5 +1,4 @@
-USING: sequences namespaces unicode.data kernel combinators.lib
-math arrays ;
+USING: sequences namespaces unicode.data kernel math arrays ;
 IN: unicode.normalize
 
 ! Conjoining Jamo behavior
@@ -19,7 +18,7 @@ IN: unicode.normalize
 
 ! These numbers come from UAX 29
 : initial? ( ch -- ? )
-    [ HEX: 1100 HEX: 1159 ?between? ] [ HEX: 115F = ] either ;
+    dup HEX: 1100 HEX: 1159 ?between? [ ] [ HEX: 115F = ] ?if ;
 : medial? ( ch -- ? ) HEX: 1160 HEX: 11A2 ?between? ;
 : final? ( ch -- ? ) HEX: 11A8 HEX: 11F9 ?between? ;
 
diff --git a/extra/unionfind/authors.txt b/extra/unionfind/authors.txt
new file mode 100644 (file)
index 0000000..16e1588
--- /dev/null
@@ -0,0 +1 @@
+Eric Mertens
diff --git a/extra/unionfind/summary.txt b/extra/unionfind/summary.txt
new file mode 100644 (file)
index 0000000..c282cc2
--- /dev/null
@@ -0,0 +1 @@
+A efficient implementation of a disjoint-set datastructure
diff --git a/extra/unionfind/unionfind.factor b/extra/unionfind/unionfind.factor
new file mode 100644 (file)
index 0000000..1f0d8be
--- /dev/null
@@ -0,0 +1,71 @@
+USING: accessors arrays combinators kernel math sequences namespaces ;
+
+IN: unionfind
+
+<PRIVATE
+
+TUPLE: unionfind parents ranks counts ;
+
+SYMBOL: uf
+
+: count ( a -- n )
+    uf get counts>> nth ;
+
+: add-count ( p a -- )
+    count [ + ] curry uf get counts>> swap change-nth ;
+
+: parent ( a -- p )
+    uf get parents>> nth ;
+
+: set-parent ( p a -- )
+    uf get parents>> set-nth ;
+
+: link-sets ( p a -- )
+    [ set-parent ]
+    [ add-count ] 2bi ;
+
+: rank ( a -- r )
+    uf get ranks>> nth ;
+
+: inc-rank ( a -- )
+    uf get ranks>> [ 1+ ] change-nth ;
+
+: topparent ( a -- p )
+    [ parent ] keep
+    2dup = [
+        [ topparent ] dip
+        2dup set-parent
+    ] unless drop ;
+
+PRIVATE>
+
+: <unionfind> ( n -- unionfind )
+    [ >array ]
+    [ 0 <array> ]
+    [ 1 <array> ] tri
+    unionfind construct-boa ;
+
+: equiv-set-size ( a uf -- n )
+    uf [ topparent count ] with-variable ;
+
+: equiv? ( a b uf -- ? )
+    uf [ [ topparent ] bi@ = ] with-variable ;
+
+: equate ( a b uf -- )
+    uf [
+        [ topparent ] bi@
+        2dup [ rank ] compare sgn
+        {
+            { -1 [ swap link-sets ] }
+            {  1 [ link-sets ] }
+            {  0 [
+                    2dup =
+                    [ 2drop ]
+                    [
+                        [ link-sets ]
+                        [ drop inc-rank ] 2bi
+                    ] if
+                 ]
+            }
+        } case
+    ] with-variable ;
index 342047d9aff7defe329b00e649e230729362e0cb..cb1c93987888ef86fb8be22d9141fb890a219c1c 100644 (file)
@@ -10,23 +10,13 @@ IN: unix.stat
 
 : S_IFMT   OCT: 170000 ; ! These bits determine file type.
 
-: S_IFDIR  OCT:  40000 ;    ! Directory.
-: S_IFCHR  OCT:  20000 ;    ! Character device.
-: S_IFBLK  OCT:  60000 ;    ! Block device.
-: S_IFREG  OCT: 100000 ;    ! Regular file.
-: S_IFIFO  OCT: 010000 ;    ! FIFO.
-: S_IFLNK  OCT: 120000 ;    ! Symbolic link.
-: S_IFSOCK OCT: 140000 ;    ! Socket.
-
-: S_ISTYPE ( mode mask -- val ) >r S_IFMT bitand r> = ;
-
-: S_ISREG  ( mode -- value ) S_IFREG S_ISTYPE ;
-: S_ISDIR  ( mode -- value ) S_IFDIR S_ISTYPE ;
-: S_ISCHR  ( mode -- value ) S_IFCHR S_ISTYPE ;
-: S_ISBLK  ( mode -- value ) S_IFBLK S_ISTYPE ;
-: S_ISFIFO ( mode -- value ) S_IFIFO S_ISTYPE ;
-: S_ISLNK  ( mode -- value ) S_IFLNK S_ISTYPE ;
-: S_ISSOCK ( mode -- value ) S_IFSOCK S_ISTYPE ;
+: S_IFDIR  OCT:  40000 ; inline   ! Directory.
+: S_IFCHR  OCT:  20000 ; inline   ! Character device.
+: S_IFBLK  OCT:  60000 ; inline   ! Block device.
+: S_IFREG  OCT: 100000 ; inline   ! Regular file.
+: S_IFIFO  OCT: 010000 ; inline   ! FIFO.
+: S_IFLNK  OCT: 120000 ; inline   ! Symbolic link.
+: S_IFSOCK OCT: 140000 ; inline   ! Socket.
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 ! File Access Permissions
index e911a5c039a40002d6c9d025a65044192bc2e37d..9005cd2b2acecc7b2aa74e81317a326cd0b130b1 100755 (executable)
@@ -43,6 +43,9 @@ FUNCTION: int dup2 ( int oldd, int newd ) ;
 FUNCTION: int execv ( char* path, char** argv ) ;
 FUNCTION: int execvp ( char* path, char** argv ) ;
 FUNCTION: int execve ( char* path, char** argv, char** envp ) ;
+: _exit ( status -- * )
+    #! We throw to give this a terminating stack effect.
+    "int" f "_exit" { "int" } alien-invoke "Exit failed" throw ;
 FUNCTION: int fchdir ( int fd ) ;
 FUNCTION: int fchown ( int fd, uid_t owner, gid_t group ) ;
 FUNCTION: int fcntl ( int fd, int cmd, int arg ) ;
index 28091d3d9db64feb7d578fe7fb12084d2f23915c..0d2f164c8de520244ae0fbcc039a208cec3a8acc 100644 (file)
@@ -61,6 +61,133 @@ LIBRARY: advapi32
 : CRYPT_MACHINE_KEYSET HEX: 20 ; inline
 : CRYPT_SILENT         HEX: 40 ; inline
 
+C-STRUCT: ACL
+    { "BYTE" "AclRevision" }
+    { "BYTE" "Sbz1" }
+    { "WORD" "AclSize" }
+    { "WORD" "AceCount" }
+    { "WORD" "Sbz2" } ;
+
+TYPEDEF: ACL* PACL
+
+: ACCESS_ALLOWED_ACE_TYPE 0 ; inline
+: ACCESS_DENIED_ACE_TYPE 1 ; inline
+: SYSTEM_AUDIT_ACE_TYPE 2 ; inline
+: SYSTEM_ALARM_ACE_TYPE 3 ; inline
+
+: OBJECT_INHERIT_ACE HEX: 1 ; inline
+: CONTAINER_INHERIT_ACE HEX: 2 ; inline
+: NO_PROPAGATE_INHERIT_ACE HEX: 4 ; inline
+: INHERIT_ONLY_ACE HEX: 8 ; inline
+: VALID_INHERIT_FLAGS HEX: f ; inline
+
+C-STRUCT: ACE_HEADER
+    { "BYTE" "AceType" }
+    { "BYTE" "AceFlags" }
+    { "WORD" "AceSize" } ;
+
+TYPEDEF: ACE_HEADER* PACE_HEADER
+
+C-STRUCT: ACCESS_ALLOWED_ACE
+    { "ACE_HEADER" "Header" }
+    { "DWORD" "Mask" }
+    { "DWORD" "SidStart" } ;
+
+TYPEDEF: ACCESS_ALLOWED_ACE* PACCESS_ALLOWED_ACE
+
+C-STRUCT: ACCESS_DENIED_ACE
+    { "ACE_HEADER" "Header" }
+    { "DWORD" "Mask" }
+    { "DWORD" "SidStart" } ;
+TYPEDEF: ACCESS_DENIED_ACE* PACCESS_DENIED_ACE
+
+
+C-STRUCT: SYSTEM_AUDIT_ACE
+    { "ACE_HEADER" "Header" }
+    { "DWORD" "Mask" }
+    { "DWORD" "SidStart" } ;
+
+TYPEDEF: SYSTEM_AUDIT_ACE* PSYSTEM_AUDIT_ACE
+
+C-STRUCT: SYSTEM_ALARM_ACE
+    { "ACE_HEADER" "Header" }
+    { "DWORD" "Mask" }
+    { "DWORD" "SidStart" } ;
+
+TYPEDEF: SYSTEM_ALARM_ACE* PSYSTEM_ALARM_ACE
+
+C-STRUCT: ACCESS_ALLOWED_CALLBACK_ACE
+    { "ACE_HEADER" "Header" }
+    { "DWORD" "Mask" }
+    { "DWORD" "SidStart" } ;
+
+TYPEDEF: ACCESS_ALLOWED_CALLBACK_ACE* PACCESS_ALLOWED_CALLBACK_ACE
+
+
+! typedef enum _TOKEN_INFORMATION_CLASS {
+: TokenUser 1 ; inline
+: TokenGroups 2 ; inline
+: TokenPrivileges 3 ; inline
+: TokenOwner 4 ; inline
+: TokenPrimaryGroup 5 ; inline
+: TokenDefaultDacl 6 ; inline
+: TokenSource 7 ; inline
+: TokenType 8 ; inline
+: TokenImpersonationLevel 9 ; inline
+: TokenStatistics 10 ; inline
+: TokenRestrictedSids 11 ; inline
+: TokenSessionId 12 ; inline
+: TokenGroupsAndPrivileges 13 ; inline
+: TokenSessionReference 14 ; inline
+: TokenSandBoxInert 15 ; inline
+! } TOKEN_INFORMATION_CLASS;
+
+: DELETE                     HEX: 00010000 ; inline
+: READ_CONTROL               HEX: 00020000 ; inline
+: WRITE_DAC                  HEX: 00040000 ; inline
+: WRITE_OWNER                HEX: 00080000 ; inline
+: SYNCHRONIZE                HEX: 00100000 ; inline
+: STANDARD_RIGHTS_REQUIRED   HEX: 000f0000 ; inline
+
+: STANDARD_RIGHTS_READ       READ_CONTROL ; inline
+: STANDARD_RIGHTS_WRITE      READ_CONTROL ; inline
+: STANDARD_RIGHTS_EXECUTE    READ_CONTROL ; inline
+
+: TOKEN_TOKEN_ADJUST_DEFAULT   HEX: 0080 ; inline
+: TOKEN_ADJUST_GROUPS          HEX: 0040 ; inline
+: TOKEN_ADJUST_PRIVILEGES      HEX: 0020 ; inline
+: TOKEN_ADJUST_SESSIONID       HEX: 0100 ; inline
+: TOKEN_ASSIGN_PRIMARY         HEX: 0001 ; inline
+: TOKEN_DUPLICATE              HEX: 0002 ; inline
+: TOKEN_EXECUTE                STANDARD_RIGHTS_EXECUTE ; inline
+: TOKEN_IMPERSONATE            HEX: 0004 ; inline
+: TOKEN_QUERY                  HEX: 0008 ; inline
+: TOKEN_QUERY_SOURCE           HEX: 0010 ; inline
+: TOKEN_ADJUST_DEFAULT         HEX: 0080 ; inline
+: TOKEN_READ STANDARD_RIGHTS_READ TOKEN_QUERY bitor ;
+
+: TOKEN_WRITE
+    {
+        STANDARD_RIGHTS_WRITE
+        TOKEN_ADJUST_PRIVILEGES
+        TOKEN_ADJUST_GROUPS
+        TOKEN_ADJUST_DEFAULT
+    } flags ; foldable
+
+: TOKEN_ALL_ACCESS
+    {
+        STANDARD_RIGHTS_REQUIRED
+        TOKEN_ASSIGN_PRIMARY
+        TOKEN_DUPLICATE
+        TOKEN_IMPERSONATE
+        TOKEN_QUERY
+        TOKEN_QUERY_SOURCE
+        TOKEN_ADJUST_PRIVILEGES
+        TOKEN_ADJUST_GROUPS
+        TOKEN_ADJUST_SESSIONID
+        TOKEN_ADJUST_DEFAULT
+    } flags ; foldable
+
 
 ! : I_ScGetCurrentGroupStateW ;
 ! : A_SHAFinal ;
@@ -85,7 +212,7 @@ LIBRARY: advapi32
 ! : AddAccessDeniedAce ;
 ! : AddAccessDeniedAceEx ;
 ! : AddAccessDeniedObjectAce ;
-! : AddAce ;
+FUNCTION: BOOL AddAce ( PACL pAcl, DWORD dwAceRevision, DWORD dwStartingAceIndex, LPVOID pAceList, DWORD nAceListLength ) ;
 ! : AddAuditAccessAce ;
 ! : AddAuditAccessAceEx ;
 ! : AddAuditAccessObjectAce ;
@@ -382,7 +509,7 @@ FUNCTION: BOOL GetUserNameW ( LPCTSTR lpBuffer, LPDWORD lpnSize ) ;
 ! : ImpersonateLoggedOnUser ;
 ! : ImpersonateNamedPipeClient ;
 ! : ImpersonateSelf ;
-! : InitializeAcl ;
+FUNCTION: BOOL InitializeAcl ( PACL pAcl, DWORD nAclLength, DWORD dwAclRevision ) ;
 ! : InitializeSecurityDescriptor ;
 ! : InitializeSid ;
 ! : InitiateSystemShutdownA ;
@@ -508,70 +635,6 @@ FUNCTION: BOOL LookupPrivilegeValueW ( LPCTSTR lpSystemName,
 ! : OpenEventLogA ;
 ! : OpenEventLogW ;
 
-! typedef enum _TOKEN_INFORMATION_CLASS {
-: TokenUser 1 ;
-: TokenGroups 2 ;
-: TokenPrivileges 3 ;
-: TokenOwner 4 ;
-: TokenPrimaryGroup 5 ;
-: TokenDefaultDacl 6 ;
-: TokenSource 7 ;
-: TokenType 8 ;
-: TokenImpersonationLevel 9 ;
-: TokenStatistics 10 ;
-: TokenRestrictedSids 11 ;
-: TokenSessionId 12 ;
-: TokenGroupsAndPrivileges 13 ;
-: TokenSessionReference 14 ;
-: TokenSandBoxInert 15 ;
-! } TOKEN_INFORMATION_CLASS;
-
-: DELETE                     HEX: 00010000 ; inline
-: READ_CONTROL               HEX: 00020000 ; inline
-: WRITE_DAC                  HEX: 00040000 ; inline
-: WRITE_OWNER                HEX: 00080000 ; inline
-: SYNCHRONIZE                HEX: 00100000 ; inline
-: STANDARD_RIGHTS_REQUIRED   HEX: 000f0000 ; inline
-
-: STANDARD_RIGHTS_READ       READ_CONTROL ; inline
-: STANDARD_RIGHTS_WRITE      READ_CONTROL ; inline
-: STANDARD_RIGHTS_EXECUTE    READ_CONTROL ; inline
-
-: TOKEN_TOKEN_ADJUST_DEFAULT   HEX: 0080 ; inline
-: TOKEN_ADJUST_GROUPS          HEX: 0040 ; inline
-: TOKEN_ADJUST_PRIVILEGES      HEX: 0020 ; inline
-: TOKEN_ADJUST_SESSIONID       HEX: 0100 ; inline
-: TOKEN_ASSIGN_PRIMARY         HEX: 0001 ; inline
-: TOKEN_DUPLICATE              HEX: 0002 ; inline
-: TOKEN_EXECUTE                STANDARD_RIGHTS_EXECUTE ; inline
-: TOKEN_IMPERSONATE            HEX: 0004 ; inline
-: TOKEN_QUERY                  HEX: 0008 ; inline
-: TOKEN_QUERY_SOURCE           HEX: 0010 ; inline
-: TOKEN_ADJUST_DEFAULT         HEX: 0080 ; inline
-: TOKEN_READ STANDARD_RIGHTS_READ TOKEN_QUERY bitor ;
-
-: TOKEN_WRITE
-    {
-        STANDARD_RIGHTS_WRITE
-        TOKEN_ADJUST_PRIVILEGES
-        TOKEN_ADJUST_GROUPS
-        TOKEN_ADJUST_DEFAULT
-    } flags ; foldable
-
-: TOKEN_ALL_ACCESS
-    {
-        STANDARD_RIGHTS_REQUIRED
-        TOKEN_ASSIGN_PRIMARY
-        TOKEN_DUPLICATE
-        TOKEN_IMPERSONATE
-        TOKEN_QUERY
-        TOKEN_QUERY_SOURCE
-        TOKEN_ADJUST_PRIVILEGES
-        TOKEN_ADJUST_GROUPS
-        TOKEN_ADJUST_SESSIONID
-        TOKEN_ADJUST_DEFAULT
-    } flags ; foldable
-
 FUNCTION: BOOL OpenProcessToken ( HANDLE ProcessHandle,
                                   DWORD DesiredAccess,
                                   PHANDLE TokenHandle ) ;
index 733071d19735c6c84d309d93087355e1382b9536..3b0db96d6394857bf654b484c62c0e7bba31f8a7 100644 (file)
@@ -1001,3 +1001,25 @@ windows-messages set-global
 : LM_GETIDEALHEIGHT WM_USER  HEX: 0301 +  ; inline
 : LM_SETITEM WM_USER  HEX: 0302 + ; inline
 : LM_GETITEM WM_USER  HEX: 0303 + ; inline
+
+
+: WA_INACTIVE 0 ; inline
+: WA_ACTIVE 1 ; inline
+: WA_CLICKACTIVE 2 ; inline
+
+: SC_SIZE         HEX: f000 ; inline
+: SC_MOVE         HEX: f010 ; inline
+: SC_MINIMIZE     HEX: f020 ; inline
+: SC_MAXIMIZE     HEX: f030 ; inline
+: SC_NEXTWINDOW   HEX: f040 ; inline
+: SC_PREVWINDOW   HEX: f050 ; inline
+: SC_CLOSE        HEX: f060 ; inline
+: SC_VSCROLL      HEX: f070 ; inline
+: SC_HSCROLL      HEX: f080 ; inline
+: SC_MOUSEMENU    HEX: f090 ; inline
+: SC_KEYMENU      HEX: f100 ; inline
+: SC_ARRANGE      HEX: f110 ; inline
+: SC_RESTORE      HEX: f120 ; inline
+: SC_TASKLIST     HEX: f130 ; inline
+: SC_SCREENSAVE   HEX: f140 ; inline
+: SC_HOTKEY       HEX: f150 ; inline
index f40392891c5b8bb885d1af1a582614e2202624a1..e7a5645f81371bc3da58826d38a5b32fa7b2963c 100644 (file)
@@ -52,22 +52,22 @@ GENERIC: client-event ( event window -- )
 
 : handle-event ( event window -- )
     over XAnyEvent-type {
-        { [ dup Expose = ] [ drop expose-event ] }
-        { [ dup ConfigureNotify = ] [ drop configure-event ] }
-        { [ dup ButtonPress = ] [ drop button-down-event$ ] }
-        { [ dup ButtonRelease = ] [ drop button-up-event$ ] }
-        { [ dup EnterNotify = ] [ drop enter-event ] }
-        { [ dup LeaveNotify = ] [ drop leave-event ] }
-        { [ dup MotionNotify = ] [ drop motion-event ] }
-        { [ dup KeyPress = ] [ drop key-down-event ] }
-        { [ dup KeyRelease = ] [ drop key-up-event ] }
-        { [ dup FocusIn = ] [ drop focus-in-event ] }
-        { [ dup FocusOut = ] [ drop focus-out-event ] }
-        { [ dup SelectionNotify = ] [ drop selection-notify-event ] }
-        { [ dup SelectionRequest = ] [ drop selection-request-event ] }
-        { [ dup ClientMessage = ] [ drop client-event ] }
-        { [ t ] [ 3drop ] }
-    } cond ;
+        { Expose [ expose-event ] }
+        { ConfigureNotify [ configure-event ] }
+        { ButtonPress [ button-down-event$ ] }
+        { ButtonRelease [ button-up-event$ ] }
+        { EnterNotify [ enter-event ] }
+        { LeaveNotify [ leave-event ] }
+        { MotionNotify [ motion-event ] }
+        { KeyPress [ key-down-event ] }
+        { KeyRelease [ key-up-event ] }
+        { FocusIn [ focus-in-event ] }
+        { FocusOut [ focus-out-event ] }
+        { SelectionNotify [ selection-notify-event ] }
+        { SelectionRequest [ selection-request-event ] }
+        { ClientMessage [ client-event ] }
+        [ 3drop ]
+    } case ;
 
 : configured-loc ( event -- dim )
     dup XConfigureEvent-x swap XConfigureEvent-y 2array ;
index 1194ff4df14c8a35767f2cf322d2e35e529a7bbc..4fee0e3f47038919c17d037edfa8be975bdeea9f 100755 (executable)
@@ -111,7 +111,7 @@ TAG: boolean xml>item
     dup children>string {
         { [ dup "1" = ] [ 2drop t ] }
         { [ "0" = ] [ drop f ] }
-        { [ t ] [ "Bad boolean" server-error ] }
+        [ "Bad boolean" server-error ]
     } cond ;
 
 : unstruct-member ( tag -- )
index b2b7d78b3e353557b7ab8fbf8f74745a64bcbcd9..de35f469cc04d494e466dec6f1ce168f5ecf1750 100644 (file)
@@ -86,7 +86,7 @@ SYMBOL: ns-stack
         { [ dup not ] [ 2drop ] }
         { [ 2dup = ] [ 2drop next ] }
         { [ dup CHAR: & = ] [ drop parse-entity (parse-char) ] }
-        { [ t ] [ , next (parse-char) ] }
+        [ , next (parse-char) ]
     } cond ;
 
 : parse-char ( ch -- string )
@@ -194,9 +194,9 @@ SYMBOL: ns-stack
     {
         { [ get-char dup CHAR: ! = ] [ drop next direct ] }
         { [ CHAR: ? = ] [ next instruct ] } 
-        { [ t ] [
+        [
             start-tag [ dup add-ns pop-ns <closer> ]
             [ middle-tag end-tag ] if
             CHAR: > expect
-        ] }
+        ]
     } cond ;
index 5b0d2ebabba6875af7d4929b06a4b5effc126b7c..141f4abbfe065a9942fec62c312d0b1ac15156e5 100755 (executable)
@@ -198,20 +198,33 @@ void free_unmarked(F_HEAP *heap)
        build_free_list(heap,heap->segment->size);
 }
 
-/* Compute total sum of sizes of free blocks */
-CELL heap_usage(F_HEAP *heap, F_BLOCK_STATUS status)
+/* Compute total sum of sizes of free blocks, and size of largest free block */
+void heap_usage(F_HEAP *heap, CELL *used, CELL *total_free, CELL *max_free)
 {
-       CELL size = 0;
+       *used = 0;
+       *total_free = 0;
+       *max_free = 0;
+
        F_BLOCK *scan = first_block(heap);
 
        while(scan)
        {
-               if(scan->status == status)
-                       size += scan->size;
+               switch(scan->status)
+               {
+               case B_ALLOCATED:
+                       *used += scan->size;
+                       break;
+               case B_FREE:
+                       *total_free += scan->size;
+                       if(scan->size > *max_free)
+                               *max_free = scan->size;
+                       break;
+               default:
+                       critical_error("Invalid scan->status",(CELL)scan);
+               }
+
                scan = next_block(heap,scan);
        }
-
-       return size;
 }
 
 /* The size of the heap, not including the last block if it's free */
@@ -283,18 +296,12 @@ void recursive_mark(F_BLOCK *block)
 /* Push the free space and total size of the code heap */
 DEFINE_PRIMITIVE(code_room)
 {
-       dpush(tag_fixnum(heap_usage(&code_heap,B_FREE) / 1024));
+       CELL used, total_free, max_free;
+       heap_usage(&code_heap,&used,&total_free,&max_free);
        dpush(tag_fixnum((code_heap.segment->size) / 1024));
-}
-
-void code_gc(void)
-{
-       garbage_collection(TENURED,true,false,0);
-}
-
-DEFINE_PRIMITIVE(code_gc)
-{
-       code_gc();
+       dpush(tag_fixnum(used / 1024));
+       dpush(tag_fixnum(total_free / 1024));
+       dpush(tag_fixnum(max_free / 1024));
 }
 
 /* Dump all code blocks for debugging */
@@ -444,7 +451,7 @@ critical here */
 void compact_code_heap(void)
 {
        /* Free all unreachable code blocks */
-       code_gc();
+       gc();
 
        fprintf(stderr,"*** Code heap compaction...\n");
        fflush(stderr);
index 4341d8ce64030403d09fa79faed5fb60e5553bbe..658dc990ae3be07fc97a9655ae626f00bd96c8a0 100644 (file)
@@ -32,7 +32,7 @@ void build_free_list(F_HEAP *heap, CELL size);
 CELL heap_allot(F_HEAP *heap, CELL size);
 void unmark_marked(F_HEAP *heap);
 void free_unmarked(F_HEAP *heap);
-CELL heap_usage(F_HEAP *heap, F_BLOCK_STATUS status);
+void heap_usage(F_HEAP *heap, CELL *used, CELL *total_free, CELL *max_free);
 CELL heap_size(F_HEAP *heap);
 
 INLINE F_BLOCK *next_block(F_HEAP *heap, F_BLOCK *block)
@@ -85,8 +85,6 @@ void iterate_code_heap(CODE_HEAP_ITERATOR iter);
 void collect_literals(void);
 void recursive_mark(F_BLOCK *block);
 void dump_heap(F_HEAP *heap);
-void code_gc(void);
 void compact_code_heap(void);
 
 DECLARE_PRIMITIVE(code_room);
-DECLARE_PRIMITIVE(code_gc);
index e55188c6a870fe5f874df2f185cecc19b78b1280..92915e49d151a1c45ad39ab213d0f514988e7835 100755 (executable)
@@ -224,12 +224,21 @@ CELL allot_code_block(CELL size)
        /* If allocation failed, do a code GC */
        if(start == 0)
        {
-               code_gc();
+               gc();
                start = heap_allot(&code_heap,size);
 
                /* Insufficient room even after code GC, give up */
                if(start == 0)
+               {
+                       CELL used, total_free, max_free;
+                       heap_usage(&code_heap,&used,&total_free,&max_free);
+
+                       fprintf(stderr,"Code heap stats:\n");
+                       fprintf(stderr,"Used: %ld\n",used);
+                       fprintf(stderr,"Total free space: %ld\n",total_free);
+                       fprintf(stderr,"Largest free block: %ld\n",max_free);
                        fatal_error("Out of memory in add-compiled-block",0);
+               }
        }
 
        return start;
index 24f7cfecb915ab250f505e278d149daa084117b5..86552d64019f9b6a93baf6f04a495818f1931e5e 100755 (executable)
@@ -1,5 +1,18 @@
 #include "master.h"
 
+#define ALLOC_DATA_HEAP "alloc_data_heap: gens=%ld, young_size=%ld, aging_size=%ld, tenured_size=%ld\n"
+#define GC_REQUESTED "garbage_collection: growing_data_heap=%d, requested_bytes=%ld\n"
+#define BEGIN_GC "begin_gc: growing_data_heap=%d, collecting_gen=%ld\n"
+#define END_GC "end_gc: gc_elapsed=%ld\n"
+#define END_AGING_GC "end_gc: aging_collections=%ld, cards_scanned=%ld\n"
+#define END_NURSERY_GC "end_gc: nursery_collections=%ld, cards_scanned=%ld\n"
+
+#ifdef GC_DEBUG
+       #define GC_PRINT printf
+#else
+       INLINE void GC_PRINT() { }
+#endif
+
 CELL init_zone(F_ZONE *z, CELL size, CELL start)
 {
        z->size = size;
@@ -14,23 +27,30 @@ void init_cards_offset(void)
                - (data_heap->segment->start >> CARD_BITS);
 }
 
-F_DATA_HEAP *alloc_data_heap(CELL gens, CELL young_size, CELL aging_size)
+F_DATA_HEAP *alloc_data_heap(CELL gens,
+       CELL young_size,
+       CELL aging_size,
+       CELL tenured_size)
 {
+       GC_PRINT(ALLOC_DATA_HEAP,gens,young_size,aging_size,tenured_size);
+
        young_size = align_page(young_size);
        aging_size = align_page(aging_size);
+       tenured_size = align_page(tenured_size);
 
        F_DATA_HEAP *data_heap = safe_malloc(sizeof(F_DATA_HEAP));
        data_heap->young_size = young_size;
        data_heap->aging_size = aging_size;
+       data_heap->tenured_size = tenured_size;
        data_heap->gen_count = gens;
 
        CELL total_size;
        if(data_heap->gen_count == 1)
-               total_size = 2 * aging_size;
+               total_size = 2 * tenured_size;
        else if(data_heap->gen_count == 2)
-               total_size = (gens - 1) * young_size + 2 * aging_size;
+               total_size = young_size + 2 * tenured_size;
        else if(data_heap->gen_count == 3)
-               total_size = gens * young_size + 2 * aging_size;
+               total_size = young_size + 2 * aging_size + 2 * tenured_size;
        else
        {
                fatal_error("Invalid number of generations",data_heap->gen_count);
@@ -39,8 +59,8 @@ F_DATA_HEAP *alloc_data_heap(CELL gens, CELL young_size, CELL aging_size)
 
        data_heap->segment = alloc_segment(total_size);
 
-       data_heap->generations = safe_malloc(sizeof(F_ZONE) * gens);
-       data_heap->semispaces = safe_malloc(sizeof(F_ZONE) * gens);
+       data_heap->generations = safe_malloc(sizeof(F_ZONE) * data_heap->gen_count);
+       data_heap->semispaces = safe_malloc(sizeof(F_ZONE) * data_heap->gen_count);
 
        CELL cards_size = total_size / CARD_SIZE;
        data_heap->cards = safe_malloc(cards_size);
@@ -48,31 +68,19 @@ F_DATA_HEAP *alloc_data_heap(CELL gens, CELL young_size, CELL aging_size)
 
        CELL alloter = data_heap->segment->start;
 
-       alloter = init_zone(&data_heap->semispaces[NURSERY],0,alloter);
-
-       alloter = init_zone(&data_heap->generations[TENURED],aging_size,alloter);
-       alloter = init_zone(&data_heap->semispaces[TENURED],aging_size,alloter);
+       alloter = init_zone(&data_heap->generations[TENURED],tenured_size,alloter);
+       alloter = init_zone(&data_heap->semispaces[TENURED],tenured_size,alloter);
 
-       int i;
-
-       if(data_heap->gen_count > 2)
+       if(data_heap->gen_count == 3)
        {
-               alloter = init_zone(&data_heap->generations[AGING],young_size,alloter);
-               alloter = init_zone(&data_heap->semispaces[AGING],young_size,alloter);
-
-               for(i = gens - 3; i >= 0; i--)
-               {
-                       alloter = init_zone(&data_heap->generations[i],
-                               young_size,alloter);
-               }
+               alloter = init_zone(&data_heap->generations[AGING],aging_size,alloter);
+               alloter = init_zone(&data_heap->semispaces[AGING],aging_size,alloter);
        }
-       else
+
+       if(data_heap->gen_count >= 2)
        {
-               for(i = gens - 2; i >= 0; i--)
-               {
-                       alloter = init_zone(&data_heap->generations[i],
-                               young_size,alloter);
-               }
+               alloter = init_zone(&data_heap->generations[NURSERY],young_size,alloter);
+               alloter = init_zone(&data_heap->semispaces[NURSERY],0,alloter);
        }
 
        if(alloter != data_heap->segment->end)
@@ -83,12 +91,12 @@ F_DATA_HEAP *alloc_data_heap(CELL gens, CELL young_size, CELL aging_size)
 
 F_DATA_HEAP *grow_data_heap(F_DATA_HEAP *data_heap, CELL requested_bytes)
 {
-       CELL new_young_size = (data_heap->young_size * 2) + requested_bytes;
-       CELL new_aging_size = (data_heap->aging_size * 2) + requested_bytes;
+       CELL new_tenured_size = (data_heap->tenured_size * 2) + requested_bytes;
 
        return alloc_data_heap(data_heap->gen_count,
-               new_young_size,
-               new_aging_size);
+               data_heap->young_size,
+               data_heap->aging_size,
+               new_tenured_size);
 }
 
 void dealloc_data_heap(F_DATA_HEAP *data_heap)
@@ -122,9 +130,10 @@ void set_data_heap(F_DATA_HEAP *data_heap_)
 void init_data_heap(CELL gens,
        CELL young_size,
        CELL aging_size,
+       CELL tenured_size,
        bool secure_gc_)
 {
-       set_data_heap(alloc_data_heap(gens,young_size,aging_size));
+       set_data_heap(alloc_data_heap(gens,young_size,aging_size,tenured_size));
 
        gc_locals_region = alloc_segment(getpagesize());
        gc_locals = gc_locals_region->start - CELLS;
@@ -133,7 +142,8 @@ void init_data_heap(CELL gens,
        extra_roots = extra_roots_region->start - CELLS;
 
        gc_time = 0;
-       minor_collections = 0;
+       aging_collections = 0;
+       nursery_collections = 0;
        cards_scanned = 0;
        secure_gc = secure_gc_;
 }
@@ -238,7 +248,7 @@ void begin_scan(void)
 
 DEFINE_PRIMITIVE(begin_scan)
 {
-       data_gc();
+       gc();
        begin_scan();
 }
 
@@ -387,7 +397,7 @@ void collect_stack_frame(F_STACK_FRAME *frame)
 callstack snapshot */
 void collect_callstack(F_CONTEXT *stacks)
 {
-       if(collecting_code)
+       if(collecting_gen == TENURED)
        {
                CELL top = (CELL)stacks->callstack_top;
                CELL bottom = (CELL)stacks->callstack_bottom;
@@ -565,7 +575,7 @@ CELL collect_next(CELL scan)
 {
        do_slots(scan,copy_handle);
 
-       if(collecting_code)
+       if(collecting_gen == TENURED)
                do_code_slots(scan);
 
        return scan + untagged_object_size(scan);
@@ -618,16 +628,14 @@ void begin_gc(CELL requested_bytes)
                so we set the newspace so the next generation. */
                newspace = &data_heap->generations[collecting_gen + 1];
        }
-}
 
-void major_gc_message(void)
-{
-       fprintf(stderr,"*** %s GC (%ld minor, %ld cards)\n",
-               collecting_code ? "Code and data" : "Data",
-               minor_collections,cards_scanned);
-       fflush(stderr);
-       minor_collections = 0;
-       cards_scanned = 0;
+#ifdef GC_DEBUG
+       printf("\n");
+       dump_generations();
+       printf("Newspace: ");
+       dump_zone(newspace);
+       printf("\n");
+#endif
 }
 
 void end_gc(void)
@@ -637,9 +645,6 @@ void end_gc(void)
                dealloc_data_heap(old_data_heap);
                old_data_heap = NULL;
                growing_data_heap = false;
-
-               fprintf(stderr,"*** Data heap resized to %lu bytes\n",
-                       data_heap->segment->size);
        }
 
        if(collecting_accumulation_gen_p())
@@ -651,9 +656,19 @@ void end_gc(void)
                        reset_generations(NURSERY,collecting_gen - 1);
 
                if(collecting_gen == TENURED)
-                       major_gc_message();
+               {
+                       GC_PRINT(END_AGING_GC,aging_collections,cards_scanned);
+                       aging_collections = 0;
+                       cards_scanned = 0;
+               }
                else if(HAVE_AGING_P && collecting_gen == AGING)
-                       minor_collections++;
+               {
+                       aging_collections++;
+
+                       GC_PRINT(END_NURSERY_GC,nursery_collections,cards_scanned);
+                       nursery_collections = 0;
+                       cards_scanned = 0;
+               }
        }
        else
        {
@@ -661,10 +676,10 @@ void end_gc(void)
                collected are now empty */
                reset_generations(NURSERY,collecting_gen);
 
-               minor_collections++;
+               nursery_collections++;
        }
 
-       if(collecting_code)
+       if(collecting_gen == TENURED)
        {
                /* now that all reachable code blocks have been marked,
                deallocate the rest */
@@ -678,7 +693,6 @@ void end_gc(void)
 If growing_data_heap_ is true, we must grow the data heap to such a size that
 an allocation of requested_bytes won't fail */
 void garbage_collection(CELL gen,
-       bool code_gc,
        bool growing_data_heap_,
        CELL requested_bytes)
 {
@@ -688,10 +702,11 @@ void garbage_collection(CELL gen,
                return;
        }
 
+       GC_PRINT(GC_REQUESTED,growing_data_heap_,requested_bytes);
+
        s64 start = current_millis();
 
        performing_gc = true;
-       collecting_code = code_gc;
        growing_data_heap = growing_data_heap_;
        collecting_gen = gen;
 
@@ -705,8 +720,7 @@ void garbage_collection(CELL gen,
                        growing_data_heap = true;
 
                        /* see the comment in unmark_marked() */
-                       if(collecting_code)
-                               unmark_marked(&code_heap);
+                       unmark_marked(&code_heap);
                }
                /* we try collecting AGING space twice before going on to
                collect TENURED */
@@ -723,6 +737,7 @@ void garbage_collection(CELL gen,
                }
        }
 
+       GC_PRINT(BEGIN_GC,growing_data_heap,collecting_gen);
        begin_gc(requested_bytes);
 
        /* initialize chase pointer */
@@ -733,7 +748,7 @@ void garbage_collection(CELL gen,
        /* collect objects referenced from older generations */
        collect_cards();
 
-       if(!collecting_code)
+       if(collecting_gen != TENURED)
        {
                /* don't scan code heap unless it has pointers to this
                generation or younger */
@@ -754,20 +769,23 @@ void garbage_collection(CELL gen,
        while(scan < newspace->here)
                scan = collect_next(scan);
 
+       CELL gc_elapsed = (current_millis() - start);
+
+       GC_PRINT(END_GC,gc_elapsed);
        end_gc();
 
-       gc_time += (current_millis() - start);
+       gc_time += gc_elapsed;
        performing_gc = false;
 }
 
-void data_gc(void)
+void gc(void)
 {
-       garbage_collection(TENURED,false,false,0);
+       garbage_collection(TENURED,false,0);
 }
 
-DEFINE_PRIMITIVE(data_gc)
+DEFINE_PRIMITIVE(gc)
 {
-       data_gc();
+       gc();
 }
 
 /* Push total time spent on GC */
@@ -778,7 +796,8 @@ DEFINE_PRIMITIVE(gc_time)
 
 void simple_gc(void)
 {
-       maybe_gc(0);
+       if(nursery->here + ALLOT_BUFFER_ZONE > nursery->end)
+               garbage_collection(NURSERY,false,0);
 }
 
 DEFINE_PRIMITIVE(become)
@@ -800,5 +819,26 @@ DEFINE_PRIMITIVE(become)
                forward_object(old_obj,new_obj);
        }
 
-       data_gc();
+       gc();
+}
+
+CELL find_all_words(void)
+{
+       GROWABLE_ARRAY(words);
+
+       begin_scan();
+
+       CELL obj;
+       while((obj = next_object()) != F)
+       {
+               if(type_of(obj) == WORD_TYPE)
+                       GROWABLE_ADD(words,obj);
+       }
+
+       /* End heap scan */
+       gc_off = false;
+
+       GROWABLE_TRIM(words);
+
+       return words;
 }
index 8f93ce79a1e4b63a445be022bb795bb22df7a467..2490ed88057f8c9b342984197cb37638e3e68ee8 100755 (executable)
@@ -19,6 +19,8 @@ DECLARE_PRIMITIVE(begin_scan);
 DECLARE_PRIMITIVE(next_object);
 DECLARE_PRIMITIVE(end_scan);
 
+void gc(void);
+
 /* generational copying GC divides memory into zones */
 typedef struct {
        /* allocation pointer is 'here'; its offset is hardcoded in the
@@ -34,6 +36,7 @@ typedef struct {
 
        CELL young_size;
        CELL aging_size;
+       CELL tenured_size;
 
        CELL gen_count;
 
@@ -134,17 +137,18 @@ CELL init_zone(F_ZONE *z, CELL size, CELL base);
 void init_data_heap(CELL gens,
        CELL young_size,
        CELL aging_size,
+       CELL tenured_size,
        bool secure_gc_);
 
 /* statistics */
 s64 gc_time;
-CELL minor_collections;
+CELL nursery_collections;
+CELL aging_collections;
 CELL cards_scanned;
 
 /* only meaningful during a GC */
 bool performing_gc;
 CELL collecting_gen;
-bool collecting_code;
 
 /* if true, we collecting AGING space for the second time, so if it is still
 full, we go on to collect TENURED */
@@ -186,10 +190,7 @@ INLINE void do_slots(CELL obj, void (* iter)(CELL *))
        }
 }
 
-/* test if the pointer is in generation being collected, or a younger one.
-init_data_heap() arranges things so that the older generations are first,
-so we have to check that the pointer occurs after the beginning of
-the requested generation. */
+/* test if the pointer is in generation being collected, or a younger one. */
 INLINE bool should_copy(CELL untagged)
 {
        if(in_zone(newspace,untagged))
@@ -221,7 +222,6 @@ CELL heap_scan_ptr;
 bool gc_off;
 
 void garbage_collection(volatile CELL gen,
-       bool code_gc,
        bool growing_data_heap_,
        CELL requested_bytes);
 
@@ -307,28 +307,53 @@ allocation (which does not call GC because of possible roots in volatile
 registers) does not run out of memory */
 #define ALLOT_BUFFER_ZONE 1024
 
-INLINE void maybe_gc(CELL a)
-{
-       /* If we are requesting a huge object, grow immediately */
-       if(nursery->size - ALLOT_BUFFER_ZONE <= a)
-               garbage_collection(TENURED,false,true,a);
-       /* If we have enough space in the nursery, just return.
-       Otherwise, perform a GC - this may grow the heap if
-       tenured space cannot hold all live objects from the nursery
-       even after a full GC */
-       else if(a + ALLOT_BUFFER_ZONE + nursery->here > nursery->end)
-               garbage_collection(NURSERY,false,false,0);
-       /* There is now sufficient room in the nursery for 'a' */
-}
-
 /*
  * It is up to the caller to fill in the object's fields in a meaningful
  * fashion!
  */
-INLINE void* allot_object(CELL type, CELL length)
+INLINE void* allot_object(CELL type, CELL a)
 {
-       maybe_gc(length);
-       CELL* object = allot_zone(nursery,length);
+       CELL *object;
+
+       if(HAVE_NURSERY_P && nursery->size - ALLOT_BUFFER_ZONE > a)
+       {
+               /* If there is insufficient room, collect the nursery */
+               if(nursery->here + ALLOT_BUFFER_ZONE + a > nursery->end)
+                       garbage_collection(NURSERY,false,0);
+
+               object = allot_zone(nursery,a);
+       }
+       /* If the object is bigger than the nursery, allocate it in
+       tenured space */
+       else
+       {
+               F_ZONE *tenured = &data_heap->generations[TENURED];
+
+               /* If tenured space does not have enough room, collect */
+               if(tenured->here + a > tenured->end)
+               {
+                       gc();
+                       tenured = &data_heap->generations[TENURED];
+               }
+
+               /* If it still won't fit, grow the heap */
+               if(tenured->here + a > tenured->end)
+               {
+                       garbage_collection(TENURED,true,a);
+                       tenured = &data_heap->generations[TENURED];
+               }
+
+               object = allot_zone(tenured,a);
+
+               /* We have to do this */
+               allot_barrier((CELL)object);
+
+               /* Allows initialization code to store old->new pointers
+               without hitting the write barrier in the common case of
+               a nursery allocation */
+               write_barrier((CELL)object);
+       }
+
        *object = tag_header(type);
        return object;
 }
@@ -337,8 +362,8 @@ CELL collect_next(CELL scan);
 
 DLLEXPORT void simple_gc(void);
 
-void data_gc(void);
-
-DECLARE_PRIMITIVE(data_gc);
+DECLARE_PRIMITIVE(gc);
 DECLARE_PRIMITIVE(gc_time);
 DECLARE_PRIMITIVE(become);
+
+CELL find_all_words(void);
index 7e18738afc721e1ca00463fbe714f4ea6ffb79aa..840d252769a27befee8d48596f27e9b0707f62f6 100755 (executable)
@@ -146,6 +146,18 @@ void print_objects(CELL start, CELL end)
        }
 }
 
+void print_datastack(void)
+{
+       printf("==== DATA STACK:\n");
+       print_objects(ds_bot,ds);
+}
+
+void print_retainstack(void)
+{
+       printf("==== RETAIN STACK:\n");
+       print_objects(rs_bot,rs);
+}
+
 void print_stack_frame(F_STACK_FRAME *frame)
 {
        print_obj(frame_executing(frame));
@@ -158,6 +170,7 @@ void print_stack_frame(F_STACK_FRAME *frame)
 
 void print_callstack(void)
 {
+       printf("==== CALL STACK:\n");
        CELL bottom = (CELL)stack_chain->callstack_bottom;
        CELL top = (CELL)stack_chain->callstack_top;
        iterate_callstack(top,bottom,print_stack_frame);
@@ -205,10 +218,10 @@ void dump_memory(CELL from, CELL to)
                dump_cell(from);
 }
 
-void dump_zone(F_ZONE z)
+void dump_zone(F_ZONE *z)
 {
-       printf("start=%lx, size=%lx, end=%lx, here=%lx\n",
-               z.start,z.size,z.end,z.here - z.start);
+       printf("start=%ld, size=%ld, here=%ld\n",
+               z->start,z->size,z->here - z->start);
 }
 
 void dump_generations(void)
@@ -217,13 +230,13 @@ void dump_generations(void)
        for(i = 0; i < data_heap->gen_count; i++)
        {
                printf("Generation %d: ",i);
-               dump_zone(data_heap->generations[i]);
+               dump_zone(&data_heap->generations[i]);
        }
 
        for(i = 0; i < data_heap->gen_count; i++)
        {
                printf("Semispace %d: ",i);
-               dump_zone(data_heap->semispaces[i]);
+               dump_zone(&data_heap->semispaces[i]);
        }
 
        printf("Cards: base=%lx, size=%lx\n",
@@ -233,7 +246,7 @@ void dump_generations(void)
 
 void dump_objects(F_FIXNUM type)
 {
-       data_gc();
+       gc();
        begin_scan();
 
        CELL obj;
@@ -336,6 +349,8 @@ void factorbug(void)
        printf("push <addr>      -- push object on data stack - NOT SAFE\n");
        printf("code             -- code heap dump\n");
 
+       bool seen_command = false;
+
        for(;;)
        {
                char cmd[1024];
@@ -344,7 +359,22 @@ void factorbug(void)
                fflush(stdout);
 
                if(scanf("%1000s",cmd) <= 0)
+               {
+                       if(!seen_command)
+                       {
+                               /* If we exit with an EOF immediately, then
+                               dump stacks. This is useful for builder and
+                               other cases where Factor is run with stdin
+                               redirected to /dev/null */
+                               print_datastack();
+                               print_retainstack();
+                               print_callstack();
+                       }
+
                        exit(1);
+               }
+
+               seen_command = true;
 
                if(strcmp(cmd,"d") == 0)
                {
@@ -371,9 +401,9 @@ void factorbug(void)
                else if(strcmp(cmd,"r") == 0)
                        dump_memory(rs_bot,rs);
                else if(strcmp(cmd,".s") == 0)
-                       print_objects(ds_bot,ds);
+                       print_datastack();
                else if(strcmp(cmd,".r") == 0)
-                       print_objects(rs_bot,rs);
+                       print_retainstack();
                else if(strcmp(cmd,".c") == 0)
                        print_callstack();
                else if(strcmp(cmd,"e") == 0)
index ff8075c4572b55c997858033b36f4ed94efeae4f..2ca6f8944cdc97969932381b9d4c494e891415d4 100755 (executable)
@@ -2,5 +2,6 @@ void print_obj(CELL obj);
 void print_nested_obj(CELL obj, F_FIXNUM nesting);
 void dump_generations(void);
 void factorbug(void);
+void dump_zone(F_ZONE *z);
 
 DECLARE_PRIMITIVE(die);
index 27158cbf44974649da6153cf4095cee93c1dd3a7..6d99d347660d4a882477e42061968441733ee851 100755 (executable)
@@ -145,3 +145,9 @@ DEFINE_PRIMITIVE(call_clear)
 {
        throw_impl(dpop(),stack_chain->callstack_bottom);
 }
+
+/* For testing purposes */
+DEFINE_PRIMITIVE(unimplemented)
+{
+       not_implemented_error();
+}
index 747a3415ba3eafb64284e2beddcf5da0e84c0266..227fed922870d121f529e49c8bf107960da3c132 100755 (executable)
@@ -55,3 +55,5 @@ void *signal_callstack_top;
 void memory_signal_handler_impl(void);
 void divide_by_zero_signal_handler_impl(void);
 void misc_signal_handler_impl(void);
+
+DECLARE_PRIMITIVE(unimplemented);
index 5825f97bdd077cd25be0664cbfaa9bff866d5756..073b3e2e34ed23cbf217ce40ee41a6f8e8a2640b 100755 (executable)
@@ -13,15 +13,17 @@ void default_parameters(F_PARAMETERS *p)
        p->gen_count = 2;
        p->code_size = 4;
        p->young_size = 1;
-       p->aging_size = 6;
+       p->aging_size = 1;
+       p->tenured_size = 6;
 #else
        p->ds_size = 32 * CELLS;
        p->rs_size = 32 * CELLS;
 
        p->gen_count = 3;
        p->code_size = 8 * CELLS;
-       p->young_size = 2 * CELLS;
-       p->aging_size = 4 * CELLS;
+       p->young_size = CELLS / 4;
+       p->aging_size = CELLS / 2;
+       p->tenured_size = 4 * CELLS;
 #endif
 
        p->secure_gc = false;
@@ -36,21 +38,8 @@ void do_stage1_init(void)
        fprintf(stderr,"*** Stage 2 early init... ");
        fflush(stderr);
 
-       GROWABLE_ARRAY(words);
+       CELL words = find_all_words();
 
-       begin_scan();
-
-       CELL obj;
-       while((obj = next_object()) != F)
-       {
-               if(type_of(obj) == WORD_TYPE)
-                       GROWABLE_ADD(words,obj);
-       }
-
-       /* End heap scan */
-       gc_off = false;
-
-       GROWABLE_TRIM(words);
        REGISTER_ROOT(words);
 
        CELL i;
@@ -84,6 +73,7 @@ void init_factor(F_PARAMETERS *p)
        /* Megabytes */
        p->young_size <<= 20;
        p->aging_size <<= 20;
+       p->tenured_size <<= 20;
        p->code_size <<= 20;
 
        /* Disable GC during init as a sanity check */
@@ -153,6 +143,7 @@ void init_factor_from_args(F_CHAR *image, int argc, F_CHAR **argv, bool embedded
                else if(factor_arg(argv[i],STR_FORMAT("-generations=%d"),&p.gen_count));
                else if(factor_arg(argv[i],STR_FORMAT("-young=%d"),&p.young_size));
                else if(factor_arg(argv[i],STR_FORMAT("-aging=%d"),&p.aging_size));
+               else if(factor_arg(argv[i],STR_FORMAT("-tenured=%d"),&p.tenured_size));
                else if(factor_arg(argv[i],STR_FORMAT("-codeheap=%d"),&p.code_size));
                else if(STRCMP(argv[i],STR_FORMAT("-securegc")) == 0)
                        p.secure_gc = true;
index 28c6c40c1d1379499864a1346813bee3818dc439..653891fdfe8cda9863bb47b986345c3518740515 100755 (executable)
@@ -17,10 +17,14 @@ INLINE void load_data_heap(FILE *file, F_HEADER *h, F_PARAMETERS *p)
 {
        CELL good_size = h->data_size + (1 << 20);
 
-       if(good_size > p->aging_size)
-               p->aging_size = good_size;
+       if(good_size > p->tenured_size)
+               p->tenured_size = good_size;
 
-       init_data_heap(p->gen_count,p->young_size,p->aging_size,p->secure_gc);
+       init_data_heap(p->gen_count,
+               p->young_size,
+               p->aging_size,
+               p->tenured_size,
+               p->secure_gc);
 
        F_ZONE *tenured = &data_heap->generations[TENURED];
 
@@ -145,7 +149,7 @@ void save_image(const F_CHAR *filename)
 DEFINE_PRIMITIVE(save_image)
 {
        /* do a full GC to push everything into tenured space */
-       code_gc();
+       gc();
 
        save_image(unbox_native_string());
 }
index a57d1f553981c6c4db6b6f2f57311b20e03c7abe..9b7df4e3a8377464108a8ee976bb8f0b14b643f8 100755 (executable)
@@ -28,7 +28,7 @@ typedef struct {
 typedef struct {
        const F_CHAR* image;
        CELL ds_size, rs_size;
-       CELL gen_count, young_size, aging_size;
+       CELL gen_count, young_size, aging_size, tenured_size;
        CELL code_size;
        bool secure_gc;
        bool fep;
index 178c8fc7ff43062bd0c66a2df7152507f88de69f..0f4daa705b41191f8e7b1d3305761d9907141d63 100644 (file)
 #include "layouts.h"
 #include "platform.h"
 #include "primitives.h"
-#include "debug.h"
 #include "run.h"
 #include "profiler.h"
 #include "errors.h"
 #include "bignumint.h"
 #include "bignum.h"
 #include "data_gc.h"
+#include "debug.h"
 #include "types.h"
 #include "math.h"
 #include "float_bits.h"
index 86f0509e38d2da1c5bee8eca66d22e4408712c7b..eb28af53e47e4c024217f51b6f489f5fb2a15253 100644 (file)
@@ -1,4 +1,12 @@
+#include <ucontext.h>
+
 #define FRAME_RETURN_ADDRESS(frame) *((XT *)(frame_successor(frame) + 1) + 1)
 
+INLINE void *ucontext_stack_pointer(void *uap)
+{
+        ucontext_t *ucontext = (ucontext_t *)uap;
+        return (void *)ucontext->uc_mcontext.uc_regs->gregs[PT_R1];
+}
+
 #define UAP_PROGRAM_COUNTER(ucontext) \
        (((ucontext_t *)(ucontext))->uc_mcontext.uc_regs->gregs[PT_NIP])
index 4c350877524a5f49ad8713b5a69bf3454de657dd..701bb8da0161fbdfebb3a3797a9a235438ea4fd0 100644 (file)
@@ -15,4 +15,10 @@ DLLEXPORT void c_to_factor_toplevel(CELL quot);
 #ifndef environ
        extern char ***_NSGetEnviron(void);
        #define environ (*_NSGetEnviron())
-#endif
\ No newline at end of file
+#endif
+
+INLINE void *ucontext_stack_pointer(void *uap)
+{
+       ucontext_t *ucontext = (ucontext_t *)uap;
+       return ucontext->uc_stack.ss_sp;
+}
diff --git a/vm/os-unix-ucontext.h b/vm/os-unix-ucontext.h
deleted file mode 100644 (file)
index 9ed0620..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#include <ucontext.h>
-
-INLINE void *ucontext_stack_pointer(void *uap)
-{
-       ucontext_t *ucontext = (ucontext_t *)uap;
-       return ucontext->uc_stack.ss_sp;
-}
index 74320288aa60c82b9382a3ff5537c3420185aa8b..6363ce68a9224ac76fa598e3e5423b98f3bbc5de 100755 (executable)
@@ -85,6 +85,16 @@ DEFINE_PRIMITIVE(read_dir)
        dpush(result);
 }
 
+DEFINE_PRIMITIVE(os_env)
+{
+       char *name = unbox_char_string();
+       char *value = getenv(name);
+       if(value == NULL)
+               dpush(F);
+       else
+               box_char_string(value);
+}
+
 DEFINE_PRIMITIVE(os_envs)
 {
        GROWABLE_ARRAY(result);
@@ -103,6 +113,21 @@ DEFINE_PRIMITIVE(os_envs)
        dpush(result);
 }
 
+DEFINE_PRIMITIVE(set_os_env)
+{
+       char *key = unbox_char_string();
+       REGISTER_C_STRING(key);
+       char *value = unbox_char_string();
+       UNREGISTER_C_STRING(key);
+       setenv(key, value, 1);
+}
+
+DEFINE_PRIMITIVE(unset_os_env)
+{
+       char *key = unbox_char_string();
+       unsetenv(key);
+}
+
 DEFINE_PRIMITIVE(set_os_envs)
 {
        F_ARRAY *array = untag_array(dpop());
index 1be41f8b5722cd67d608360d04374fb9b67d30f4..136168807a22863e139a19dc8a6ac0ea447533df 100755 (executable)
@@ -215,7 +215,37 @@ void sleep_millis(DWORD msec)
        Sleep(msec);
 }
 
-DECLARE_PRIMITIVE(set_os_envs)
+DEFINE_PRIMITIVE(os_env)
+{
+       F_CHAR *key = unbox_u16_string();
+       F_CHAR *value = safe_malloc(MAX_UNICODE_PATH);
+       int ret;
+       ret = GetEnvironmentVariable(key, value, MAX_UNICODE_PATH);
+       if(ret == 0)
+               dpush(F);
+       else
+               dpush(tag_object(from_u16_string(value)));
+       free(value);
+}
+
+DEFINE_PRIMITIVE(set_os_env)
+{
+       F_CHAR *key = unbox_u16_string();
+       REGISTER_C_STRING(key);
+       F_CHAR *value = unbox_u16_string();
+       UNREGISTER_C_STRING(key);
+       if(!SetEnvironmentVariable(key, value))
+               general_error(ERROR_IO, tag_object(get_error_message()), F, NULL);
+}
+
+DEFINE_PRIMITIVE(unset_os_env)
+{
+       if(!SetEnvironmentVariable(unbox_u16_string(), NULL)
+               && GetLastError() != ERROR_ENVVAR_NOT_FOUND)
+               general_error(ERROR_IO, tag_object(get_error_message()), F, NULL);
+}
+
+DEFINE_PRIMITIVE(set_os_envs)
 {
        not_implemented_error();
 }
index a8c8ba756f028ea0b21e9fcb1b61a34e053a217b..2f97cb9d1d383ac6a4ceaa896e93a0cf412e50fd 100644 (file)
@@ -27,7 +27,6 @@
        #include "os-unix.h"
 
        #ifdef __APPLE__
-               #include "os-unix-ucontext.h"
                #include "os-macosx.h"
                #include "mach_signal.h"
                
@@ -84,7 +83,6 @@
                        #if defined(FACTOR_X86)
                                #include "os-linux-x86.32.h"
                        #elif defined(FACTOR_PPC)
-                               #include "os-unix-ucontext.h"
                                #include "os-linux-ppc.h"
                        #elif defined(FACTOR_ARM)
                                #include "os-linux-arm.h"
index 6a6aeb9d46391a46d223153d891379abf61b5c7a..2906a154a25704214a629601566121f89734eb9f 100755 (executable)
@@ -90,8 +90,7 @@ void *primitives[] = {
        primitive_setenv,
        primitive_existsp,
        primitive_read_dir,
-       primitive_data_gc,
-       primitive_code_gc,
+       primitive_gc,
        primitive_gc_time,
        primitive_save_image,
        primitive_save_image_and_exit,
@@ -183,9 +182,12 @@ void *primitives[] = {
        primitive_set_innermost_stack_frame_quot,
        primitive_call_clear,
        primitive_os_envs,
+       primitive_set_os_env,
+       primitive_unset_os_env,
        primitive_set_os_envs,
        primitive_resize_byte_array,
        primitive_resize_bit_array,
        primitive_resize_float_array,
        primitive_dll_validp,
+       primitive_unimplemented,
 };
index 72c9046eabfab842e3891e6545dfe1e32e0c043a..08bb846c85053d2f72f0ca61f3e2a47140a23262 100755 (executable)
@@ -57,22 +57,23 @@ void set_profiling(bool profiling)
 
        profiling_p = profiling;
 
-       /* Push everything to tenured space so that we can heap scan,
-       also code GC so that we can allocate profiling blocks if
-       necessary */
-       code_gc();
+       /* Push everything to tenured space so that we can heap scan
+       and allocate profiling blocks if necessary */
+       gc();
 
-       /* Update word XTs and saved callstack objects */
-       begin_scan();
+       CELL words = find_all_words();
 
-       CELL obj;
-       while((obj = next_object()) != F)
+       REGISTER_ROOT(words);
+
+       CELL i;
+       CELL length = array_capacity(untag_object(words));
+       for(i = 0; i < length; i++)
        {
-               if(type_of(obj) == WORD_TYPE)
-                       update_word_xt(untag_object(obj));
+               F_WORD *word = untag_word(array_nth(untag_array(words),i));
+               update_word_xt(word);
        }
 
-       gc_off = false; /* end heap scan */
+       UNREGISTER_ROOT(words);
 
        /* Update XTs in code heap */
        iterate_code_heap(relocate_code_block);
index 282be0a447b069f51e2ac89c76fa6e41b1a41d64..ae0c91d9e610f827e7d918a5afbb59e7968c94dd 100755 (executable)
--- a/vm/run.c
+++ b/vm/run.c
@@ -280,16 +280,6 @@ DEFINE_PRIMITIVE(exit)
        exit(to_fixnum(dpop()));
 }
 
-DEFINE_PRIMITIVE(os_env)
-{
-       char *name = unbox_char_string();
-       char *value = getenv(name);
-       if(value == NULL)
-               dpush(F);
-       else
-               box_char_string(value);
-}
-
 DEFINE_PRIMITIVE(eq)
 {
        CELL lhs = dpop();
index c112c5f587788d797c194af5910f71dbdb63dc8f..e2afb08525c70c202f924d1ace89c62d36bd81c0 100755 (executable)
--- a/vm/run.h
+++ b/vm/run.h
@@ -249,6 +249,8 @@ DECLARE_PRIMITIVE(setenv);
 DECLARE_PRIMITIVE(exit);
 DECLARE_PRIMITIVE(os_env);
 DECLARE_PRIMITIVE(os_envs);
+DECLARE_PRIMITIVE(set_os_env);
+DECLARE_PRIMITIVE(unset_os_env);
 DECLARE_PRIMITIVE(set_os_envs);
 DECLARE_PRIMITIVE(eq);
 DECLARE_PRIMITIVE(millis);
index 24bb4cb3ca53a130038d5e33ae7f16fa034a47b1..f88c3ef3cb6d8cde568cd016e5eb093b84f5a1e4 100755 (executable)
@@ -42,7 +42,7 @@ F_WORD *allot_word(CELL vocab, CELL name)
        UNREGISTER_ROOT(name);
        UNREGISTER_ROOT(vocab);
 
-       word->hashcode = tag_fixnum(rand());
+       word->hashcode = tag_fixnum((rand() << 16) ^ rand());
        word->vocabulary = vocab;
        word->name = name;
        word->def = userenv[UNDEFINED_ENV];