]> gitweb.factorcode.org Git - factor.git/commitdiff
Merge branch 'master' of git://factorcode.org/git/factor into s3
authorDaniel Ehrenberg <littledan@pool-224-36.res.carleton.edu>
Mon, 5 Apr 2010 00:43:15 +0000 (19:43 -0500)
committerDaniel Ehrenberg <littledan@pool-224-36.res.carleton.edu>
Mon, 5 Apr 2010 00:43:15 +0000 (19:43 -0500)
271 files changed:
GNUmakefile
Nmakefile
basis/alarms/alarms-tests.factor
basis/alien/data/data-docs.factor
basis/bit-sets/bit-sets-docs.factor
basis/bootstrap/compiler/compiler.factor
basis/bootstrap/handbook/handbook.factor
basis/bootstrap/image/image.factor
basis/bootstrap/threads/threads.factor
basis/bootstrap/ui/tools/tools.factor
basis/boxes/boxes.factor
basis/calendar/calendar-docs.factor
basis/calendar/calendar-tests.factor
basis/calendar/calendar.factor
basis/channels/channels.factor
basis/classes/struct/struct.factor
basis/cocoa/messages/messages.factor
basis/command-line/command-line-docs.factor
basis/compiler/alien/alien.factor
basis/compiler/cfg/alias-analysis/alias-analysis.factor
basis/compiler/cfg/instructions/instructions.factor
basis/compiler/cfg/intrinsics/intrinsics.factor
basis/compiler/cfg/intrinsics/misc/misc.factor
basis/compiler/codegen/codegen.factor
basis/compiler/constants/constants.factor
basis/compiler/tests/alien.factor
basis/compiler/tree/propagation/propagation-tests.factor
basis/compiler/tree/propagation/slots/slots.factor
basis/concurrency/conditions/conditions.factor
basis/concurrency/distributed/distributed.factor
basis/concurrency/exchangers/exchangers.factor
basis/concurrency/mailboxes/mailboxes.factor
basis/concurrency/messaging/messaging.factor
basis/core-foundation/file-descriptors/file-descriptors.factor
basis/core-graphics/core-graphics.factor
basis/cpu/architecture/architecture.factor
basis/cpu/ppc/bootstrap.factor
basis/cpu/ppc/ppc.factor
basis/cpu/x86/32/32.factor
basis/cpu/x86/32/bootstrap.factor
basis/cpu/x86/32/unix/bootstrap.factor [new file with mode: 0644]
basis/cpu/x86/32/winnt/bootstrap.factor [new file with mode: 0644]
basis/cpu/x86/64/64.factor
basis/cpu/x86/64/bootstrap.factor
basis/cpu/x86/assembler/assembler-tests.factor
basis/cpu/x86/assembler/assembler.factor
basis/cpu/x86/assembler/operands/operands.factor
basis/cpu/x86/bootstrap.factor
basis/cpu/x86/x86.factor
basis/debugger/debugger.factor
basis/delegate/delegate-docs.factor
basis/delegate/delegate-tests.factor
basis/delegate/delegate.factor
basis/deques/deques.factor
basis/dlists/dlists.factor
basis/heaps/heaps.factor
basis/http/client/client.factor
basis/io/backend/unix/multiplexers/kqueue/kqueue.factor
basis/io/backend/unix/unix.factor
basis/io/backend/windows/nt/nt.factor
basis/io/backend/windows/nt/privileges/privileges.factor
basis/io/backend/windows/windows.factor
basis/io/directories/unix/unix.factor
basis/io/files/unique/unique-docs.factor
basis/io/files/unique/unique.factor
basis/io/files/unique/unix/unix.factor
basis/io/files/unix/unix-tests.factor
basis/io/files/unix/unix.factor
basis/io/files/windows/windows.factor
basis/io/launcher/launcher.factor
basis/io/mmap/unix/unix.factor
basis/io/mmap/windows/windows.factor
basis/io/monitors/linux/linux.factor
basis/io/monitors/windows/nt/nt.factor
basis/io/pipes/windows/nt/nt.factor
basis/libc/libc-docs.factor
basis/libc/libc.factor
basis/literals/literals-docs.factor
basis/literals/literals-tests.factor
basis/literals/literals.factor
basis/locals/errors/errors.factor
basis/locals/locals.factor
basis/locals/parser/parser.factor
basis/locals/rewrite/point-free/point-free.factor
basis/locals/rewrite/sugar/sugar.factor
basis/locals/types/types.factor
basis/math/bitwise/bitwise-docs.factor
basis/math/bitwise/bitwise-tests.factor
basis/math/bitwise/bitwise.factor
basis/math/rectangles/rectangles.factor
basis/math/vectors/simd/simd.factor
basis/mirrors/mirrors.factor
basis/models/product/product-docs.factor
basis/openssl/libssl/libssl.factor
basis/peg/peg.factor
basis/random/windows/windows.factor
basis/regexp/parser/parser.factor
basis/regexp/regexp-tests.factor
basis/regexp/regexp.factor
basis/specialized-arrays/specialized-arrays.factor
basis/stack-checker/backend/backend.factor
basis/stack-checker/errors/errors.factor
basis/stack-checker/known-words/known-words.factor
basis/threads/threads-docs.factor
basis/threads/threads-tests.factor
basis/threads/threads.factor
basis/tools/continuations/continuations.factor
basis/tools/deploy/deploy-docs.factor
basis/tools/deploy/deploy.factor
basis/tools/deploy/macosx/macosx.factor
basis/tools/deploy/shaker/shaker.factor
basis/tools/deploy/shaker/strip-c-io.factor [new file with mode: 0644]
basis/tools/deploy/windows/windows.factor
basis/tools/threads/threads.factor
basis/typed/typed.factor
basis/ui/backend/windows/windows.factor
basis/ui/gadgets/buttons/buttons.factor
basis/ui/gadgets/gadgets.factor
basis/ui/tools/listener/listener.factor
basis/ui/tools/operations/operations.factor
basis/unix/linux/inotify/inotify.factor
basis/unix/statfs/macosx/macosx.factor
basis/unix/unix.factor
basis/urls/urls.factor
basis/validators/validators-tests.factor
basis/validators/validators.factor
basis/vm/vm.factor
basis/windows/advapi32/advapi32.factor [changed mode: 0644->0755]
basis/windows/com/syntax/syntax.factor
basis/windows/directx/d3d9types/d3d9types.factor
basis/windows/errors/errors.factor [changed mode: 0644->0755]
basis/windows/gdi32/gdi32.factor
basis/windows/user32/user32.factor
basis/windows/winsock/winsock.factor
basis/x11/windows/windows.factor
basis/x11/x11.factor
basis/x11/xlib/xlib.factor
basis/xml/syntax/inverse/inverse.factor [new file with mode: 0644]
basis/xml/syntax/syntax.factor
build-support/factor.sh
core/alien/alien.factor
core/bootstrap/primitives.factor
core/continuations/continuations-docs.factor
core/continuations/continuations.factor
core/hash-sets/hash-sets-docs.factor
core/kernel/kernel-docs.factor
core/kernel/kernel-tests.factor
core/lexer/lexer.factor
core/parser/parser-tests.factor
core/sets/sets-docs.factor
core/syntax/syntax.factor
core/system/system.factor
core/vocabs/loader/loader-docs.factor
core/vocabs/loader/loader-tests.factor
core/vocabs/loader/loader.factor
core/vocabs/loader/test/m/m.factor [new file with mode: 0644]
core/vocabs/loader/test/m/tags.txt [new file with mode: 0644]
core/vocabs/loader/test/n/n.factor [new file with mode: 0644]
core/vocabs/loader/test/n/tags.txt [new file with mode: 0644]
core/vocabs/loader/test/o/o.factor [new file with mode: 0644]
core/vocabs/loader/test/o/tags.txt [new file with mode: 0644]
core/vocabs/vocabs.factor
extra/astar/astar-docs.factor [deleted file]
extra/astar/astar-tests.factor [deleted file]
extra/astar/astar.factor [deleted file]
extra/astar/authors.txt [deleted file]
extra/astar/summary.txt [deleted file]
extra/cursors/authors.txt
extra/cursors/cursors-tests.factor
extra/cursors/cursors.factor
extra/elf/authors.txt [new file with mode: 0644]
extra/elf/elf.factor [new file with mode: 0644]
extra/elf/summary.txt [new file with mode: 0644]
extra/fullscreen/fullscreen.factor
extra/game/debug/authors.txt [new file with mode: 0644]
extra/game/debug/debug.factor [new file with mode: 0644]
extra/game/debug/summary.txt [new file with mode: 0644]
extra/game/debug/tags.txt [new file with mode: 0644]
extra/game/debug/tests/tests.factor [new file with mode: 0644]
extra/game/loop/loop.factor
extra/gpu/demos/raytrace/deploy.factor
extra/gpu/render/render.factor
extra/gpu/shaders/shaders.factor
extra/io/serial/unix/bsd/bsd.factor
extra/io/serial/unix/unix-tests.factor
extra/io/serial/unix/unix.factor
extra/irc/gitbot/gitbot.factor
extra/mason/child/child-tests.factor
extra/mason/common/common.factor
extra/model-viewer/model-viewer.factor
extra/path-finding/authors.txt [new file with mode: 0644]
extra/path-finding/path-finding-docs.factor [new file with mode: 0644]
extra/path-finding/path-finding-tests.factor [new file with mode: 0644]
extra/path-finding/path-finding.factor [new file with mode: 0644]
extra/path-finding/summary.txt [new file with mode: 0644]
extra/spelling/authors.txt [new file with mode: 0644]
extra/spelling/spelling-tests.factor [new file with mode: 0644]
extra/spelling/spelling.factor [new file with mode: 0644]
extra/spelling/summary.txt [new file with mode: 0644]
extra/spelling/tags.txt [new file with mode: 0644]
extra/spelling/test.txt [new file with mode: 0644]
extra/variables/variables.factor [new file with mode: 0644]
extra/vars/authors.txt [deleted file]
extra/vars/summary.txt [deleted file]
extra/vars/tags.txt [deleted file]
extra/vars/vars.factor [deleted file]
extra/webapps/planet/planet.factor
extra/webkit-demo/webkit-demo.factor
extra/websites/concatenative/page.css
vm/Config.freebsd
vm/Config.linux
vm/Config.macosx
vm/Config.netbsd
vm/Config.openbsd
vm/Config.windows.nt
vm/alien.cpp
vm/callbacks.cpp [changed mode: 0644->0755]
vm/callbacks.hpp
vm/callstack.cpp
vm/callstack.hpp
vm/code_block_visitor.hpp
vm/code_blocks.cpp
vm/collector.hpp
vm/contexts.cpp
vm/contexts.hpp
vm/cpu-ppc.hpp
vm/cpu-x86.hpp [changed mode: 0644->0755]
vm/data_heap.cpp
vm/debug.cpp
vm/errors.cpp
vm/errors.hpp
vm/factor.cpp
vm/factor.hpp
vm/gc.cpp
vm/gc.hpp
vm/image.hpp
vm/instruction_operands.hpp
vm/io.cpp
vm/mach_signal.cpp
vm/master.hpp
vm/math.cpp
vm/mvm-none.cpp [new file with mode: 0644]
vm/mvm-unix.cpp [new file with mode: 0644]
vm/mvm-windows-nt.cpp [new file with mode: 0644]
vm/mvm.cpp [new file with mode: 0644]
vm/mvm.hpp [new file with mode: 0644]
vm/objects.hpp
vm/os-freebsd.hpp
vm/os-genunix.cpp
vm/os-genunix.hpp
vm/os-linux-arm.cpp
vm/os-linux.hpp
vm/os-macosx-ppc.hpp
vm/os-macosx-x86.32.hpp
vm/os-macosx-x86.64.hpp
vm/os-macosx.hpp
vm/os-macosx.mm
vm/os-netbsd.hpp
vm/os-openbsd.hpp [new file with mode: 0644]
vm/os-unix.cpp
vm/os-unix.hpp
vm/os-windows-nt.cpp
vm/os-windows-nt.hpp
vm/os-windows.cpp
vm/os-windows.hpp
vm/platform.hpp
vm/primitives.hpp
vm/segments.hpp
vm/slot_visitor.hpp
vm/vm.cpp
vm/vm.hpp

index eac1c696df5b5ecab92c5eb709d48b2c60f79bb7..9f93deedf290a9482c9d668c18c202b97537c6e2 100755 (executable)
@@ -52,6 +52,7 @@ ifdef CONFIG
                vm/io.o \
                vm/jit.o \
                vm/math.o \
+               vm/mvm.o \
                vm/nursery_collector.o \
                vm/object_start_map.o \
                vm/objects.o \
@@ -168,22 +169,16 @@ macosx.app: factor
        mkdir -p $(BUNDLE)/Contents/Frameworks
        mv $(EXECUTABLE) $(BUNDLE)/Contents/MacOS/factor
        ln -s Factor.app/Contents/MacOS/factor ./factor
-       cp $(ENGINE) $(BUNDLE)/Contents/Frameworks/$(ENGINE)
-
-       install_name_tool \
-               -change libfactor.dylib \
-               @executable_path/../Frameworks/libfactor.dylib \
-               Factor.app/Contents/MacOS/factor
 
 $(ENGINE): $(DLL_OBJS)
        $(TOOLCHAIN_PREFIX)$(LINKER) $(ENGINE) $(DLL_OBJS)
 
-factor: $(EXE_OBJS) $(ENGINE)
-       $(TOOLCHAIN_PREFIX)$(CPP) $(LIBS) $(LIBPATH) -L. $(LINK_WITH_ENGINE) \
+factor: $(EXE_OBJS) $(DLL_OBJS)
+       $(TOOLCHAIN_PREFIX)$(CPP) $(LIBS) $(LIBPATH) -L. $(DLL_OBJS) \
                $(CFLAGS) -o $(EXECUTABLE) $(EXE_OBJS)
 
-factor-console: $(EXE_OBJS) $(ENGINE)
-       $(TOOLCHAIN_PREFIX)$(CPP) $(LIBS) $(LIBPATH) -L. $(LINK_WITH_ENGINE) \
+factor-console: $(EXE_OBJS) $(DLL_OBJS)
+       $(TOOLCHAIN_PREFIX)$(CPP) $(LIBS) $(LIBPATH) -L. $(DLL_OBJS) \
                $(CFLAGS) $(CFLAGS_CONSOLE) -o $(CONSOLE_EXECUTABLE) $(EXE_OBJS)
 
 factor-ffi-test: $(FFI_TEST_LIBRARY)
index 7349deae23b27727f089c75bdd74060b565342f1..9df7a6a1eee94bad9e9b40f349d01335da6f4185 100755 (executable)
--- a/Nmakefile
+++ b/Nmakefile
@@ -2,11 +2,11 @@
 LINK_FLAGS = /nologo /DEBUG shell32.lib
 CL_FLAGS = /nologo /Zi /O2 /W3 /DFACTOR_DEBUG
 !ELSE
-LINK_FLAGS = /nologo shell32.lib
+LINK_FLAGS = /nologo /safeseh:no shell32.lib
 CL_FLAGS = /nologo /O2 /W3
 !ENDIF
 
-EXE_OBJS = factor.dll.lib vm\main-windows-nt.obj vm\factor.res
+EXE_OBJS = vm\main-windows-nt.obj vm\factor.res
 
 DLL_OBJS = vm\os-windows-nt.obj \
        vm\os-windows.obj \
@@ -38,6 +38,8 @@ DLL_OBJS = vm\os-windows-nt.obj \
        vm\io.obj \
        vm\jit.obj \
        vm\math.obj \
+       vm\mvm.obj \
+       vm\mvm-windows-nt.obj \
        vm\nursery_collector.obj \
        vm\object_start_map.obj \
        vm\objects.obj \
@@ -61,7 +63,7 @@ DLL_OBJS = vm\os-windows-nt.obj \
 .rs.res:
        rc $<
 
-all: factor.com factor.exe libfactor-ffi-test.dll
+all: factor.com factor.exe factor.dll.lib libfactor-ffi-test.dll
 
 libfactor-ffi-test.dll: vm/ffi_test.obj
        link $(LINK_FLAGS) /out:libfactor-ffi-test.dll /dll vm/ffi_test.obj
@@ -69,11 +71,11 @@ libfactor-ffi-test.dll: vm/ffi_test.obj
 factor.dll.lib: $(DLL_OBJS)
        link $(LINK_FLAGS) /implib:factor.dll.lib /out:factor.dll /dll $(DLL_OBJS)
 
-factor.com: $(EXE_OBJS)
-       link $(LINK_FLAGS) /out:factor.com /SUBSYSTEM:console $(EXE_OBJS)
+factor.com: $(EXE_OBJS) $(DLL_OBJS)
+       link $(LINK_FLAGS) /out:factor.com /SUBSYSTEM:console $(EXE_OBJS) $(DLL_OBJS)
 
-factor.exe: $(EXE_OBJS)
-       link $(LINK_FLAGS) /out:factor.exe /SUBSYSTEM:windows $(EXE_OBJS)
+factor.exe: $(EXE_OBJS) $(DLL_OBJS)
+       link $(LINK_FLAGS) /out:factor.exe /SUBSYSTEM:windows $(EXE_OBJS) $(DLL_OBJS)
 
 clean:
        del vm\*.obj
index 2379e3e80d809baba9cd08424a94a6955f28c67a..8f7868324d1f874061bf0f07de26015280f96c23 100644 (file)
@@ -11,7 +11,6 @@ IN: alarms.tests
 ] unit-test\r
 \r
 [ ] [\r
-    [\r
-        [ resume ] curry instant later drop\r
-    ] "test" suspend drop\r
+    self [ resume ] curry instant later drop\r
+    "test" suspend drop\r
 ] unit-test\r
index 4600ea68371406961468afc9be8a664fe2115c2b..d36a4d5fd2b2840efb84eb27b87b4a5badd60d33 100644 (file)
@@ -60,6 +60,8 @@ $nl
 }
 "You must always free pointers returned by any of the above words when the block of memory is no longer in use:"
 { $subsections free }
+"The above words record memory allocations, to help catch double frees and track down memory leaks with " { $link "tools.destructors" } ". To free memory allocated by a C library, another word can be used:"
+{ $subsections (free) }
 "Utilities for automatically freeing memory in conjunction with " { $link with-destructors } ":"
 { $subsections
     &free
@@ -148,9 +150,9 @@ $nl
 }
 "The first allocates " { $link byte-array } "s, and the latter allocates manually-managed memory which is not moved by the garbage collector and has to be explicitly freed by calling " { $link free } ". See " { $link "byte-arrays-gc" } " for a discussion of the two approaches."
 $nl
-"The C type " { $link char } { $snippet "*" } " represents a generic pointer to " { $snippet "char" } "; arguments with this type will expect and return " { $link alien } "s, and won't perform any implicit string conversion."
+"The C type " { $snippet "char*" } " represents a generic pointer to " { $snippet "char" } "; arguments with this type will expect and return " { $link alien } "s, and won't perform any implicit string conversion."
 $nl
 "A word to read strings from arbitrary addresses:"
 { $subsections alien>string }
-"For example, if a C function returns a " { $link c-string } " but stipulates that the caller must deallocate the memory afterward, you must define the function as returning " { $snippet "char*" } " and call one of the above words before passing the pointer to " { $link free } "." ;
+"For example, if a C function returns a " { $link c-string } " but stipulates that the caller must deallocate the memory afterward, you must define the function as returning " { $snippet "char*" } " and call " { $link (free) } " yourself." ;
 
index bb4dc75cac522bdf1ff7749fe8bfce398098831c..706ffb5cf1d8ccd5c3bdbae9f205e2cb9957732a 100644 (file)
@@ -3,9 +3,9 @@ IN: bit-sets
 
 ARTICLE: "bit-sets" "Bit sets"
 "The " { $vocab-link "bit-sets" } " vocabulary implements bit-array-backed sets. Bitsets are efficient for implementing relatively dense sets whose members are in a contiguous range of integers starting from 0. One bit is required for each integer in this range in the underlying representation." $nl
-"Bit sets are of the class"
+"Bit sets form a class:"
 { $subsection bit-set }
-"They can be instantiated with the word"
+"Constructing new bit sets:"
 { $subsection <bit-set> } ;
 
 ABOUT: "bit-sets"
index 0bdb2494f88957bfa5031cef2bf4d8351c0ec6ec..0237ed99ee4558c51582bcfddb70c4c7e72200d8 100644 (file)
@@ -20,11 +20,8 @@ IN: bootstrap.compiler
     "alien.remote-control" require
 ] unless
 
-"prettyprint" vocab [
-    "stack-checker.errors.prettyprint" require
-    "alien.prettyprint" require
-    "alien.debugger" require
-] when
+"prettyprint" "alien.prettyprint" require-when
+"debugger" "alien.debugger" require-when
 
 "cpu." cpu name>> append require
 
index 51aa9eefafb7b560c99f8931d4b913624472938e..11f7349b7962d320429563cdb54068a72aad90f1 100644 (file)
@@ -1,4 +1,4 @@
 USING: vocabs.loader vocabs kernel ;\r
 IN: bootstrap.handbook\r
 \r
-"bootstrap.help" vocab [ "help.handbook" require ] when\r
+"bootstrap.help" "help.handbook" require-when\r
index 3552f0bd92ca44c5bff578ca35d01d031a039f38..62240f73ce1f044183db3af5f84f7933a5156c0c 100644 (file)
@@ -15,10 +15,11 @@ generalizations ;
 IN: bootstrap.image
 
 : arch ( os cpu -- arch )
+    [ dup "winnt" = "winnt" "unix" ? ] dip
     {
-        { "ppc" [ "-ppc" append ] }
-        { "x86.64" [ "winnt" = "winnt" "unix" ? "-x86.64" append ] }
-        [ nip ]
+        { "ppc" [ drop "-ppc" append ] }
+        { "x86.32" [ nip "-x86.32" append ] }
+        { "x86.64" [ nip "-x86.64" append ] }
     } case ;
 
 : my-arch ( -- arch )
@@ -32,7 +33,7 @@ IN: bootstrap.image
 
 : images ( -- seq )
     {
-        "x86.32"
+        "winnt-x86.32" "unix-x86.32"
         "winnt-x86.64" "unix-x86.64"
         "linux-ppc" "macosx-ppc"
     } ;
@@ -129,8 +130,8 @@ SYMBOL: jit-literals
 : jit-vm ( offset rc -- )
     [ jit-parameter ] dip rt-vm jit-rel ;
 
-: jit-dlsym ( name library rc -- )
-    rt-dlsym jit-rel [ string>symbol jit-parameter ] bi@ ;
+: jit-dlsym ( name rc -- )
+    rt-dlsym jit-rel string>symbol jit-parameter f jit-parameter ;
 
 :: jit-conditional ( test-quot false-quot -- )
     [ 0 test-quot call ] B{ } make length :> len
index 24cbba6af815eab92c0c103940c7677d56884979..3a8fe98cf408ba39610365bec70fb32c67678e1e 100644 (file)
@@ -1,11 +1,9 @@
 ! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: vocabs vocabs.loader kernel io.thread threads
+USING: vocabs.loader kernel io.thread threads
 compiler.utilities namespaces ;
 IN: bootstrap.threads
 
-"debugger" vocab [
-    "debugger.threads" require
-] when
+"debugger" "debugger.threads" require-when
 
-[ yield ] yield-hook set-global
\ No newline at end of file
+[ yield ] yield-hook set-global
index 5cf05aef91a539723bb8292f7ec1a039066d76de..7db69ce9c12e560b4192bfe8403a57023fff599e 100644 (file)
@@ -4,9 +4,7 @@ USING: kernel vocabs vocabs.loader sequences system ;
 [ "bootstrap." prepend vocab ] all? [
     "ui.tools" require
 
-    "ui.backend.cocoa" vocab [
-        "ui.backend.cocoa.tools" require
-    ] when
+    "ui.backend.cocoa" "ui.backend.cocoa.tools" require-when
 
     "ui.tools.walker" require
 ] when
index 39f8eb44cc354c3a68e19396a0dd69943e21d963..a159e1402b04027301eac6f104814f41e81642cc 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2008 Slava Pestov.\r
+! Copyright (C) 2008, 2010 Slava Pestov.\r
 ! See http://factorcode.org/license.txt for BSD license.\r
 USING: kernel accessors ;\r
 IN: boxes\r
@@ -11,16 +11,18 @@ ERROR: box-full box ;
 \r
 : >box ( value box -- )\r
     dup occupied>>\r
-    [ box-full ] [ t >>occupied (>>value) ] if ;\r
+    [ box-full ] [ t >>occupied (>>value) ] if ; inline\r
 \r
 ERROR: box-empty box ;\r
 \r
+: check-box ( box -- box )\r
+    dup occupied>> [ box-empty ] unless ; inline\r
+\r
 : box> ( box -- value )\r
-    dup occupied>>\r
-    [ [ f ] change-value f >>occupied drop ] [ box-empty ] if ;\r
+    check-box [ f ] change-value f >>occupied drop ; inline\r
 \r
 : ?box ( box -- value/f ? )\r
-    dup occupied>> [ box> t ] [ drop f f ] if ;\r
+    dup occupied>> [ box> t ] [ drop f f ] if ; inline\r
 \r
 : if-box? ( box quot -- )\r
     [ ?box ] dip [ drop ] if ; inline\r
index 6ce8b1d5fde4fd86b2744750b37b13ea98ceeb10..a5a31ebd659808537b2dd22de3e08bbec46e724a 100644 (file)
@@ -76,27 +76,27 @@ HELP: day-abbreviation3
 } related-words
 
 HELP: average-month
-{ $values { "ratio" ratio } }
+{ $values { "value" ratio } }
 { $description "The length of an average month averaged over 400 years. Used internally for adding an arbitrary real number of months to a timestamp." } ;
 
 HELP: months-per-year
-{ $values { "integer" integer } }
+{ $values { "value" integer } }
 { $description "Returns the number of months in a year." } ;
 
 HELP: days-per-year
-{ $values { "ratio" ratio } }
+{ $values { "value" ratio } }
 { $description "Returns the number of days in a year averaged over 400 years. Used internally for adding an arbitrary real number of days to a timestamp." } ;
 
 HELP: hours-per-year
-{ $values { "ratio" ratio } }
+{ $values { "value" ratio } }
 { $description "Returns the number of hours in a year averaged over 400 years. Used internally for adding an arbitrary real number of hours to a timestamp." } ;
 
 HELP: minutes-per-year
-{ $values { "ratio" ratio } }
+{ $values { "value" ratio } }
 { $description "Returns the number of minutes in a year averaged over 400 years. Used internally for adding an arbitrary real number of minutes to a timestamp." } ;
 
 HELP: seconds-per-year
-{ $values { "integer" integer } }
+{ $values { "value" integer } }
 { $description "Returns the number of seconds in a year averaged over 400 years. Used internally for adding an arbitrary real number of seconds to a timestamp." } ;
 
 HELP: julian-day-number
index 2490b87c374b0876dc6bf991d2b7ec232f305a31..3f52b4d2e7f2da50688a450580d9112070201647 100644 (file)
@@ -176,3 +176,13 @@ IN: calendar.tests
 [ t ] [ 1356998399 unix-time>timestamp 2013 <year-gmt> 1 seconds time- = ] unit-test
 
 [ t ] [ 1500000000 random [ unix-time>timestamp timestamp>unix-time ] keep = ] unit-test
+
+[ t ] [
+    2009 1 29 <date> 1 months time+
+    2009 3 1 <date> =
+] unit-test
+
+[ t ] [
+    2008 1 29 <date> 1 months time+
+    2008 2 29 <date> =
+] unit-test
index cd87701aa91fba0b33aa19f7c302d9d91267fb12..8758b8198b2df520b80631b02bec4a7205169a3e 100644 (file)
@@ -99,12 +99,12 @@ CONSTANT: day-abbreviations3
 : day-abbreviation3 ( n -- string )
     day-abbreviations3 nth ; inline
 
-: average-month ( -- ratio ) 30+5/12 ; inline
-: months-per-year ( -- integer ) 12 ; inline
-: days-per-year ( -- ratio ) 3652425/10000 ; inline
-: hours-per-year ( -- ratio ) 876582/100 ; inline
-: minutes-per-year ( -- ratio ) 5259492/10 ; inline
-: seconds-per-year ( -- integer ) 31556952 ; inline
+CONSTANT: average-month 30+5/12
+CONSTANT: months-per-year 12
+CONSTANT: days-per-year 3652425/10000
+CONSTANT: hours-per-year 876582/100
+CONSTANT: minutes-per-year 5259492/10
+CONSTANT: seconds-per-year 31556952
 
 :: julian-day-number ( year month day -- n )
     #! Returns a composite date number
@@ -200,7 +200,7 @@ GENERIC: +second ( timestamp x -- timestamp )
     [ 3 >>month 1 >>day ] when ;
 
 M: integer +year ( timestamp n -- timestamp )
-    [ [ + ] curry change-year adjust-leap-year ] unless-zero ;
+    [ + ] curry change-year adjust-leap-year ;
 
 M: real +year ( timestamp n -- timestamp )
     [ float>whole-part swapd days-per-year * +day swap +year ] unless-zero ;
index 0eb7881f95915c9c336ba09400e731ac2aaf1d1f..870085f77afbee1540475f5d3293a5d6892212b0 100644 (file)
@@ -17,7 +17,7 @@ GENERIC: from ( channel -- value )
 <PRIVATE
 
 : wait ( channel -- )
-    [ senders>> push ] curry
+    [ self ] dip senders>> push
     "channel send" suspend drop ;
 
 : (to) ( value receivers -- )
@@ -36,7 +36,7 @@ M: channel to ( value channel -- )
     [ dup wait to ] [ nip (to) ] if-empty ;
 
 M: channel from ( channel -- value )
-    [
-        notify senders>>
-        [ (from) ] unless-empty
-    ] curry "channel receive" suspend ;
+    [ self ] dip
+    notify senders>>
+    [ (from) ] unless-empty
+    "channel receive" suspend ;
index 79dea73d8cd4a0478226a9caca2edc2f9bf119b5..ffde2337486cfb5182c32f0e7658aae6c2c954b4 100644 (file)
@@ -404,4 +404,4 @@ FUNCTOR-SYNTAX: STRUCT:
 
 USING: vocabs vocabs.loader ;
 
-"prettyprint" vocab [ "classes.struct.prettyprint" require ] when
+"prettyprint" "classes.struct.prettyprint" require-when
index a74408703711c7e8f3ed70d9f73dfc3089c303a9..c422d85423eb39c3dafb5f2cd9a1435649ddddcd 100644 (file)
@@ -5,8 +5,7 @@ classes.struct continuations combinators compiler compiler.alien
 core-graphics.types stack-checker kernel math namespaces make
 quotations sequences strings words cocoa.runtime cocoa.types io
 macros memoize io.encodings.utf8 effects layouts libc
-libc.private lexer init core-foundation fry generalizations
-specialized-arrays ;
+lexer init core-foundation fry generalizations specialized-arrays ;
 QUALIFIED-WITH: alien.c-types c
 IN: cocoa.messages
 
index 9a69614766843c5d9c31958072f88ddcf2471a5b..b17f8250dd34ffa31d1ed28c799273410be935e7 100644 (file)
@@ -43,14 +43,16 @@ ARTICLE: "runtime-cli-args" "Command line switches for the VM"
     { { $snippet "-i=" { $emphasis "image" } } { "Specifies the image file to use; see " { $link "images" } } }
     { { $snippet "-datastack=" { $emphasis "n" } } "Data stack size, kilobytes" }
     { { $snippet "-retainstack=" { $emphasis "n" } } "Retain stack size, kilobytes" }
+    { { $snippet "-callstack=" { $emphasis "n" } } "Call stack size, kilobytes" }
     { { $snippet "-young=" { $emphasis "n" } } { "Size of youngest generation (0), megabytes" } }
     { { $snippet "-aging=" { $emphasis "n" } } "Size of aging generation (1), megabytes" }
     { { $snippet "-tenured=" { $emphasis "n" } } "Size of oldest generation (2), megabytes" }
     { { $snippet "-codeheap=" { $emphasis "n" } } "Code heap size, megabytes" }
+    { { $snippet "-callbacks=" { $emphasis "n" } } "Callback heap size, megabytes" }
     { { $snippet "-pic=" { $emphasis "n" } } "Maximum inline cache size. Setting of 0 disables inline caching, > 1 enables polymorphic inline caching" }
     { { $snippet "-securegc" } "If specified, unused portions of the data heap will be zeroed out after every garbage collection" }
 }
-"If an " { $snippet "-i=" } " switch is not present, the default image file is used, which is usually a file named " { $snippet "factor.image" } " in the same directory as the runtime executable (on Windows and Mac OS X) or the current directory (on Unix)." ;
+"If an " { $snippet "-i=" } " switch is not present, the default image file is used, which is usually a file named " { $snippet "factor.image" } " in the same directory as the Factor executable." ;
 
 ARTICLE: "bootstrap-cli-args" "Command line switches for bootstrap"
 "A number of command line switches can be passed to a bootstrap image to modify the behavior of the resulting image:"
index 6a63b719dfb537da709be8fac6a8b6f0669e49fe..7426d7e9408770a921027d075010bd99c621cecb 100644 (file)
@@ -1,17 +1,17 @@
-! Copyright (C) 2008 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors kernel namespaces make math sequences layouts
 alien.c-types cpu.architecture ;
 IN: compiler.alien
 
-: large-struct? ( ctype -- ? )
+: large-struct? ( type -- ? )
     dup c-struct? [ return-struct-in-registers? not ] [ drop f ] if ;
 
 : alien-parameters ( params -- seq )
     dup parameters>>
     swap return>> large-struct? [ void* prefix ] when ;
 
-: alien-return ( params -- ctype )
+: alien-return ( params -- type )
     return>> dup large-struct? [ drop void ] when ;
 
 : c-type-stack-align ( type -- align )
index 24433ad594f75ff9742e166082b3c54c1d226a9a..44326c179fb4b60834b78764a54ffb66788b093b 100644 (file)
@@ -202,14 +202,16 @@ M: ##slot-imm insn-slot# slot>> ;
 M: ##set-slot insn-slot# slot>> constant ;
 M: ##set-slot-imm insn-slot# slot>> ;
 M: ##alien-global insn-slot# [ library>> ] [ symbol>> ] bi 2array ;
-M: ##vm-field-ptr insn-slot# field-name>> ;
+M: ##vm-field insn-slot# offset>> ;
+M: ##set-vm-field insn-slot# offset>> ;
 
 M: ##slot insn-object obj>> resolve ;
 M: ##slot-imm insn-object obj>> resolve ;
 M: ##set-slot insn-object obj>> resolve ;
 M: ##set-slot-imm insn-object obj>> resolve ;
 M: ##alien-global insn-object drop \ ##alien-global ;
-M: ##vm-field-ptr insn-object drop \ ##vm-field-ptr ;
+M: ##vm-field insn-object drop \ ##vm-field ;
+M: ##set-vm-field insn-object drop \ ##vm-field ;
 
 : init-alias-analysis ( insns -- insns' )
     H{ } clone histories set
@@ -222,7 +224,7 @@ M: ##vm-field-ptr insn-object drop \ ##vm-field-ptr ;
     0 ac-counter set
     next-ac heap-ac set
 
-    \ ##vm-field-ptr set-new-ac
+    \ ##vm-field set-new-ac
     \ ##alien-global set-new-ac
 
     dup local-live-in [ set-heap-ac ] each ;
index 68a8b8ce59d6fc376e2d6251a1be2f1c9cf12d06..c015cb640b5222a3dcaaff6c04e784507cab9a62 100644 (file)
@@ -660,9 +660,13 @@ INSN: ##alien-global
 def: dst/int-rep
 literal: symbol library ;
 
-INSN: ##vm-field-ptr
+INSN: ##vm-field
 def: dst/int-rep
-literal: field-name ;
+literal: offset ;
+
+INSN: ##set-vm-field
+use: src/int-rep
+literal: offset ;
 
 ! FFI
 INSN: ##alien-invoke
@@ -831,8 +835,8 @@ UNION: ##allocation
 ##box-displaced-alien ;
 
 ! For alias analysis
-UNION: ##read ##slot ##slot-imm ##vm-field-ptr ##alien-global ;
-UNION: ##write ##set-slot ##set-slot-imm ;
+UNION: ##read ##slot ##slot-imm ##vm-field ##alien-global ;
+UNION: ##write ##set-slot ##set-slot-imm ##set-vm-field ;
 
 ! Instructions that kill all live vregs but cannot trigger GC
 UNION: partial-sync-insn
index d753a4c1b496c75cbf0a329e9147bc685689ba23..2b2ae7d160d15a94cf8c76fb3243aac040bd91a7 100644 (file)
@@ -30,7 +30,9 @@ IN: compiler.cfg.intrinsics
 
 {
     { kernel.private:tag [ drop emit-tag ] }
+    { kernel.private:context-object [ emit-context-object ] }
     { kernel.private:special-object [ emit-special-object ] }
+    { kernel.private:set-special-object [ emit-set-special-object ] }
     { kernel.private:(identity-hashcode) [ drop emit-identity-hashcode ] }
     { math.private:both-fixnums? [ drop emit-both-fixnums? ] }
     { math.private:fixnum+ [ drop emit-fixnum+ ] }
index fed5492220847bbd760935147a1995d2c94151f3..da77bcaa09d69deb332739ddbe24bf00c207e0fa 100644 (file)
@@ -1,19 +1,40 @@
-! Copyright (C) 2008 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: namespaces layouts sequences kernel math accessors
 compiler.tree.propagation.info compiler.cfg.stacks
 compiler.cfg.hats compiler.cfg.instructions
+compiler.cfg.builder.blocks
 compiler.cfg.utilities ;
+FROM: vm => context-field-offset vm-field-offset ;
 IN: compiler.cfg.intrinsics.misc
 
 : emit-tag ( -- )
     ds-pop tag-mask get ^^and-imm ^^tag-fixnum ds-push ;
 
+: special-object-offset ( n -- offset )
+    cells "special-objects" vm-field-offset + ;
+
 : emit-special-object ( node -- )
-    "special-objects" ^^vm-field-ptr
-    swap node-input-infos first literal>>
-    [ ds-drop 0 ^^slot-imm ] [ ds-pop ^^offset>slot ^^slot ] if*
-    ds-push ;
+    dup node-input-infos first literal>> [
+        ds-drop
+        special-object-offset ^^vm-field
+        ds-push
+    ] [ emit-primitive ] ?if ;
+
+: emit-set-special-object ( node -- )
+    dup node-input-infos second literal>> [
+        ds-drop
+        [ ds-pop ] dip special-object-offset ##set-vm-field
+    ] [ emit-primitive ] ?if ;
+
+: context-object-offset ( n -- n )
+    cells "context-objects" context-field-offset + ;
+
+: emit-context-object ( node -- )
+    dup node-input-infos first literal>> [
+        "ctx" vm-field-offset ^^vm-field
+        ds-drop swap context-object-offset cell /i 0 ^^slot-imm ds-push
+    ] [ emit-primitive ] ?if ;
 
 : emit-identity-hashcode ( -- )
     ds-pop tag-mask get bitnot ^^load-immediate ^^and 0 0 ^^slot-imm
index 73cfd6b86e8bc29c8330689d91f3ef7bddc32ef4..4208fec0a73fb544f6c88d0456cc7174a536232a 100755 (executable)
@@ -210,7 +210,8 @@ CODEGEN: ##compare-imm %compare-imm
 CODEGEN: ##compare-float-ordered %compare-float-ordered
 CODEGEN: ##compare-float-unordered %compare-float-unordered
 CODEGEN: ##save-context %save-context
-CODEGEN: ##vm-field-ptr %vm-field-ptr
+CODEGEN: ##vm-field %vm-field
+CODEGEN: ##set-vm-field %set-vm-field
 
 CODEGEN: _fixnum-add %fixnum-add
 CODEGEN: _fixnum-sub %fixnum-sub
@@ -458,7 +459,7 @@ M: ##alien-indirect generate-insn
     ! Generate code for boxing input parameters in a callback.
     [
         dup \ %save-param-reg move-parameters
-        %nest-stacks
+        %begin-callback
         box-parameters
     ] with-param-regs ;
 
@@ -482,5 +483,4 @@ M: ##alien-callback generate-insn
     params>>
     [ registers>objects ]
     [ wrap-callback-quot %alien-callback ]
-    [ alien-return [ %unnest-stacks ] [ %callback-value ] if-void ]
-    tri ;
+    [ alien-return [ %end-callback ] [ %end-callback-value ] if-void ] tri ;
index 73e77cca4dd94f074b5f66acb75f9c2ee90d5794..ac0fcff0ffd2fe31af852638b77ff51f30d1b4db 100644 (file)
@@ -28,10 +28,16 @@ CONSTANT: deck-bits 18
 : callstack-length-offset ( -- n ) 1 \ callstack type-number slot-offset ; inline
 : callstack-top-offset ( -- n ) 2 \ callstack type-number slot-offset ; inline
 : vm-context-offset ( -- n ) 0 bootstrap-cells ; inline
+: vm-spare-context-offset ( -- n ) 1 bootstrap-cells ; inline
 : context-callstack-top-offset ( -- n ) 0 bootstrap-cells ; inline
 : context-callstack-bottom-offset ( -- n ) 1 bootstrap-cells ; inline
 : context-datastack-offset ( -- n ) 2 bootstrap-cells ; inline
 : context-retainstack-offset ( -- n ) 3 bootstrap-cells ; inline
+: context-callstack-save-offset ( -- n ) 4 bootstrap-cells ; inline
+: context-callstack-seg-offset ( -- n ) 7 bootstrap-cells ; inline
+: segment-start-offset ( -- n ) 0 bootstrap-cells ; inline
+: segment-size-offset ( -- n ) 1 bootstrap-cells ; inline
+: segment-end-offset ( -- n ) 2 bootstrap-cells ; inline
 
 ! Relocation classes
 CONSTANT: rc-absolute-cell 0
@@ -59,6 +65,7 @@ CONSTANT: rt-megamorphic-cache-hits 8
 CONSTANT: rt-vm 9
 CONSTANT: rt-cards-offset 10
 CONSTANT: rt-decks-offset 11
+CONSTANT: rt-exception-handler 12
 
 : rc-absolute? ( n -- ? )
     ${ rc-absolute-ppc-2/2 rc-absolute-cell rc-absolute } member? ;
index ad8dac3ef95c285042fa9c73be1f4480fa5b2879..ceac1b094c58efdb39b06a6a6f51b08bd1c7bd23 100755 (executable)
@@ -4,7 +4,7 @@ compiler continuations effects io io.backend io.pathnames
 io.streams.string kernel math memory namespaces
 namespaces.private parser quotations sequences
 specialized-arrays stack-checker stack-checker.errors
-system threads tools.test words alien.complex ;
+system threads tools.test words alien.complex concurrency.promises ;
 FROM: alien.c-types => float short ;
 SPECIALIZED-ARRAY: float
 SPECIALIZED-ARRAY: char
@@ -432,14 +432,17 @@ STRUCT: double-rect
     void { void* void* double-rect } "cdecl"
     [ "example" set-global 2drop ] alien-callback ;
 
-: double-rect-test ( arg -- arg' )
-    f f rot
-    double-rect-callback
+: double-rect-test ( arg callback -- arg' )
+    [ f f ] 2dip
     void { void* void* double-rect } "cdecl" alien-indirect
     "example" get-global ;
 
 [ 1.0 2.0 3.0 4.0 ]
-[ 1.0 2.0 3.0 4.0 <double-rect> double-rect-test >double-rect< ] unit-test
+[
+    1.0 2.0 3.0 4.0 <double-rect>
+    double-rect-callback double-rect-test
+    >double-rect<
+] unit-test
 
 STRUCT: test_struct_14
     { x1 double }
@@ -579,6 +582,21 @@ FUNCTION: short ffi_test_48 ( bool-field-test x ) ;
 
 ] unless
 
+! Test interaction between threads and callbacks
+: thread-callback-1 ( -- callback )
+    int { } "cdecl" [ yield 100 ] alien-callback ;
+
+: thread-callback-2 ( -- callback )
+    int { } "cdecl" [ yield 200 ] alien-callback ;
+
+: thread-callback-invoker ( callback -- n )
+    int { } "cdecl" alien-indirect ;
+
+<promise> "p" set
+[ thread-callback-1 thread-callback-invoker "p" get fulfill ] in-thread
+[ 200 ] [ thread-callback-2 thread-callback-invoker ] unit-test
+[ 100 ] [ "p" get ?promise ] unit-test
+
 ! Regression: calling an undefined function would raise a protection fault
 FUNCTION: void this_does_not_exist ( ) ;
 
index 444a4247660fe2dc20ead127694e161e12226fda..ad8a75ecddcbc0785991efc969d3499fae938558 100644 (file)
@@ -467,6 +467,12 @@ TUPLE: fold-boa-test-tuple { x read-only } { y read-only } { z read-only } ;
 [ [ 1 2 3 fold-boa-test-tuple boa ] final-literals ]
 unit-test
 
+TUPLE: don't-fold-boa-test-tuple < identity-tuple ;
+
+[ V{ f } ]
+[ [ don't-fold-boa-test-tuple boa ] final-literals ]
+unit-test
+
 TUPLE: immutable-prop-test-tuple { x sequence read-only } ;
 
 [ V{ T{ immutable-prop-test-tuple f "hey" } } ] [
index 2602d6d59a9ed7ebd6830514c855aa2ffbd587e4..14546f0237dca9926e8f175536847086cd47ca6c 100644 (file)
@@ -34,17 +34,18 @@ IN: compiler.tree.propagation.slots
     [ read-only>> [ value-info ] [ drop f ] if ] 2map
     f prefix ;
 
-: (propagate-tuple-constructor) ( values class -- info )
-    [ read-only-slots ] keep
-    over rest-slice [ dup [ literal?>> ] when ] all? [
-        [ rest-slice ] dip fold-<tuple-boa>
-    ] [
-        <tuple-info>
-    ] if ;
+: fold-<tuple-boa>? ( values class -- ? )
+    [ rest-slice [ dup [ literal?>> ] when ] all? ]
+    [ identity-tuple class<= not ]
+    bi* and ;
+
+: (propagate-<tuple-boa>) ( values class -- info )
+    [ read-only-slots ] keep 2dup fold-<tuple-boa>?
+    [ [ rest-slice ] dip fold-<tuple-boa> ] [ <tuple-info> ] if ;
 
 : propagate-<tuple-boa> ( #call -- infos )
     in-d>> unclip-last
-    value-info literal>> first (propagate-tuple-constructor) 1array ;
+    value-info literal>> first (propagate-<tuple-boa>) 1array ;
 
 : read-only-slot? ( n class -- ? )
     all-slots [ offset>> = ] with find nip
index ad00bbdfa9ff262ca7f36af3248efc478c81f4c5..2fb75226eb2e44272ffdbf82fc6e164204c57302 100644 (file)
@@ -1,13 +1,13 @@
-! Copyright (C) 2008 Slava Pestov.\r
+! Copyright (C) 2008, 2010 Slava Pestov.\r
 ! See http://factorcode.org/license.txt for BSD license.\r
 USING: deques threads kernel arrays sequences alarms fry ;\r
 IN: concurrency.conditions\r
 \r
 : notify-1 ( deque -- )\r
-    dup deque-empty? [ drop ] [ pop-back resume-now ] if ;\r
+    dup deque-empty? [ drop ] [ pop-back resume-now ] if ; inline\r
 \r
 : notify-all ( deque -- )\r
-    [ resume-now ] slurp-deque ;\r
+    [ resume-now ] slurp-deque ; inline\r
 \r
 : queue-timeout ( queue timeout -- alarm )\r
     #! Add an alarm which removes the current thread from the\r
@@ -22,10 +22,13 @@ IN: concurrency.conditions
 \r
 ERROR: wait-timeout ;\r
 \r
+: queue ( queue -- )\r
+    [ self ] dip push-front ; inline\r
+\r
 : wait ( queue timeout status -- )\r
     over [\r
-        [ queue-timeout [ drop ] ] dip suspend\r
+        [ queue-timeout ] dip suspend\r
         [ wait-timeout ] [ cancel-alarm ] if\r
     ] [\r
-        [ drop '[ _ push-front ] ] dip suspend drop\r
-    ] if ;\r
+        [ drop queue ] dip suspend drop\r
+    ] if ; inline\r
index 0015b10cef444c70b0903a24545f177a7acc6981..229cea85480fa5a223eab0fe49b7e826604905bc 100644 (file)
@@ -20,7 +20,7 @@ PRIVATE>
     registered-remote-threads delete-at ;
 
 : get-remote-thread ( name -- thread )
-    dup registered-remote-threads at [ ] [ thread ] ?if ;
+    dup registered-remote-threads at [ ] [ threads at ] ?if ;
 
 SYMBOL: local-node
 
index 97b3c14fe41cd29c4ac1185119b10463fcece045..7cfe01608529082aa7055e4b9c81ae7749697dfe 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2008 Slava Pestov.\r
+! Copyright (C) 2008, 2010 Slava Pestov.\r
 ! See http://factorcode.org/license.txt for BSD license.\r
 USING: kernel threads boxes accessors fry ;\r
 IN: concurrency.exchangers\r
@@ -17,5 +17,6 @@ TUPLE: exchanger thread object ;
         [ thread>> box> resume-with ] dip\r
     ] [\r
         [ object>> >box ] keep\r
-        '[ _ thread>> >box ] "exchange" suspend\r
+        [ self ] dip thread>> >box\r
+        "exchange" suspend\r
     ] if ;\r
index e245f93bd5f86f7169668e9a5fb7b5abd5e12852..163873575c9f4b11f7069bf99a290aef6b46aee9 100644 (file)
@@ -6,22 +6,24 @@ concurrency.conditions accessors debugger debugger.threads
 locals fry ;
 IN: concurrency.mailboxes
 
-TUPLE: mailbox threads data ;
+TUPLE: mailbox { threads dlist } { data dlist } ;
 
 : <mailbox> ( -- mailbox )
     mailbox new
         <dlist> >>threads
-        <dlist> >>data ;
+        <dlist> >>data ; inline
 
 : mailbox-empty? ( mailbox -- bool )
-    data>> deque-empty? ;
+    data>> deque-empty? ; inline
 
-: mailbox-put ( obj mailbox -- )
+GENERIC: mailbox-put ( obj mailbox -- )
+
+M: mailbox mailbox-put
     [ data>> push-front ]
     [ threads>> notify-all ] bi yield ;
 
 : wait-for-mailbox ( mailbox timeout -- )
-    [ threads>> ] dip "mailbox" wait ;
+    [ threads>> ] dip "mailbox" wait ; inline
 
 :: block-unless-pred ( ... mailbox timeout pred: ( ... message -- ... ? ) -- ... )
     mailbox data>> pred dlist-any? [
@@ -34,16 +36,17 @@ TUPLE: mailbox threads data ;
         2dup wait-for-mailbox block-if-empty
     ] [
         drop
-    ] if ;
+    ] if ; inline recursive
 
 : mailbox-peek ( mailbox -- obj )
     data>> peek-back ;
 
-: mailbox-get-timeout ( mailbox timeout -- obj )
-    block-if-empty data>> pop-back ;
+GENERIC# mailbox-get-timeout 1 ( mailbox timeout -- obj )
+
+M: mailbox mailbox-get-timeout block-if-empty data>> pop-back ;
 
 : mailbox-get ( mailbox -- obj )
-    f mailbox-get-timeout ;
+    f mailbox-get-timeout ; inline
 
 : mailbox-get-all-timeout ( mailbox timeout -- array )
     block-if-empty
index 37965309e8b4f1a41fbf966bea242eb81ae4a2db..3f55b0969b2705d97ed8edbb1caead9c942423f4 100644 (file)
@@ -1,20 +1,22 @@
-! Copyright (C) 2005, 2008 Chris Double, Slava Pestov.\r
+! Copyright (C) 2005, 2010 Chris Double, Slava Pestov.\r
 ! See http://factorcode.org/license.txt for BSD license.\r
-USING: kernel threads concurrency.mailboxes continuations\r
-namespaces assocs accessors summary fry ;\r
+USING: kernel kernel.private threads concurrency.mailboxes\r
+continuations namespaces assocs accessors summary fry ;\r
 IN: concurrency.messaging\r
 \r
 GENERIC: send ( message thread -- )\r
 \r
-: mailbox-of ( thread -- mailbox )\r
-    dup mailbox>> [ ] [\r
-        <mailbox> [ >>mailbox drop ] keep\r
-    ] ?if ;\r
+GENERIC: mailbox-of ( thread -- mailbox )\r
+\r
+M: thread mailbox-of\r
+    dup mailbox>>\r
+    [ { mailbox } declare ]\r
+    [ <mailbox> [ >>mailbox drop ] keep ] ?if ; inline\r
 \r
 M: thread send ( message thread -- )\r
-    check-registered mailbox-of mailbox-put ;\r
+    mailbox-of mailbox-put ;\r
 \r
-: my-mailbox ( -- mailbox ) self mailbox-of ;\r
+: my-mailbox ( -- mailbox ) self mailbox-of ; inline\r
 \r
 : receive ( -- message )\r
     my-mailbox mailbox-get ?linked ;\r
index ec5581d4633237cd40d36912344401ae4e90b303..4ec362f0fcec48e7443f9334d5b4e8eb7cef36d7 100644 (file)
@@ -1,6 +1,7 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien.c-types alien.syntax kernel math.bitwise core-foundation ;
+USING: alien.c-types alien.syntax kernel math.bitwise core-foundation
+literals ;
 IN: core-foundation.file-descriptors
 
 TYPEDEF: void* CFFileDescriptorRef
@@ -25,7 +26,7 @@ FUNCTION: void CFFileDescriptorEnableCallBacks (
 ) ;
 
 : enable-all-callbacks ( fd -- )
-    { kCFFileDescriptorReadCallBack kCFFileDescriptorWriteCallBack } flags
+    flags{ kCFFileDescriptorReadCallBack kCFFileDescriptorWriteCallBack }
     CFFileDescriptorEnableCallBacks ;
 
 : <CFFileDescriptor> ( fd callback -- handle )
index f3f759115cc2204ccab25a097ffaf23f35e27f9d..1b7693da142081b62ff765af7e9e693dd928737f 100644 (file)
@@ -3,7 +3,7 @@
 USING: alien alien.c-types alien.destructors alien.syntax accessors
 destructors fry kernel math math.bitwise sequences libc colors
 images images.memory core-graphics.types core-foundation.utilities
-opengl.gl ;
+opengl.gl literals ;
 IN: core-graphics
 
 ! CGImageAlphaInfo
@@ -16,15 +16,15 @@ kCGImageAlphaFirst
 kCGImageAlphaNoneSkipLast
 kCGImageAlphaNoneSkipFirst ;
 
-: kCGBitmapAlphaInfoMask ( -- n ) HEX: 1f ; inline
-: kCGBitmapFloatComponents ( -- n ) 1 8 shift ; inline
+CONSTANT: kCGBitmapAlphaInfoMask HEX: 1f
+CONSTANT: kCGBitmapFloatComponents 256
 
-: kCGBitmapByteOrderMask ( -- n ) HEX: 7000 ; inline
-: kCGBitmapByteOrderDefault ( -- n ) 0 12 shift ; inline
-: kCGBitmapByteOrder16Little ( -- n ) 1 12 shift ; inline
-: kCGBitmapByteOrder32Little ( -- n ) 2 12 shift ; inline
-: kCGBitmapByteOrder16Big ( -- n ) 3 12 shift ; inline
-: kCGBitmapByteOrder32Big ( -- n ) 4 12 shift ; inline
+CONSTANT: kCGBitmapByteOrderMask HEX: 7000
+CONSTANT: kCGBitmapByteOrderDefault 0
+CONSTANT: kCGBitmapByteOrder16Little 4096
+CONSTANT: kCGBitmapByteOrder32Little 8192
+CONSTANT: kCGBitmapByteOrder16Big 12288
+CONSTANT: kCGBitmapByteOrder32Big 16384
 
 : kCGBitmapByteOrder16Host ( -- n )
     little-endian?
@@ -121,8 +121,8 @@ FUNCTION: uint GetCurrentButtonState ( ) ;
 
 <PRIVATE
 
-: bitmap-flags ( -- flags )
-    { kCGImageAlphaPremultipliedFirst kCGBitmapByteOrder32Host } flags ;
+: bitmap-flags ( -- n )
+    kCGImageAlphaPremultipliedFirst kCGBitmapByteOrder32Host bitor ;
 
 : bitmap-color-space ( -- color-space )
     CGColorSpaceCreateDeviceRGB &CGColorSpaceRelease ;
index 4d99b5a0edcea0591f32f60cd6cba923f2c359b5..ad1a4be2eb072f67966b5b641813c1a343965d75 100644 (file)
@@ -447,8 +447,10 @@ HOOK: %set-alien-double    cpu ( ptr offset value -- )
 HOOK: %set-alien-vector    cpu ( ptr offset value rep -- )
 
 HOOK: %alien-global cpu ( dst symbol library -- )
-HOOK: %vm-field cpu ( dst fieldname -- )
-HOOK: %vm-field-ptr cpu ( dst fieldname -- )
+HOOK: %vm-field cpu ( dst offset -- )
+HOOK: %set-vm-field cpu ( src offset -- )
+
+: %context ( dst -- ) 0 %vm-field ;
 
 HOOK: %allot cpu ( dst size class temp -- )
 HOOK: %write-barrier cpu ( src slot temp1 temp2 -- )
@@ -582,13 +584,13 @@ HOOK: %prepare-alien-indirect cpu ( -- )
 
 HOOK: %alien-indirect cpu ( -- )
 
-HOOK: %alien-callback cpu ( quot -- )
+HOOK: %begin-callback cpu ( -- )
 
-HOOK: %callback-value cpu ( ctype -- )
+HOOK: %alien-callback cpu ( quot -- )
 
-HOOK: %nest-stacks cpu ( -- )
+HOOK: %end-callback cpu ( -- )
 
-HOOK: %unnest-stacks cpu ( -- )
+HOOK: %end-callback-value cpu ( c-type -- )
 
 HOOK: callback-return-rewind cpu ( params -- n )
 
index b2ae9c4e73afd6d2d54b48d5ecdd2cee265ab58f..f7a1917d0e9fb7eafa0e5fb81f94a79a49bf2449 100644 (file)
@@ -3,7 +3,8 @@
 USING: bootstrap.image.private kernel kernel.private namespaces\r
 system cpu.ppc.assembler compiler.units compiler.constants math\r
 math.private math.ranges layouts words vocabs slots.private\r
-locals locals.backend generic.single.private fry sequences ;\r
+locals locals.backend generic.single.private fry sequences\r
+threads.private ;\r
 FROM: cpu.ppc.assembler => B ;\r
 IN: bootstrap.ppc\r
 \r
@@ -14,6 +15,22 @@ CONSTANT: ds-reg 13
 CONSTANT: rs-reg 14\r
 CONSTANT: vm-reg 15\r
 CONSTANT: ctx-reg 16\r
+CONSTANT: nv-reg 17\r
+\r
+: jit-call ( string -- )\r
+    0 2 LOAD32 rc-absolute-ppc-2/2 jit-dlsym\r
+    2 MTLR\r
+    BLRL ;\r
+\r
+: jit-call-quot ( -- )\r
+    4 3 quot-entry-point-offset LWZ\r
+    4 MTLR\r
+    BLRL ;\r
+\r
+: jit-jump-quot ( -- )\r
+    4 3 quot-entry-point-offset LWZ\r
+    4 MTCTR\r
+    BCTR ;\r
 \r
 : factor-area-size ( -- n ) 16 ;\r
 \r
@@ -52,29 +69,71 @@ CONSTANT: ctx-reg 16
     saved-int-regs-size +\r
     saved-fp-regs-size +\r
     saved-vec-regs-size +\r
+    4 +\r
     16 align ;\r
 \r
+: old-context-save-offset ( -- n )\r
+    432 save-at ;\r
+\r
 [\r
+    ! Save old stack pointer\r
+    11 1 MR\r
+\r
+    ! Create stack frame\r
     0 MFLR\r
-    1 1 callback-frame-size neg STWU\r
+    1 1 callback-frame-size SUBI\r
     0 1 callback-frame-size lr-save + STW\r
 \r
+    ! Save all non-volatile registers\r
     nv-int-regs [ 4 * save-int ] each-index\r
     nv-fp-regs [ 8 * 80 + save-fp ] each-index\r
     nv-vec-regs [ 16 * 224 + save-vec ] each-index\r
 \r
+    ! Stick old stack pointer in a non-volatile register so that\r
+    ! callbacks can access their arguments\r
+    nv-reg 11 MR\r
+\r
+    ! Load VM into vm-reg\r
     0 vm-reg LOAD32 rc-absolute-ppc-2/2 rt-vm jit-rel\r
 \r
+    ! Save old context\r
+    2 vm-reg vm-context-offset LWZ\r
+    2 1 old-context-save-offset STW\r
+\r
+    ! Switch over to the spare context\r
+    2 vm-reg vm-spare-context-offset LWZ\r
+    2 vm-reg vm-context-offset STW\r
+\r
+    ! Save C callstack pointer\r
+    1 2 context-callstack-save-offset STW\r
+\r
+    ! Load Factor callstack pointer\r
+    1 2 context-callstack-bottom-offset LWZ\r
+\r
+    ! Call into Factor code\r
     0 2 LOAD32 rc-absolute-ppc-2/2 rt-entry-point jit-rel\r
     2 MTLR\r
     BLRL\r
 \r
+    ! Load VM again, pointlessly\r
+    0 vm-reg LOAD32 rc-absolute-ppc-2/2 rt-vm jit-rel\r
+\r
+    ! Load C callstack pointer\r
+    2 vm-reg vm-context-offset LWZ\r
+    1 2 context-callstack-save-offset LWZ\r
+\r
+    ! Load old context\r
+    2 1 old-context-save-offset LWZ\r
+    2 vm-reg vm-context-offset STW\r
+\r
+    ! Restore non-volatile registers\r
     nv-vec-regs [ 16 * 224 + restore-vec ] each-index\r
     nv-fp-regs [ 8 * 80 + restore-fp ] each-index\r
     nv-int-regs [ 4 * restore-int ] each-index\r
 \r
+    ! Tear down stack frame and return\r
     0 1 callback-frame-size lr-save + LWZ\r
-    1 1 0 LWZ\r
+    1 1 callback-frame-size ADDI\r
     0 MTLR\r
     BLR\r
 ] callback-stub jit-define\r
@@ -92,7 +151,6 @@ CONSTANT: ctx-reg 16
     rs-reg ctx-reg context-retainstack-offset STW ;\r
 \r
 : jit-restore-context ( -- )\r
-    jit-load-context\r
     ds-reg ctx-reg context-datastack-offset LWZ\r
     rs-reg ctx-reg context-retainstack-offset LWZ ;\r
 \r
@@ -267,9 +325,8 @@ CONSTANT: ctx-reg 16
     jit-save-context\r
     3 6 MR\r
     4 vm-reg MR\r
-    0 5 LOAD32 "inline_cache_miss" f rc-absolute-ppc-2/2 jit-dlsym\r
-    5 MTLR\r
-    BLRL\r
+    "inline_cache_miss" jit-call\r
+    jit-load-context\r
     jit-restore-context ;\r
 \r
 [ jit-load-return-address jit-inline-cache-miss ]\r
@@ -321,10 +378,9 @@ CONSTANT: ctx-reg 16
 [\r
     3 ds-reg 0 LWZ\r
     ds-reg dup 4 SUBI\r
-    5 3 quot-entry-point-offset LWZ\r
 ]\r
-[ 5 MTLR BLRL ]\r
-[ 5 MTCTR BCTR ] \ (call) define-combinator-primitive\r
+[ jit-call-quot ]\r
+[ jit-jump-quot ] \ (call) define-combinator-primitive\r
 \r
 [\r
     3 ds-reg 0 LWZ\r
@@ -343,14 +399,22 @@ CONSTANT: ctx-reg 16
 \r
 ! Special primitives\r
 [\r
+    nv-reg 3 MR\r
+\r
+    3 vm-reg MR\r
+    "begin_callback" jit-call\r
+\r
+    jit-load-context\r
     jit-restore-context\r
-    ! Save ctx->callstack_bottom\r
-    1 ctx-reg context-callstack-bottom-offset STW\r
+\r
     ! Call quotation\r
-    5 3 quot-entry-point-offset LWZ\r
-    5 MTLR\r
-    BLRL\r
+    3 nv-reg MR\r
+    jit-call-quot\r
+\r
     jit-save-context\r
+\r
+    3 vm-reg MR\r
+    "end_callback" jit-call\r
 ] \ c-to-factor define-sub-primitive\r
 \r
 [\r
@@ -362,6 +426,7 @@ CONSTANT: ctx-reg 16
     0 vm-reg LOAD32 0 rc-absolute-ppc-2/2 jit-vm\r
 \r
     ! Load ds and rs registers\r
+    jit-load-context\r
     jit-restore-context\r
 \r
     ! We have changed the stack; load return address again\r
@@ -369,9 +434,7 @@ CONSTANT: ctx-reg 16
     0 MTLR\r
 \r
     ! Call quotation\r
-    4 3 quot-entry-point-offset LWZ\r
-    4 MTCTR\r
-    BCTR\r
+    jit-call-quot\r
 ] \ unwind-native-frames define-sub-primitive\r
 \r
 [\r
@@ -392,9 +455,7 @@ CONSTANT: ctx-reg 16
     1 3 MR\r
     ! Call memcpy; arguments are now in the correct registers\r
     1 1 -64 STWU\r
-    0 2 LOAD32 "factor_memcpy" f rc-absolute-ppc-2/2 jit-dlsym\r
-    2 MTLR\r
-    BLRL\r
+    "factor_memcpy" jit-call\r
     1 1 0 LWZ\r
     ! Return with new callstack\r
     0 1 lr-save LWZ\r
@@ -405,13 +466,10 @@ CONSTANT: ctx-reg 16
 [\r
     jit-save-context\r
     4 vm-reg MR\r
-    0 2 LOAD32 "lazy_jit_compile" f rc-absolute-ppc-2/2 jit-dlsym\r
-    2 MTLR\r
-    BLRL\r
-    5 3 quot-entry-point-offset LWZ\r
+    "lazy_jit_compile" jit-call\r
 ]\r
-[ 5 MTLR BLRL ]\r
-[ 5 MTCTR BCTR ]\r
+[ jit-call-quot ]\r
+[ jit-jump-quot ]\r
 \ lazy-jit-compile define-combinator-primitive\r
 \r
 ! Objects\r
@@ -665,9 +723,7 @@ CONSTANT: ctx-reg 16
     [ BNO ]\r
     [\r
         5 vm-reg MR\r
-        0 6 LOAD32 func f rc-absolute-ppc-2/2 jit-dlsym\r
-        6 MTLR\r
-        BLRL\r
+        func jit-call\r
     ]\r
     jit-conditional* ;\r
 \r
@@ -689,11 +745,78 @@ CONSTANT: ctx-reg 16
     [\r
         4 4 tag-bits get SRAWI\r
         5 vm-reg MR\r
-        0 6 LOAD32 "overflow_fixnum_multiply" f rc-absolute-ppc-2/2 jit-dlsym\r
-        6 MTLR\r
-        BLRL\r
+        "overflow_fixnum_multiply" jit-call\r
     ]\r
     jit-conditional*\r
 ] \ fixnum* define-sub-primitive\r
 \r
+! Contexts\r
+: jit-switch-context ( reg -- )\r
+    ! Save ds, rs registers\r
+    jit-save-context\r
+\r
+    ! Make the new context the current one\r
+    ctx-reg swap MR\r
+    ctx-reg vm-reg vm-context-offset STW\r
+\r
+    ! Load new stack pointer\r
+    1 ctx-reg context-callstack-top-offset LWZ\r
+\r
+    ! Load new ds, rs registers\r
+    jit-restore-context ;\r
+\r
+: jit-pop-context-and-param ( -- )\r
+    3 ds-reg 0 LWZ\r
+    3 3 alien-offset LWZ\r
+    4 ds-reg -4 LWZ\r
+    ds-reg ds-reg 8 SUBI ;\r
+\r
+: jit-push-param ( -- )\r
+    ds-reg ds-reg 4 ADDI\r
+    4 ds-reg 0 STW ;\r
+\r
+: jit-set-context ( -- )\r
+    jit-pop-context-and-param\r
+    3 jit-switch-context\r
+    jit-push-param ;\r
+\r
+[ jit-set-context ] \ (set-context) define-sub-primitive\r
+\r
+: jit-pop-quot-and-param ( -- )\r
+    3 ds-reg 0 LWZ\r
+    4 ds-reg -4 LWZ\r
+    ds-reg ds-reg 8 SUBI ;\r
+\r
+: jit-start-context ( -- )\r
+    ! Create the new context in return-reg\r
+    3 vm-reg MR\r
+    "new_context" jit-call\r
+    6 3 MR\r
+\r
+    jit-pop-quot-and-param\r
+\r
+    6 jit-switch-context\r
+\r
+    jit-push-param\r
+\r
+    jit-jump-quot ;\r
+\r
+[ jit-start-context ] \ (start-context) define-sub-primitive\r
+\r
+: jit-delete-current-context ( -- )\r
+    jit-load-context\r
+    3 vm-reg MR\r
+    4 ctx-reg MR\r
+    "delete_context" jit-call ;\r
+\r
+[\r
+    jit-delete-current-context\r
+    jit-set-context\r
+] \ (set-context-and-delete) define-sub-primitive\r
+\r
+[\r
+    jit-delete-current-context\r
+    jit-start-context\r
+] \ (start-context-and-delete) define-sub-primitive\r
+\r
 [ "bootstrap.ppc" forget-vocab ] with-compilation-unit\r
index 6d84aad8d50bd2a422e722ad3a71dc0aee555589..cf8a8323861b48d6bfce055c6af12dc672b904f5 100644 (file)
@@ -58,11 +58,9 @@ CONSTANT: vm-reg 15
 
 : %load-vm-addr ( reg -- ) vm-reg MR ;
 
-M: ppc %vm-field ( dst field -- )
-    [ vm-reg ] dip vm-field-offset LWZ ;
+M: ppc %vm-field ( dst field -- ) [ vm-reg ] dip LWZ ;
 
-M: ppc %vm-field-ptr ( dst field -- )
-    [ vm-reg ] dip vm-field-offset ADDI ;
+M: ppc %set-vm-field ( src field -- ) [ vm-reg ] dip STW ;
 
 GENERIC: loc-reg ( loc -- reg )
 
@@ -385,7 +383,7 @@ M: ppc %set-alien-float -rot STFS ;
 M: ppc %set-alien-double -rot STFD ;
 
 : load-zone-ptr ( reg -- )
-    "nursery" %vm-field-ptr ;
+    vm-reg "nursery" vm-field-offset ADDI ;
 
 : load-allot-ptr ( nursery-ptr allot-ptr -- )
     [ drop load-zone-ptr ] [ swap 0 LWZ ] 2bi ;
@@ -567,8 +565,7 @@ M:: ppc %compare-float-unordered-branch ( label src1 src2 cc -- )
     } case ;
 
 : next-param@ ( n -- reg x )
-    2 1 stack-frame get total-size>> LWZ
-    [ 2 ] dip param@ ;
+    [ 17 ] dip param@ ;
 
 : store-to-frame ( src n rep -- )
     {
@@ -604,14 +601,14 @@ M: ppc %push-stack ( -- )
     int-regs return-reg ds-reg 0 STW ;
 
 M: ppc %push-context-stack ( -- )
-    11 "ctx" %vm-field
+    11 %context
     12 11 "datastack" context-field-offset LWZ
     12 12 4 ADDI
     12 11 "datastack" context-field-offset STW
     int-regs return-reg 12 0 STW ;
 
 M: ppc %pop-context-stack ( -- )
-    11 "ctx" %vm-field
+    11 %context
     12 11 "datastack" context-field-offset LWZ
     int-regs return-reg 12 0 LWZ
     12 12 4 SUBI
@@ -677,14 +674,12 @@ M: ppc %box-large-struct ( n c-type -- )
     "from_value_struct" f %alien-invoke ;
 
 M:: ppc %restore-context ( temp1 temp2 -- )
-    temp1 "ctx" %vm-field
-    temp2 1 stack-frame get total-size>> ADDI
-    temp2 temp1 "callstack-bottom" context-field-offset STW
+    temp1 %context
     ds-reg temp1 "datastack" context-field-offset LWZ
     rs-reg temp1 "retainstack" context-field-offset LWZ ;
 
 M:: ppc %save-context ( temp1 temp2 -- )
-    temp1 "ctx" %vm-field
+    temp1 %context
     1 temp1 "callstack-top" context-field-offset STW
     ds-reg temp1 "datastack" context-field-offset STW
     rs-reg temp1 "retainstack" context-field-offset STW ;
@@ -692,14 +687,6 @@ M:: ppc %save-context ( temp1 temp2 -- )
 M: ppc %alien-invoke ( symbol dll -- )
     [ 11 ] 2dip %alien-global 11 MTLR BLRL ;
 
-M: ppc %alien-callback ( quot -- )
-    3 4 %restore-context
-    3 swap %load-reference
-    4 3 quot-entry-point-offset LWZ
-    4 MTLR
-    BLRL
-    3 4 %save-context ;
-
 M: ppc %prepare-alien-indirect ( -- )
     3 ds-reg 0 LWZ
     ds-reg ds-reg 4 SUBI
@@ -710,18 +697,6 @@ M: ppc %prepare-alien-indirect ( -- )
 M: ppc %alien-indirect ( -- )
     16 MTLR BLRL ;
 
-M: ppc %callback-value ( ctype -- )
-    ! Save top of data stack
-    3 ds-reg 0 LWZ
-    3 1 0 local@ STW
-    3 %load-vm-addr
-    ! Restore data/call/retain stacks
-    "unnest_stacks" f %alien-invoke
-    ! Restore top of data stack
-    3 1 0 local@ LWZ
-    ! Unbox former top of data stack to return registers
-    unbox-return ;
-
 M: ppc immediate-arithmetic? ( n -- ? ) -32768 32767 between? ;
 
 M: ppc immediate-bitwise? ( n -- ? ) 0 65535 between? ;
@@ -757,13 +732,30 @@ M: ppc %box-small-struct ( c-type -- )
     4 3 4 LWZ
     3 3 0 LWZ ;
 
-M: ppc %nest-stacks ( -- )
+M: ppc %begin-callback ( -- )
     3 %load-vm-addr
-    "nest_stacks" f %alien-invoke ;
+    "begin_callback" f %alien-invoke ;
+
+M: ppc %alien-callback ( quot -- )
+    3 4 %restore-context
+    3 swap %load-reference
+    4 3 quot-entry-point-offset LWZ
+    4 MTLR
+    BLRL
+    3 4 %save-context ;
 
-M: ppc %unnest-stacks ( -- )
+M: ppc %end-callback ( -- )
     3 %load-vm-addr
-    "unnest_stacks" f %alien-invoke ;
+    "end_callback" f %alien-invoke ;
+
+M: ppc %end-callback-value ( ctype -- )
+    ! Save top of data stack
+    16 ds-reg 0 LWZ
+    %end-callback
+    ! Restore top of data stack
+    3 16 MR
+    ! Unbox former top of data stack to return registers
+    unbox-return ;
 
 M: ppc %unbox-small-struct ( size -- )
     heap-size cell align cell /i {
index b8b621ee11eee419c3d21bad2a8a9c218ada3a16..97f0cfb66845e4b7e08a3bd75c4cba789956ac27 100755 (executable)
@@ -28,10 +28,13 @@ M: x86.32 %mov-vm-ptr ( reg -- )
     0 MOV 0 rc-absolute-cell rel-vm ;
 
 M: x86.32 %vm-field ( dst field -- )
-    [ 0 [] MOV ] dip vm-field-offset rc-absolute-cell rel-vm ;
+    [ 0 [] MOV ] dip rc-absolute-cell rel-vm ;
+
+M: x86.32 %set-vm-field ( dst field -- )
+    [ 0 [] swap MOV ] dip rc-absolute-cell rel-vm ;
 
 M: x86.32 %vm-field-ptr ( dst field -- )
-    [ 0 MOV ] dip vm-field-offset rc-absolute-cell rel-vm ;
+    [ 0 MOV ] dip rc-absolute-cell rel-vm ;
 
 : local@ ( n -- op )
     stack-frame get extra-stack-space dup 16 assert= + stack@ ;
@@ -166,7 +169,7 @@ M: x86.32 %pop-stack ( n -- )
     EAX swap ds-reg reg-stack MOV ;
 
 M: x86.32 %pop-context-stack ( -- )
-    temp-reg "ctx" %vm-field
+    temp-reg %context
     EAX temp-reg "datastack" context-field-offset [+] MOV
     EAX EAX [] MOV
     temp-reg "datastack" context-field-offset [+] bootstrap-cell SUB ;
@@ -228,14 +231,6 @@ M:: x86.32 %unbox-large-struct ( n c-type -- )
     0 stack@ EAX MOV
     "to_value_struct" f %alien-invoke ;
 
-M: x86.32 %nest-stacks ( -- )
-    0 save-vm-ptr
-    "nest_stacks" f %alien-invoke ;
-
-M: x86.32 %unnest-stacks ( -- )
-    0 save-vm-ptr
-    "unnest_stacks" f %alien-invoke ;
-
 M: x86.32 %prepare-alien-indirect ( -- )
     EAX ds-reg [] MOV
     ds-reg 4 SUB
@@ -247,18 +242,25 @@ M: x86.32 %prepare-alien-indirect ( -- )
 M: x86.32 %alien-indirect ( -- )
     EBP CALL ;
 
+M: x86.32 %begin-callback ( -- )
+    0 save-vm-ptr
+    ESP 4 [+] 0 MOV
+    "begin_callback" f %alien-invoke ;
+
 M: x86.32 %alien-callback ( quot -- )
     EAX EDX %restore-context
     EAX swap %load-reference
     EAX quot-entry-point-offset [+] CALL
     EAX EDX %save-context ;
 
-M: x86.32 %callback-value ( ctype -- )
+M: x86.32 %end-callback ( -- )
+    0 save-vm-ptr
+    "end_callback" f %alien-invoke ;
+
+M: x86.32 %end-callback-value ( ctype -- )
     %pop-context-stack
     4 stack@ EAX MOV
-    0 save-vm-ptr
-    ! Restore data/call/retain stacks
-    "unnest_stacks" f %alien-invoke
+    %end-callback
     ! Place former top of data stack back in EAX
     EAX 4 stack@ MOV
     ! Unbox EAX
index cf2d09501ccd1524010e520bdf56b5cb46978fdf..9b1a1de23dc6de804065ebc9dbee4909cd071473 100644 (file)
@@ -3,7 +3,7 @@
 USING: bootstrap.image.private kernel kernel.private namespaces
 system cpu.x86.assembler cpu.x86.assembler.operands layouts
 vocabs parser compiler.constants sequences math math.private
-generic.single.private ;
+generic.single.private threads.private ;
 IN: bootstrap.x86
 
 4 \ cell set
@@ -16,17 +16,20 @@ IN: bootstrap.x86
 : temp1 ( -- reg ) EDX ;
 : temp2 ( -- reg ) ECX ;
 : temp3 ( -- reg ) EBX ;
-: safe-reg ( -- reg ) EAX ;
 : stack-reg ( -- reg ) ESP ;
 : frame-reg ( -- reg ) EBP ;
 : vm-reg ( -- reg ) ECX ;
 : ctx-reg ( -- reg ) EBP ;
 : nv-regs ( -- seq ) { ESI EDI EBX } ;
+: nv-reg ( -- reg ) EBX ;
 : ds-reg ( -- reg ) ESI ;
 : rs-reg ( -- reg ) EDI ;
 : fixnum>slot@ ( -- ) temp0 2 SAR ;
 : rex-length ( -- n ) 0 ;
 
+: jit-call ( name -- )
+    0 CALL rc-relative jit-dlsym ;
+
 [
     ! save stack frame size
     stack-frame-size PUSH
@@ -49,7 +52,8 @@ IN: bootstrap.x86
     ctx-reg vm-reg vm-context-offset [+] MOV ;
 
 : jit-save-context ( -- )
-    EDX RSP -4 [+] LEA
+    jit-load-context
+    EDX ESP -4 [+] LEA
     ctx-reg context-callstack-top-offset [+] EDX MOV
     ctx-reg context-datastack-offset [+] ds-reg MOV
     ctx-reg context-retainstack-offset [+] rs-reg MOV ;
@@ -59,40 +63,59 @@ IN: bootstrap.x86
     rs-reg ctx-reg context-retainstack-offset [+] MOV ;
 
 [
+    ! ctx-reg is preserved across the call because it is non-volatile
+    ! in the C ABI
     jit-load-vm
-    jit-load-context
     jit-save-context
     ! call the primitive
     ESP [] vm-reg MOV
     0 CALL rc-relative rt-dlsym jit-rel
-    ! restore ds, rs registers
     jit-restore-context
 ] jit-primitive jit-define
 
+: jit-jump-quot ( -- )
+    EAX quot-entry-point-offset [+] JMP ;
+
+: jit-call-quot ( -- )
+    EAX quot-entry-point-offset [+] CALL ;
+
 [
-    ! Load quotation
+    jit-load-vm
+    ESP [] vm-reg MOV
     EAX EBP 8 [+] MOV
-    ! save ctx->callstack_bottom, load ds, rs registers
+    ESP 4 [+] EAX MOV
+    "begin_callback" jit-call
+
     jit-load-vm
     jit-load-context
     jit-restore-context
-    EDX stack-reg stack-frame-size 4 - [+] LEA
-    ctx-reg context-callstack-bottom-offset [+] EDX MOV
-    ! call the quotation
-    EAX quot-entry-point-offset [+] CALL
-    ! save ds, rs registers
+
+    jit-call-quot
+
+    jit-load-vm
     jit-save-context
+
+    ESP [] vm-reg MOV
+    "end_callback" jit-call
 ] \ c-to-factor define-sub-primitive
 
 [
     EAX ds-reg [] MOV
     ds-reg bootstrap-cell SUB
 ]
-[ EAX quot-entry-point-offset [+] CALL ]
-[ EAX quot-entry-point-offset [+] JMP ]
+[ jit-call-quot ]
+[ jit-jump-quot ]
 \ (call) define-combinator-primitive
 
 [
+    ! Load ds and rs registers
+    jit-load-vm
+    jit-load-context
+    jit-restore-context
+
+    ! Windows-specific setup
+    ctx-reg jit-update-seh
+
     ! Clear x87 stack, but preserve rounding mode and exception flags
     ESP 2 SUB
     ESP [] FNSTCW
@@ -107,13 +130,7 @@ IN: bootstrap.x86
     ! Unwind stack frames
     ESP EDX MOV
 
-    ! Load ds and rs registers
-    jit-load-vm
-    jit-load-context
-    jit-restore-context
-
-    ! Call quotation
-    EAX quot-entry-point-offset [+] JMP
+    jit-jump-quot
 ] \ unwind-native-frames define-sub-primitive
 
 [
@@ -137,7 +154,7 @@ IN: bootstrap.x86
     EDX PUSH
     EBP PUSH
     EAX PUSH
-    0 CALL "factor_memcpy" f rc-relative jit-dlsym
+    "factor_memcpy" jit-call
     ESP 12 ADD
     ! Return with new callstack
     0 RET
@@ -145,7 +162,6 @@ IN: bootstrap.x86
 
 [
     jit-load-vm
-    jit-load-context
     jit-save-context
 
     ! Store arguments
@@ -153,10 +169,10 @@ IN: bootstrap.x86
     ESP 4 [+] vm-reg MOV
 
     ! Call VM
-    0 CALL "lazy_jit_compile" f rc-relative jit-dlsym
+    "lazy_jit_compile" jit-call
 ]
-[ EAX quot-entry-point-offset [+] CALL ]
-[ EAX quot-entry-point-offset [+] JMP ]
+[ jit-call-quot ]
+[ jit-jump-quot ]
 \ lazy-jit-compile define-combinator-primitive
 
 ! Inline cache miss entry points
@@ -167,11 +183,10 @@ IN: bootstrap.x86
 ! frame, and the stack. The frame setup takes this into account.
 : jit-inline-cache-miss ( -- )
     jit-load-vm
-    jit-load-context
     jit-save-context
     ESP 4 [+] vm-reg MOV
     ESP [] EBX MOV
-    0 CALL "inline_cache_miss" f rc-relative jit-dlsym
+    "inline_cache_miss" jit-call
     jit-restore-context ;
 
 [ jit-load-return-address jit-inline-cache-miss ]
@@ -188,7 +203,6 @@ IN: bootstrap.x86
 : jit-overflow ( insn func -- )
     ds-reg 4 SUB
     jit-load-vm
-    jit-load-context
     jit-save-context
     EAX ds-reg [] MOV
     EDX ds-reg 4 [+] MOV
@@ -200,7 +214,7 @@ IN: bootstrap.x86
         ESP [] EAX MOV
         ESP 4 [+] EDX MOV
         ESP 8 [+] vm-reg MOV
-        [ 0 CALL ] dip f rc-relative jit-dlsym
+        jit-call
     ]
     jit-conditional ;
 
@@ -211,7 +225,6 @@ IN: bootstrap.x86
 [
     ds-reg 4 SUB
     jit-load-vm
-    jit-load-context
     jit-save-context
     EBX ds-reg [] MOV
     EAX EBX MOV
@@ -225,10 +238,98 @@ IN: bootstrap.x86
         ESP [] EBX MOV
         ESP 4 [+] EBP MOV
         ESP 8 [+] vm-reg MOV
-        0 CALL "overflow_fixnum_multiply" f rc-relative jit-dlsym
+        "overflow_fixnum_multiply" jit-call
     ]
     jit-conditional
 ] \ fixnum* define-sub-primitive
 
+! Contexts
+: jit-switch-context ( reg -- )
+    ! Save ds, rs registers
+    jit-load-vm
+    jit-save-context
+
+    ! Make the new context the current one
+    ctx-reg swap MOV
+    vm-reg vm-context-offset [+] ctx-reg MOV
+
+    ! Load new stack pointer
+    ESP ctx-reg context-callstack-top-offset [+] MOV
+
+    ! Windows-specific setup
+    ctx-reg jit-update-tib
+
+    ! Load new ds, rs registers
+    jit-restore-context ;
+
+: jit-set-context ( -- )
+    ! Load context and parameter from datastack
+    EAX ds-reg [] MOV
+    EAX EAX alien-offset [+] MOV
+    EBX ds-reg -4 [+] MOV
+    ds-reg 8 SUB
+
+    ! Make the new context active
+    EAX jit-switch-context
+
+    ! Windows-specific setup
+    ctx-reg jit-update-seh
+
+    ! Twiddle stack for return
+    ESP 4 ADD
+
+    ! Store parameter to datastack
+    ds-reg 4 ADD
+    ds-reg [] EBX MOV ;
+
+[ jit-set-context ] \ (set-context) define-sub-primitive
+
+: jit-start-context ( -- )
+    ! Create the new context in return-reg
+    jit-load-vm
+    ESP [] vm-reg MOV
+    "new_context" jit-call
+
+    ! Save pointer to quotation and parameter
+    EBX ds-reg MOV
+    ds-reg 8 SUB
+
+    ! Make the new context active
+    EAX jit-switch-context
+
+    ! Push parameter
+    EAX EBX -4 [+] MOV
+    ds-reg 4 ADD
+    ds-reg [] EAX MOV
+
+    ! Windows-specific setup
+    jit-install-seh
+
+    ! Push a fake return address
+    0 PUSH
+
+    ! Jump to initial quotation
+    EAX EBX [] MOV
+    jit-jump-quot ;
+
+[ jit-start-context ] \ (start-context) define-sub-primitive
+
+: jit-delete-current-context ( -- )
+    jit-load-vm
+    jit-load-context
+    ESP [] vm-reg MOV
+    ESP 4 [+] ctx-reg MOV
+    "delete_context" jit-call ;
+
+[
+    jit-delete-current-context
+    jit-set-context
+] \ (set-context-and-delete) define-sub-primitive
+
+[
+    jit-delete-current-context
+    jit-start-context
+] \ (start-context-and-delete) define-sub-primitive
+
 << "vocab:cpu/x86/bootstrap.factor" parse-file suffix! >>
 call
diff --git a/basis/cpu/x86/32/unix/bootstrap.factor b/basis/cpu/x86/32/unix/bootstrap.factor
new file mode 100644 (file)
index 0000000..1e3bee4
--- /dev/null
@@ -0,0 +1,14 @@
+! Copyright (C) 2010 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: cpu.x86.assembler cpu.x86.assembler.operands kernel
+layouts parser sequences ;
+IN: bootstrap.x86
+
+: jit-save-tib ( -- ) ;
+: jit-restore-tib ( -- ) ;
+: jit-update-tib ( ctx-reg -- ) drop ;
+: jit-install-seh ( -- ) ESP bootstrap-cell ADD ;
+: jit-update-seh ( ctx-reg -- ) drop ;
+
+<< "vocab:cpu/x86/32/bootstrap.factor" parse-file suffix! >>
+call
diff --git a/basis/cpu/x86/32/winnt/bootstrap.factor b/basis/cpu/x86/32/winnt/bootstrap.factor
new file mode 100644 (file)
index 0000000..b8ee1da
--- /dev/null
@@ -0,0 +1,54 @@
+! Copyright (C) 2010 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: bootstrap.image.private compiler.constants
+cpu.x86.assembler cpu.x86.assembler.operands kernel layouts
+locals parser sequences ;
+IN: bootstrap.x86
+
+: tib-exception-list-offset ( -- n ) 0 bootstrap-cells ;
+: tib-stack-base-offset ( -- n ) 1 bootstrap-cells ;
+: tib-stack-limit-offset ( -- n ) 2 bootstrap-cells ;
+
+: jit-save-tib ( -- )
+    tib-exception-list-offset [] FS PUSH
+    tib-stack-base-offset [] FS PUSH
+    tib-stack-limit-offset [] FS PUSH ;
+
+: jit-restore-tib ( -- )
+    tib-stack-limit-offset [] FS POP
+    tib-stack-base-offset [] FS POP
+    tib-exception-list-offset [] FS POP ;
+
+:: jit-update-tib ( ctx-reg -- )
+    ! There's a redundant load here because we're not allowed
+    ! to clobber ctx-reg. Clobbers EAX.
+    ! Save callstack base in TIB
+    EAX ctx-reg context-callstack-seg-offset [+] MOV
+    EAX EAX segment-end-offset [+] MOV
+    tib-stack-base-offset [] EAX FS MOV
+    ! Save callstack limit in TIB
+    EAX ctx-reg context-callstack-seg-offset [+] MOV
+    EAX EAX segment-start-offset [+] MOV
+    tib-stack-limit-offset [] EAX FS MOV ;
+
+: jit-install-seh ( -- )
+    ! Create a new exception record and store it in the TIB.
+    ! Align stack
+    ESP 3 bootstrap-cells ADD
+    ! Exception handler address filled in by callback.cpp
+    0 PUSH rc-absolute-cell rt-exception-handler jit-rel
+    ! No next handler
+    0 PUSH
+    ! This is the new exception handler
+    tib-exception-list-offset [] ESP FS MOV ;
+
+:: jit-update-seh ( ctx-reg -- )
+    ! Load exception record structure that jit-install-seh
+    ! created from the bottom of the callstack. Clobbers EAX.
+    EAX ctx-reg context-callstack-bottom-offset [+] MOV
+    EAX bootstrap-cell ADD
+    ! Store exception record in TIB.
+    tib-exception-list-offset [] EAX FS MOV ;
+
+<< "vocab:cpu/x86/32/bootstrap.factor" parse-file suffix! >>
+call
index 856127aedf49424acccf7ea34fad213cfc052ab4..4dfb250348f1a62026ccb694343494222fb9deb8 100644 (file)
@@ -38,26 +38,30 @@ M: x86.64 machine-registers
     } ;
 
 : vm-reg ( -- reg ) R13 ; inline
+: nv-reg ( -- reg ) RBX ; inline
 
 M: x86.64 %mov-vm-ptr ( reg -- )
     vm-reg MOV ;
 
-M: x86.64 %vm-field ( dst field -- )
-    [ vm-reg ] dip vm-field-offset [+] MOV ;
+M: x86.64 %vm-field ( dst offset -- )
+    [ vm-reg ] dip [+] MOV ;
 
-M: x86.64 %vm-field-ptr ( dst field -- )
-    [ vm-reg ] dip vm-field-offset [+] LEA ;
+M: x86.64 %set-vm-field ( src offset -- )
+    [ vm-reg ] dip [+] swap MOV ;
+
+M: x86.64 %vm-field-ptr ( dst offset -- )
+    [ vm-reg ] dip [+] LEA ;
 
 : param@ ( n -- op ) reserved-stack-space + stack@ ;
 
 M: x86.64 %prologue ( n -- )
-    temp-reg -7 [] LEA
+    temp-reg -7 [RIP+] LEA
     dup PUSH
     temp-reg PUSH
     stack-reg swap 3 cells - SUB ;
 
 M: x86.64 %prepare-jump
-    pic-tail-reg xt-tail-pic-offset [] LEA ;
+    pic-tail-reg xt-tail-pic-offset [RIP+] LEA ;
 
 : load-cards-offset ( dst -- )
     0 MOV rc-absolute-cell rel-cards-offset ;
@@ -110,7 +114,7 @@ M: x86.64 %pop-stack ( n -- )
     param-reg-0 swap ds-reg reg-stack MOV ;
 
 M: x86.64 %pop-context-stack ( -- )
-    temp-reg "ctx" %vm-field
+    temp-reg %context
     param-reg-0 temp-reg "datastack" context-field-offset [+] MOV
     param-reg-0 param-reg-0 [] MOV
     temp-reg "datastack" context-field-offset [+] bootstrap-cell SUB ;
@@ -215,23 +219,20 @@ M: x86.64 %alien-invoke
     rc-absolute-cell rel-dlsym
     R11 CALL ;
 
-M: x86.64 %nest-stacks ( -- )
-    param-reg-0 %mov-vm-ptr
-    "nest_stacks" f %alien-invoke ;
-
-M: x86.64 %unnest-stacks ( -- )
-    param-reg-0 %mov-vm-ptr
-    "unnest_stacks" f %alien-invoke ;
-
 M: x86.64 %prepare-alien-indirect ( -- )
     param-reg-0 ds-reg [] MOV
     ds-reg 8 SUB
     param-reg-1 %mov-vm-ptr
     "pinned_alien_offset" f %alien-invoke
-    RBP RAX MOV ;
+    nv-reg RAX MOV ;
 
 M: x86.64 %alien-indirect ( -- )
-    RBP CALL ;
+    nv-reg CALL ;
+
+M: x86.64 %begin-callback ( -- )
+    param-reg-0 %mov-vm-ptr
+    param-reg-1 0 MOV
+    "begin_callback" f %alien-invoke ;
 
 M: x86.64 %alien-callback ( quot -- )
     param-reg-0 param-reg-1 %restore-context
@@ -239,16 +240,15 @@ M: x86.64 %alien-callback ( quot -- )
     param-reg-0 quot-entry-point-offset [+] CALL
     param-reg-0 param-reg-1 %save-context ;
 
-M: x86.64 %callback-value ( ctype -- )
-    %pop-context-stack
-    RSP 8 SUB
-    param-reg-0 PUSH
+M: x86.64 %end-callback ( -- )
     param-reg-0 %mov-vm-ptr
-    ! Restore data/call/retain stacks
-    "unnest_stacks" f %alien-invoke
-    ! Put former top of data stack in param-reg-0
-    param-reg-0 POP
-    RSP 8 ADD
+    "end_callback" f %alien-invoke ;
+
+M: x86.64 %end-callback-value ( ctype -- )
+    %pop-context-stack
+    nv-reg param-reg-0 MOV
+    %end-callback
+    param-reg-0 nv-reg MOV
     ! Unbox former top of data stack to return registers
     unbox-return ;
 
index bc560580fac3dbae0965669c8b9c4e6ba349fabc..69734df225140c3ebc6e82728b043eab245d103f 100644 (file)
@@ -3,7 +3,7 @@
 USING: bootstrap.image.private kernel kernel.private namespaces
 system layouts vocabs parser compiler.constants math
 math.private cpu.x86.assembler cpu.x86.assembler.operands
-sequences generic.single.private ;
+sequences generic.single.private threads.private ;
 IN: bootstrap.x86
 
 8 \ cell set
@@ -16,7 +16,7 @@ IN: bootstrap.x86
 : temp2 ( -- reg ) RDX ;
 : temp3 ( -- reg ) RBX ;
 : return-reg ( -- reg ) RAX ;
-: safe-reg ( -- reg ) RAX ;
+: nv-reg ( -- reg ) RBX ;
 : stack-reg ( -- reg ) RSP ;
 : frame-reg ( -- reg ) RBP ;
 : ctx-reg ( -- reg ) R12 ;
@@ -26,19 +26,28 @@ IN: bootstrap.x86
 : fixnum>slot@ ( -- ) temp0 1 SAR ;
 : rex-length ( -- n ) 1 ;
 
+: jit-save-tib ( -- ) ;
+: jit-restore-tib ( -- ) ;
+: jit-update-tib ( ctx-reg -- ) drop ;
+: jit-install-seh ( -- ) stack-reg bootstrap-cell ADD ;
+
+: jit-call ( name -- )
+    RAX 0 MOV rc-absolute-cell jit-dlsym
+    RAX CALL ;
+
 [
     ! load entry point
-    safe-reg 0 MOV rc-absolute-cell rt-this jit-rel
+    RAX 0 MOV rc-absolute-cell rt-this jit-rel
     ! save stack frame size
     stack-frame-size PUSH
     ! push entry point
-    safe-reg PUSH
+    RAX PUSH
     ! alignment
     RSP stack-frame-size 3 bootstrap-cells - SUB
 ] jit-prolog jit-define
 
 [
-    temp3 5 [] LEA
+    temp3 5 [RIP+] LEA
     0 JMP rc-relative rt-entry-point-pic-tail jit-rel
 ] jit-word-jump jit-define
 
@@ -47,17 +56,18 @@ IN: bootstrap.x86
 
 : jit-save-context ( -- )
     jit-load-context
-    safe-reg RSP -8 [+] LEA
-    ctx-reg context-callstack-top-offset [+] safe-reg MOV
+    R11 RSP -8 [+] LEA
+    ctx-reg context-callstack-top-offset [+] R11 MOV
     ctx-reg context-datastack-offset [+] ds-reg MOV
     ctx-reg context-retainstack-offset [+] rs-reg MOV ;
 
 : jit-restore-context ( -- )
-    jit-load-context
     ds-reg ctx-reg context-datastack-offset [+] MOV
     rs-reg ctx-reg context-retainstack-offset [+] MOV ;
 
 [
+    ! ctx-reg is preserved across the call because it is non-volatile
+    ! in the C ABI
     jit-save-context
     ! call the primitive
     arg1 vm-reg MOV
@@ -66,22 +76,34 @@ IN: bootstrap.x86
     jit-restore-context
 ] jit-primitive jit-define
 
+: jit-jump-quot ( -- ) arg1 quot-entry-point-offset [+] JMP ;
+
+: jit-call-quot ( -- ) arg1 quot-entry-point-offset [+] CALL ;
+
 [
+    arg2 arg1 MOV
+    arg1 vm-reg MOV
+    "begin_callback" jit-call
+
+    jit-load-context
     jit-restore-context
-    ! save ctx->callstack_bottom
-    safe-reg stack-reg stack-frame-size 8 - [+] LEA
-    ctx-reg context-callstack-bottom-offset [+] safe-reg MOV
+
     ! call the quotation
-    arg1 quot-entry-point-offset [+] CALL
+    arg1 return-reg MOV
+    jit-call-quot
+
     jit-save-context
+
+    arg1 vm-reg MOV
+    "end_callback" jit-call
 ] \ c-to-factor define-sub-primitive
 
 [
     arg1 ds-reg [] MOV
     ds-reg bootstrap-cell SUB
 ]
-[ arg1 quot-entry-point-offset [+] CALL ]
-[ arg1 quot-entry-point-offset [+] JMP ]
+[ jit-call-quot ]
+[ jit-jump-quot ]
 \ (call) define-combinator-primitive
 
 [
@@ -99,10 +121,11 @@ IN: bootstrap.x86
     vm-reg 0 MOV 0 rc-absolute-cell jit-vm
 
     ! Load ds and rs registers
+    jit-load-context
     jit-restore-context
 
     ! Call quotation
-    arg1 quot-entry-point-offset [+] JMP
+    jit-jump-quot
 ] \ unwind-native-frames define-sub-primitive
 
 [
@@ -124,8 +147,7 @@ IN: bootstrap.x86
     ! Call memcpy; arguments are now in the correct registers
     ! Create register shadow area for Win64
     RSP 32 SUB
-    safe-reg 0 MOV "factor_memcpy" f rc-absolute-cell jit-dlsym
-    safe-reg CALL
+    "factor_memcpy" jit-call
     ! Tear down register shadow area
     RSP 32 ADD
     ! Return with new callstack
@@ -135,11 +157,11 @@ IN: bootstrap.x86
 [
     jit-save-context
     arg2 vm-reg MOV
-    safe-reg 0 MOV "lazy_jit_compile" f rc-absolute-cell jit-dlsym
-    safe-reg CALL
+    "lazy_jit_compile" jit-call
+    arg1 return-reg MOV
 ]
 [ return-reg quot-entry-point-offset [+] CALL ]
-[ return-reg quot-entry-point-offset [+] JMP ]
+[ jit-jump-quot ]
 \ lazy-jit-compile define-combinator-primitive
 
 ! Inline cache miss entry points
@@ -152,8 +174,8 @@ IN: bootstrap.x86
     jit-save-context
     arg1 RBX MOV
     arg2 vm-reg MOV
-    RAX 0 MOV "inline_cache_miss" f rc-absolute-cell jit-dlsym
-    RAX CALL
+    "inline_cache_miss" jit-call
+    jit-load-context
     jit-restore-context ;
 
 [ jit-load-return-address jit-inline-cache-miss ]
@@ -176,11 +198,7 @@ IN: bootstrap.x86
     [ [ arg3 arg2 ] dip call ] dip
     ds-reg [] arg3 MOV
     [ JNO ]
-    [
-        arg3 vm-reg MOV
-        RAX 0 MOV f rc-absolute-cell jit-dlsym
-        RAX CALL
-    ]
+    [ arg3 vm-reg MOV jit-call ]
     jit-conditional ; inline
 
 [ [ ADD ] "overflow_fixnum_add" jit-overflow ] \ fixnum+ define-sub-primitive
@@ -202,11 +220,79 @@ IN: bootstrap.x86
         arg1 tag-bits get SAR
         arg2 RBX MOV
         arg3 vm-reg MOV
-        RAX 0 MOV "overflow_fixnum_multiply" f rc-absolute-cell jit-dlsym
-        RAX CALL
+        "overflow_fixnum_multiply" jit-call
     ]
     jit-conditional
 ] \ fixnum* define-sub-primitive
 
+! Contexts
+: jit-switch-context ( reg -- )
+    ! Save ds, rs registers
+    jit-save-context
+
+    ! Make the new context the current one
+    ctx-reg swap MOV
+    vm-reg vm-context-offset [+] ctx-reg MOV
+
+    ! Load new stack pointer
+    RSP ctx-reg context-callstack-top-offset [+] MOV
+
+    ! Load new ds, rs registers
+    jit-restore-context ;
+
+: jit-pop-context-and-param ( -- )
+    arg1 ds-reg [] MOV
+    arg1 arg1 alien-offset [+] MOV
+    arg2 ds-reg -8 [+] MOV
+    ds-reg 16 SUB ;
+
+: jit-push-param ( -- )
+    ds-reg 8 ADD
+    ds-reg [] arg2 MOV ;
+
+: jit-set-context ( -- )
+    jit-pop-context-and-param
+    arg1 jit-switch-context
+    RSP 8 ADD
+    jit-push-param ;
+
+[ jit-set-context ] \ (set-context) define-sub-primitive
+
+: jit-pop-quot-and-param ( -- )
+    arg1 ds-reg [] MOV
+    arg2 ds-reg -8 [+] MOV
+    ds-reg 16 SUB ;
+
+: jit-start-context ( -- )
+    ! Create the new context in return-reg
+    arg1 vm-reg MOV
+    "new_context" jit-call
+
+    jit-pop-quot-and-param
+
+    return-reg jit-switch-context
+
+    jit-push-param
+
+    jit-jump-quot ;
+
+[ jit-start-context ] \ (start-context) define-sub-primitive
+
+: jit-delete-current-context ( -- )
+    jit-load-context
+    arg1 vm-reg MOV
+    arg2 ctx-reg MOV
+    "delete_context" jit-call ;
+
+[
+    jit-delete-current-context
+    jit-set-context
+] \ (set-context-and-delete) define-sub-primitive
+
+[
+    jit-delete-current-context
+    jit-start-context
+] \ (start-context-and-delete) define-sub-primitive
+
 << "vocab:cpu/x86/bootstrap.factor" parse-file suffix! >>
 call
index 531110da7bf2a36cc0ce568c39a0ca140bd71fee..8ed789f392e317d269aae787c903a075a9093f9f 100644 (file)
@@ -1,5 +1,5 @@
 USING: cpu.x86.assembler cpu.x86.assembler.operands
-kernel tools.test namespaces make ;
+kernel tools.test namespaces make layouts ;
 IN: cpu.x86.assembler.tests
 
 [ { HEX: 40 HEX: 8a HEX: 2a } ] [ [ BPL RDX [] MOV ] { } make ] unit-test
@@ -164,3 +164,11 @@ IN: cpu.x86.assembler.tests
 
 [ { 15 183 195 } ] [ [ EAX BX MOVZX ] { } make ] unit-test
 
+bootstrap-cell 4 = [
+    [ { 100 199 5 0 0 0 0 123 0 0 0 } ] [ [ 0 [] FS 123 MOV ] { } make ] unit-test
+] when
+
+bootstrap-cell 8 = [
+    [ { 72 137 13 123 0 0 0 } ] [ [ 123 [RIP+] RCX MOV ] { } make ] unit-test
+    [ { 101 72 137 12 37 123 0 0 0 } ] [ [ 123 [] GS RCX MOV ] { } make ] unit-test
+] when
index b075b121a5c7c130f285af29ac3c3853c8ee1f31..b91083dad1f64345b727ecc2330d403c61e63a4c 100644 (file)
@@ -1,9 +1,9 @@
-! Copyright (C) 2005, 2009 Slava Pestov, Joe Groff.
+! Copyright (C) 2005, 2010 Slava Pestov, Joe Groff.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: arrays io.binary kernel combinators kernel.private math
-math.bitwise locals namespaces make sequences words system
-layouts math.order accessors cpu.x86.assembler.operands
-cpu.x86.assembler.operands.private ;
+USING: arrays io.binary kernel combinators
+combinators.short-circuit math math.bitwise locals namespaces
+make sequences words system layouts math.order accessors
+cpu.x86.assembler.operands cpu.x86.assembler.operands.private ;
 QUALIFIED: sequences
 IN: cpu.x86.assembler
 
@@ -22,7 +22,11 @@ IN: cpu.x86.assembler
 GENERIC: sib-present? ( op -- ? )
 
 M: indirect sib-present?
-    [ base>> { ESP RSP R12 } member? ] [ index>> ] [ scale>> ] tri or or ;
+    {
+        [ base>> { ESP RSP R12 } member? ]
+        [ index>> ]
+        [ scale>> ]
+    } 1|| ;
 
 M: register sib-present? drop f ;
 
@@ -188,6 +192,13 @@ M: register displacement, drop ;
 
 PRIVATE>
 
+! Segment override prefixes
+: CS ( -- ) HEX: 2e , ;
+: ES ( -- ) HEX: 26 , ;
+: SS ( -- ) HEX: 36 , ;
+: FS ( -- ) HEX: 64 , ;
+: GS ( -- ) HEX: 65 , ;
+
 ! Moving stuff
 GENERIC: PUSH ( op -- )
 M: register PUSH f HEX: 50 short-operand ;
index bd9a3f6cddff869c2b899b93f8ceca6d2a302636..e8d98cde1730e240779d9d350d8e9a2c05cef439 100644 (file)
@@ -1,13 +1,9 @@
-! Copyright (C) 2008, 2009 Slava Pestov, Joe Groff.
+! Copyright (C) 2008, 2010 Slava Pestov, Joe Groff.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel words math accessors sequences namespaces
 assocs layouts cpu.x86.assembler.syntax ;
 IN: cpu.x86.assembler.operands
 
-! In 32-bit mode, { 1234 } is absolute indirect addressing.
-! In 64-bit mode, { 1234 } is RIP-relative.
-! Beware!
-
 REGISTERS: 8 AL CL DL BL SPL BPL SIL DIL R8B R9B R10B R11B R12B R13B R14B R15B ;
 
 ALIAS: AH SPL
@@ -90,7 +86,13 @@ M: object operand-64? drop f ;
 PRIVATE>
 
 : [] ( reg/displacement -- indirect )
-    dup integer? [ [ f f f ] dip ] [ f f f ] if <indirect> ;
+    dup integer?
+    [ [ f f bootstrap-cell 8 = 0 f ? ] dip <indirect> ]
+    [ f f f <indirect> ]
+    if ;
+
+: [RIP+] ( displacement -- indirect )
+    [ f f f ] dip <indirect> ;
 
 : [+] ( reg displacement -- indirect )
     dup integer?
index 8f1a4d7f498ebfbc25fd2508bb6a8b2e7f02f8db..80b56f9f9159f581433fba9d18876048e75d6478 100644 (file)
@@ -13,37 +13,54 @@ big-endian off
     ! Optimizing compiler's side of callback accesses
     ! arguments that are on the stack via the frame pointer.
     ! On x86-64, some arguments are passed in registers, and
-    ! so the only register that is safe for use here is safe-reg.
+    ! so the only register that is safe for use here is nv-reg.
     frame-reg PUSH
     frame-reg stack-reg MOV
 
     ! Save all non-volatile registers
     nv-regs [ PUSH ] each
 
-    ! Save old stack pointer and align
-    safe-reg stack-reg MOV
-    stack-reg bootstrap-cell SUB
-    stack-reg -16 AND
-    stack-reg [] safe-reg MOV
-
-    ! Register shadow area - only required on Win64, but doesn't
-    ! hurt on other platforms
-    stack-reg 32 SUB
+    jit-save-tib
 
     ! Load VM into vm-reg
     vm-reg 0 MOV rc-absolute-cell rt-vm jit-rel
 
+    ! Save old context
+    nv-reg vm-reg vm-context-offset [+] MOV
+    nv-reg PUSH
+
+    ! Switch over to the spare context
+    nv-reg vm-reg vm-spare-context-offset [+] MOV
+    vm-reg vm-context-offset [+] nv-reg MOV
+
+    ! Save C callstack pointer
+    nv-reg context-callstack-save-offset [+] stack-reg MOV
+
+    ! Load Factor callstack pointer
+    stack-reg nv-reg context-callstack-bottom-offset [+] MOV
+
+    nv-reg jit-update-tib
+    jit-install-seh
+
     ! Call into Factor code
-    safe-reg 0 MOV rc-absolute-cell rt-entry-point jit-rel
-    safe-reg CALL
+    nv-reg 0 MOV rc-absolute-cell rt-entry-point jit-rel
+    nv-reg CALL
+
+    ! Load VM into vm-reg; only needed on x86-32, but doesn't
+    ! hurt on x86-64
+    vm-reg 0 MOV rc-absolute-cell rt-vm jit-rel
 
-    ! Tear down register shadow area
-    stack-reg 32 ADD
+    ! Load C callstack pointer
+    nv-reg vm-reg vm-context-offset [+] MOV
+    stack-reg nv-reg context-callstack-save-offset [+] MOV
 
-    ! Undo stack alignment
-    stack-reg stack-reg [] MOV
+    ! Load old context
+    nv-reg POP
+    vm-reg vm-context-offset [+] nv-reg MOV
 
     ! Restore non-volatile registers
+    jit-restore-tib
+
     nv-regs <reversed> [ POP ] each
 
     frame-reg POP
@@ -56,15 +73,15 @@ big-endian off
 
 [
     ! Load word
-    safe-reg 0 MOV rc-absolute-cell rt-literal jit-rel
+    nv-reg 0 MOV rc-absolute-cell rt-literal jit-rel
     ! Bump profiling counter
-    safe-reg profile-count-offset [+] 1 tag-fixnum ADD
+    nv-reg profile-count-offset [+] 1 tag-fixnum ADD
     ! Load word->code
-    safe-reg safe-reg word-code-offset [+] MOV
+    nv-reg nv-reg word-code-offset [+] MOV
     ! Compute word entry point
-    safe-reg compiled-header-size ADD
+    nv-reg compiled-header-size ADD
     ! Jump to entry point
-    safe-reg JMP
+    nv-reg JMP
 ] jit-profiling jit-define
 
 [
index e54e307f79fffe8478574272d83732db7f04a1fa..acd2e1358dbdb9b7f1e95dd041728f5f6b37ee74 100644 (file)
@@ -423,8 +423,13 @@ M: x86 %sar int-rep two-operand [ SAR ] emit-shift ;
 
 HOOK: %mov-vm-ptr cpu ( reg -- )
 
+HOOK: %vm-field-ptr cpu ( reg offset -- )
+
+: load-zone-offset ( nursery-ptr -- )
+    "nursery" vm-field-offset %vm-field-ptr ;
+
 : load-allot-ptr ( nursery-ptr allot-ptr -- )
-    [ drop "nursery" %vm-field-ptr ] [ swap [] MOV ] 2bi ;
+    [ drop load-zone-offset ] [ swap [] MOV ] 2bi ;
 
 : inc-allot-ptr ( nursery-ptr n -- )
     [ [] ] dip data-alignment get align ADD ;
@@ -456,7 +461,7 @@ M: x86 %write-barrier ( src slot temp1 temp2 -- ) (%write-barrier) ;
 M: x86 %write-barrier-imm ( src slot temp1 temp2 -- ) (%write-barrier) ;
 
 M:: x86 %check-nursery ( label size temp1 temp2 -- )
-    temp1 "nursery" %vm-field-ptr
+    temp1 load-zone-offset
     ! Load 'here' into temp2
     temp2 temp1 [] MOV
     temp2 size ADD
@@ -477,7 +482,7 @@ M: x86 %push-stack ( -- )
     ds-reg [] int-regs return-reg MOV ;
 
 M: x86 %push-context-stack ( -- )
-    temp-reg "ctx" %vm-field
+    temp-reg %context
     temp-reg "datastack" context-field-offset [+] bootstrap-cell ADD
     temp-reg temp-reg "datastack" context-field-offset [+] MOV
     temp-reg [] int-regs return-reg MOV ;
@@ -1403,10 +1408,7 @@ M: x86 %loop-entry 16 code-alignment [ NOP ] times ;
 
 M:: x86 %restore-context ( temp1 temp2 -- )
     #! Load Factor stack pointers on entry from C to Factor.
-    #! Also save callstack bottom!
-    temp1 "ctx" %vm-field
-    temp2 stack-reg stack-frame get total-size>> cell - [+] LEA
-    temp1 "callstack-bottom" context-field-offset [+] temp2 MOV
+    temp1 %context
     ds-reg temp1 "datastack" context-field-offset [+] MOV
     rs-reg temp1 "retainstack" context-field-offset [+] MOV ;
 
@@ -1414,7 +1416,7 @@ M:: x86 %save-context ( temp1 temp2 -- )
     #! Save Factor stack pointers in case the C code calls a
     #! callback which does a GC, which must reliably trace
     #! all roots.
-    temp1 "ctx" %vm-field
+    temp1 %context
     temp2 stack-reg cell neg [+] LEA
     temp1 "callstack-top" context-field-offset [+] temp2 MOV
     temp1 "datastack" context-field-offset [+] ds-reg MOV
index c34a50190f8d4a0d84c19fe620d8d51eb3a6a0b3..8f448ff23756f2beea489dc73b556b2cf78204c6 100644 (file)
@@ -120,6 +120,8 @@ HOOK: signal-error. os ( obj -- )
 : datastack-overflow. ( obj -- ) "Data" stack-overflow. ;
 : retainstack-underflow. ( obj -- ) "Retain" stack-underflow. ;
 : retainstack-overflow. ( obj -- ) "Retain" stack-overflow. ;
+: callstack-underflow. ( obj -- ) "Call" stack-underflow. ;
+: callstack-overflow. ( obj -- ) "Call" stack-overflow. ;
 
 : memory-error. ( error -- )
     "Memory protection fault at address " write third .h ;
@@ -153,8 +155,10 @@ PREDICATE: vm-error < array
         { 11 [ datastack-overflow.     ] }
         { 12 [ retainstack-underflow.  ] }
         { 13 [ retainstack-overflow.   ] }
-        { 14 [ memory-error.           ] }
-        { 15 [ fp-trap-error.          ] }
+        { 14 [ callstack-underflow.    ] }
+        { 15 [ callstack-overflow.     ] }
+        { 16 [ memory-error.           ] }
+        { 17 [ fp-trap-error.          ] }
     } ; inline
 
 M: vm-error summary drop "VM error" ;
index d4867714d36d7487bf3030811f78f0fd30f9bc28..451016cc6c9f46e57fdb2346d164576b720ef767 100644 (file)
@@ -18,9 +18,16 @@ HELP: define-consult
 { $notes "Usually, " { $link POSTPONE: CONSULT: } " should be used instead. This is only for runtime use." } ;
 
 HELP: CONSULT:
-{ $syntax "CONSULT: group class getter... ;" } 
-{ $values { "group" "a protocol, generic word or tuple class" } { "class" "a class" } { "getter" "code to get where the method should be forwarded" } }
-{ $description "Defines a class to consult, using the given code, on the generic words contained in the group. This means that, when one of the words in the group is called on an object of this class, the quotation will be called, and then the generic word called again. If the getter is empty, this will cause an infinite loop. Consultation overwrites the existing methods, but others can be defined afterwards." } ;
+{ $syntax """CONSULT: group class
+    code ;""" } 
+{ $values { "group" "a protocol, generic word or tuple class" } { "class" "a class" } { "code" "code to get the object to which the method should be forwarded" } }
+{ $description "Declares that objects of " { $snippet "class" } " will delegate the generic words contained in " { $snippet "group" } " to the object returned by executing " { $snippet "code" } " with the original object as an input." { $snippet "CONSULT:" } " will overwrite any existing methods on " { $snippet "class" } " for the members of " { $snippet "group" } ", but new methods can be added after the " { $snippet "CONSULT:" } " to override the delegation." } ;
+
+HELP: BROADCAST:
+{ $syntax """BROADCAST: group class
+    code ;""" } 
+{ $values { "group" "a protocol, generic word or tuple class" } { "class" "a class" } { "code" "code to get the object to which the method should be forwarded" } }
+{ $description "Declares that objects of " { $snippet "class" } " will delegate the generic words contained in " { $snippet "group" } " to every object in the sequence returned by executing " { $snippet "code" } " with the original object as an input." { $snippet "BROADCAST:" } " will overwrite any existing methods on " { $snippet "class" } " for the members of " { $snippet "group" } ", but new methods can be added after the " { $snippet "BROADCAST:" } " to override the delegation. Every generic word in " { $snippet "group" } " must return no outputs; otherwise, a " { $link broadcast-words-must-have-no-outputs } " error will be raised." } ;
 
 HELP: SLOT-PROTOCOL:
 { $syntax "SLOT-PROTOCOL: protocol-name slots... ;" }
@@ -28,7 +35,7 @@ HELP: SLOT-PROTOCOL:
 
 { define-protocol POSTPONE: PROTOCOL: } related-words
 
-{ define-consult POSTPONE: CONSULT: } related-words
+{ define-consult POSTPONE: BROADCAST: POSTPONE: CONSULT: } related-words
 
 HELP: group-words
 { $values { "group" "a group" } { "words" "an array of words" } }
@@ -52,6 +59,7 @@ $nl
 { $subsections POSTPONE: SLOT-PROTOCOL: }
 "Defining consultation:"
 { $subsections
+    POSTPONE: BROADCAST:
     POSTPONE: CONSULT:
     define-consult
 }
index 17f81708c5e94c5d9f5ee1c2fec77156a44b58b6..4a280ef58432998b1fc5246ee20c6c2c619cd5b3 100644 (file)
@@ -1,7 +1,7 @@
 USING: delegate kernel arrays tools.test words math definitions
 compiler.units parser generic prettyprint io.streams.string
 accessors eval multiline generic.single delegate.protocols
-delegate.private assocs see ;
+delegate.private assocs see make ;
 IN: delegate.tests
 
 TUPLE: hello this that ;
@@ -197,3 +197,18 @@ DEFER: seq-delegate
     sequence-protocol \ protocol-consult word-prop
     key?
 ] unit-test
+
+GENERIC: broadcastable ( x -- )
+GENERIC: nonbroadcastable ( x -- y )
+
+TUPLE: broadcaster targets ;
+
+BROADCAST: broadcastable broadcaster targets>> ;
+
+M: integer broadcastable 1 + , ;
+
+[ "USING: accessors delegate ; IN: delegate.tests BROADCAST: nonbroadcastable broadcaster targets>> ;" eval( -- ) ]
+[ error>> broadcast-words-must-have-no-outputs? ] must-fail-with
+
+[ { 2 3 4 } ]
+[ { 1 2 3 } broadcaster boa [ broadcastable ] { } make ] unit-test
index dc3024b55faddeae3cd9c53e5f7df3f12aadfc3b..5c8703116dfbc26330ad4e74284d5f247034c316 100644 (file)
@@ -1,12 +1,14 @@
 ! Copyright (C) 2007, 2008 Daniel Ehrenberg
-! Portions copyright (C) 2009 Slava Pestov
+! Portions copyright (C) 2009, 2010 Slava Pestov, Joe Groff
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors arrays assocs classes.tuple definitions generic
+USING: accessors arrays assocs classes.tuple definitions effects generic
 generic.standard hashtables kernel lexer math parser
 generic.parser sequences sets slots words words.symbol fry
 compiler.units ;
 IN: delegate
 
+ERROR: broadcast-words-must-have-no-outputs group ;
+
 <PRIVATE
 
 : protocol-words ( protocol -- words )
@@ -28,12 +30,19 @@ M: tuple-class group-words
         2array
     ] map concat ;
 
+: check-broadcast-group ( group -- group )
+    dup group-words [ first stack-effect out>> empty? ] all?
+    [ broadcast-words-must-have-no-outputs ] unless ;
+
 ! Consultation
 
 TUPLE: consultation group class quot loc ;
+TUPLE: broadcast < consultation ;
 
 : <consultation> ( group class quot -- consultation )
     f consultation boa ; 
+: <broadcast> ( group class quot -- consultation )
+    [ check-broadcast-group ] 2dip f broadcast boa ; 
 
 : create-consult-method ( word consultation -- method )
     [ class>> swap first create-method dup fake-definition ] keep
@@ -44,13 +53,21 @@ PREDICATE: consult-method < method "consultation" word-prop ;
 M: consult-method reset-word
     [ call-next-method ] [ f "consultation" set-word-prop ] bi ;
 
-: consult-method-quot ( quot word -- object )
+GENERIC# (consult-method-quot) 2 ( consultation quot word -- object )
+
+M: consultation (consult-method-quot)
+    '[ _ call _ execute ] nip ;
+M: broadcast (consult-method-quot)
+    '[ _ call [ _ execute ] each ] nip ;
+
+: consult-method-quot ( consultation word -- object )
+    [ dup quot>> ] dip
     [ second [ [ dip ] curry ] times ] [ first ] bi
-    '[ _ call _ execute ] ;
+    (consult-method-quot) ;
 
 : consult-method ( word consultation -- )
     [ create-consult-method ]
-    [ quot>> swap consult-method-quot ] 2bi
+    [ swap consult-method-quot ] 2bi
     define ;
 
 : change-word-prop ( word prop quot -- )
@@ -89,6 +106,10 @@ SYNTAX: CONSULT:
     scan-word scan-word parse-definition <consultation>
     [ save-location ] [ define-consult ] bi ;
 
+SYNTAX: BROADCAST:
+    scan-word scan-word parse-definition <broadcast>
+    [ save-location ] [ define-consult ] bi ;
+
 M: consultation where loc>> ;
 
 M: consultation set-where (>>loc) ;
index 1e1be404a77f5459215e6455e9d3aa7603b5847d..7483c0f56b12c90e330ae9a89c090f1496b68822 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2008, 2009 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel sequences math fry ;
 IN: deques
@@ -16,22 +16,22 @@ GENERIC: node-value ( node -- value )
 GENERIC: deque-empty? ( deque -- ? )
 
 : push-front ( obj deque -- )
-    push-front* drop ;
+    push-front* drop ; inline
 
 : push-all-front ( seq deque -- )
     [ push-front ] curry each ;
 
 : push-back ( obj deque -- )
-    push-back* drop ;
+    push-back* drop ; inline
 
 : push-all-back ( seq deque -- )
     [ push-back ] curry each ;
 
 : pop-front ( deque -- obj )
-    [ peek-front ] [ pop-front* ] bi ;
+    [ peek-front ] [ pop-front* ] bi ; inline
 
 : pop-back ( deque -- obj )
-    [ peek-back ] [ pop-back* ] bi ;
+    [ peek-back ] [ pop-back* ] bi ; inline
 
 : slurp-deque ( deque quot -- )
     [ drop '[ _ deque-empty? not ] ]
index 44140d31093a76a07505a6ce01ac5a3edb637264..53e134fad9fb2f88c410279b11a4168b495fc638 100644 (file)
@@ -29,7 +29,7 @@ TUPLE: dlist
 : <hashed-dlist> ( -- search-deque )
     20 <hashtable> <dlist> <search-deque> ;
 
-M: dlist deque-empty? front>> not ;
+M: dlist deque-empty? front>> not ; inline
 
 M: dlist-node node-value obj>> ;
 
index 677daca69de52e85006fbfe78c9b4388248614f2..28d18cb53acce3ab053fa321b8ff34c3cdcce77d 100644 (file)
@@ -35,7 +35,7 @@ TUPLE: max-heap < heap ;
 : <max-heap> ( -- max-heap ) max-heap <heap> ;
 
 M: heap heap-empty? ( heap -- ? )
-    data>> empty? ;
+    data>> empty? ; inline
 
 M: heap heap-size ( heap -- n )
     data>> length ;
index 2ce0ec9dfce9dcceea45b3b0a9f20fe84a74fde9..1221ee39f35ae8165694c90096dd047ce61e294e 100644 (file)
@@ -196,4 +196,4 @@ ERROR: download-failed response ;
 
 USING: vocabs vocabs.loader ;
 
-"debugger" vocab [ "http.client.debugger" require ] when
+"debugger" "http.client.debugger" require-when
index 16d0338da532eb39f8e59129797353b2db545155..41fc7a65bca4799a581f88101be5296ec22e3c1d 100644 (file)
@@ -3,7 +3,7 @@
 USING: accessors alien.c-types combinators destructors
 io.backend.unix kernel math.bitwise sequences
 specialized-arrays unix unix.kqueue unix.time assocs
-io.backend.unix.multiplexers classes.struct ;
+io.backend.unix.multiplexers classes.struct literals ;
 SPECIALIZED-ARRAY: kevent
 IN: io.backend.unix.multiplexers.kqueue
 
@@ -31,13 +31,13 @@ M: kqueue-mx dispose* fd>> close-file ;
 
 M: kqueue-mx add-input-callback ( thread fd mx -- )
     [ call-next-method ] [
-        [ EVFILT_READ { EV_ADD EV_ONESHOT } flags make-kevent ] dip
+        [ EVFILT_READ flags{ EV_ADD EV_ONESHOT } make-kevent ] dip
         register-kevent
     ] 2bi ;
 
 M: kqueue-mx add-output-callback ( thread fd mx -- )
     [ call-next-method ] [
-        [ EVFILT_WRITE { EV_ADD EV_ONESHOT } flags make-kevent ] dip
+        [ EVFILT_WRITE flags{ EV_ADD EV_ONESHOT } make-kevent ] dip
         register-kevent
     ] 2bi ;
 
index 39f0a5fec381bd1d2e2bebfbc41a0017ce74bcee..0e84f1b65e522ff478cb779d93ff288bc60d6bb7 100644 (file)
@@ -67,12 +67,11 @@ M: io-timeout summary drop "I/O operation timed out" ;
 
 : wait-for-fd ( handle event -- )
     dup +retry+ eq? [ 2drop ] [
-        '[
-            swap handle-fd mx get-global _ {
-                { +input+ [ add-input-callback ] }
-                { +output+ [ add-output-callback ] }
-            } case
-        ] "I/O" suspend nip [ io-timeout ] when
+        [ [ self ] dip handle-fd mx get-global ] dip {
+            { +input+ [ add-input-callback ] }
+            { +output+ [ add-output-callback ] }
+        } case
+        "I/O" suspend [ io-timeout ] when
     ] if ;
 
 : wait-for-port ( port event -- )
index de29f33ee612d20bfb84222e1fc07eba6f4ee7fe..5cbe7b3ad94155f0630331b5ad9cb725d55d8076 100644 (file)
@@ -40,8 +40,8 @@ M: winnt add-completion ( win32-handle -- )
 : twiddle-thumbs ( overlapped port -- bytes-transferred )
     [
         drop
-        [ >c-ptr pending-overlapped get-global set-at ] curry "I/O" suspend
-        {
+        [ self ] dip >c-ptr pending-overlapped get-global set-at
+        "I/O" suspend {
             { [ dup integer? ] [ ] }
             { [ dup array? ] [
                 first dup eof?
index 6022e91efdcbf4c4e3280c659390d642bc646bee..53a67bbeab4f36fcd503242e08abba5c81a95557 100644 (file)
@@ -2,7 +2,7 @@ USING: alien alien.c-types alien.data alien.syntax arrays continuations
 destructors generic io.mmap io.ports io.backend.windows io.files.windows
 kernel libc locals math math.bitwise namespaces quotations sequences windows
 windows.advapi32 windows.kernel32 windows.types io.backend system accessors
-io.backend.windows.privileges classes.struct windows.errors ;
+io.backend.windows.privileges classes.struct windows.errors literals ;
 IN: io.backend.windows.nt.privileges
 
 TYPEDEF: TOKEN_PRIVILEGES* PTOKEN_PRIVILEGES
@@ -11,7 +11,7 @@ TYPEDEF: TOKEN_PRIVILEGES* PTOKEN_PRIVILEGES
 !  http://msdn.microsoft.com/msdnmag/issues/05/03/TokenPrivileges/
 
 : (open-process-token) ( handle -- handle )
-    { TOKEN_ADJUST_PRIVILEGES TOKEN_QUERY } flags PHANDLE <c-object>
+    flags{ TOKEN_ADJUST_PRIVILEGES TOKEN_QUERY } PHANDLE <c-object>
     [ OpenProcessToken win32-error=0/f ] keep *void* ;
 
 : open-process-token ( -- handle )
index 6ec2ec4dc585968161b98480dee03a2e998def3c..0e0a803679a8bafd7064d6a6ec51900529192c40 100644 (file)
@@ -5,7 +5,7 @@ io.buffers io.files io.ports io.binary io.timeouts system
 strings kernel math namespaces sequences windows.errors
 windows.kernel32 windows.shell32 windows.types splitting
 continuations math.bitwise accessors init sets assocs
-classes.struct classes ;
+classes.struct classes literals ;
 IN: io.backend.windows
 
 TUPLE: win32-handle < disposable handle ;
@@ -43,12 +43,12 @@ HOOK: add-completion io-backend ( port -- )
     <win32-file> |dispose
     dup add-completion ;
 
-: share-mode ( -- n )
-    {
+CONSTANT: share-mode
+    flags{
         FILE_SHARE_READ
         FILE_SHARE_WRITE
         FILE_SHARE_DELETE
-    } flags ; foldable
+    }
 
 : default-security-attributes ( -- obj )
     SECURITY_ATTRIBUTES <struct>
index 77d7f2d1b27354d0be5e328c11f2c16c8c2e20a7..0cc8aaa0e43766f2e508eaebd154e4a33fa61a4e 100644 (file)
@@ -4,11 +4,10 @@ USING: accessors alien.c-types alien.strings combinators
 continuations destructors fry io io.backend io.backend.unix
 io.directories io.encodings.binary io.encodings.utf8 io.files
 io.pathnames io.files.types kernel math.bitwise sequences system
-unix unix.stat vocabs.loader classes.struct unix.ffi ;
+unix unix.stat vocabs.loader classes.struct unix.ffi literals ;
 IN: io.directories.unix
 
-: touch-mode ( -- n )
-    { O_WRONLY O_APPEND O_CREAT O_EXCL } flags ; foldable
+CONSTANT: touch-mode flags{ O_WRONLY O_APPEND O_CREAT O_EXCL }
 
 M: unix touch-file ( path -- )
     normalize-path
index a2051bd10afa1a44c4b426fdfeac3c6ce217eeba..7e8d166b3213a75ff2d1db5a9fc2e3952920dbe5 100644 (file)
@@ -54,12 +54,19 @@ HELP: with-unique-directory
 }
 { $description "Creates a directory with " { $link unique-directory } " and calls the quotation with the pathname on the stack using the " { $link with-temporary-directory } " combinator. The quotation can access the " { $link current-temporary-directory } " symbol for the name of the temporary directory. Subsequent unique files will be created in this unique directory until the combinator returns." } ;
 
+HELP: copy-file-unique
+{ $values
+    { "path" "a pathname string" } { "prefix" string } { "suffix" string }
+    { "path'" "a pathname string" }
+}
+{ $description "Copies " { $snippet "path" } " to a new unique file in the directory stored in " { $link current-temporary-directory } ". Returns the new path." } ;
+
 HELP: move-file-unique
 { $values
-    { "path" "a pathname string" } { "directory" "a directory" }
+    { "path" "a pathname string" } { "prefix" string } { "suffix" string }
     { "path'" "a pathname string" }
 }
-{ $description "Moves " { $snippet "path" } " to " { $snippet "directory" } " by creating a unique file in this directory. Returns the new path." } ;
+{ $description "Moves " { $snippet "path" } " to a new unique file in the directory stored in " { $link current-temporary-directory } ". Returns the new path." } ;
 
 HELP: current-temporary-directory
 { $values
@@ -98,7 +105,10 @@ ARTICLE: "io.files.unique" "Unique files"
 }
 "Default temporary directory:"
 { $subsections default-temporary-directory }
-"Moving files into a directory safely:"
-{ $subsections move-file-unique } ;
+"Copying and moving files to a new unique file:"
+{ $subsections
+    copy-file-unique
+    move-file-unique
+} ;
 
 ABOUT: "io.files.unique"
index 07f7b25140bdc192da95247e2ae6b589c81e75ae..5bf89b95207cf15fe068fb8c2fd1c1796cd2c29f 100644 (file)
@@ -70,10 +70,17 @@ PRIVATE>
 : unique-file ( prefix -- path )
     "" make-unique-file ;
 
-: move-file-unique ( path directory -- path' )
-    [
-        "" unique-file [ move-file ] keep
-    ] with-temporary-directory ;
+: move-file-unique ( path prefix suffix -- path' )
+    make-unique-file [ move-file ] keep ;
+
+: copy-file-unique ( path prefix suffix -- path' )
+    make-unique-file [ copy-file ] keep ;
+
+: temporary-file ( -- path ) "" unique-file ;
+
+: with-working-directory ( path quot -- )
+    over make-directories
+    dupd '[ _ _ with-temporary-directory ] with-directory ; inline
 
 {
     { [ os unix? ] [ "io.files.unique.unix" ] }
index ec72d9128bc4e5a05b6290b6c15afc5ceb08e402..cd60e3d4b8b4c5e0a925baa1251eb412c15b8b06 100644 (file)
@@ -1,11 +1,10 @@
 ! Copyright (C) 2008 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel io.ports io.backend.unix math.bitwise
-unix system io.files.unique unix.ffi ;
+unix system io.files.unique unix.ffi literals ;
 IN: io.files.unique.unix
 
-: open-unique-flags ( -- flags )
-    { O_RDWR O_CREAT O_EXCL } flags ;
+CONSTANT: open-unique-flags flags{ O_RDWR O_CREAT O_EXCL }
 
 M: unix (touch-unique-file) ( path -- )
     open-unique-flags file-mode open-file close-file ;
index 93e499a5762c53287ea40b9617bd6a97dcb1f27a..06f7473aed44adb91bc35194edb60b4944aad3f5 100644 (file)
@@ -2,7 +2,7 @@ USING: tools.test io.files io.files.temp io.pathnames
 io.directories io.files.info io.files.info.unix continuations
 kernel io.files.unix math.bitwise calendar accessors
 math.functions math unix.users unix.groups arrays sequences
-grouping io.pathnames.private ;
+grouping io.pathnames.private literals ;
 IN: io.files.unix.tests
 
 [ "/usr/libexec/" ] [ "/usr/libexec/awk/" parent-directory ] unit-test
@@ -45,7 +45,7 @@ IN: io.files.unix.tests
 prepare-test-file
 
 [ t ]
-[ test-file { USER-ALL GROUP-ALL OTHER-ALL } flags set-file-permissions perms OCT: 777 = ] unit-test
+[ test-file flags{ USER-ALL GROUP-ALL OTHER-ALL } set-file-permissions perms OCT: 777 = ] unit-test
 
 [ t ] [ test-file user-read? ] unit-test
 [ t ] [ test-file user-write? ] unit-test
@@ -85,7 +85,7 @@ prepare-test-file
 [ f ] [ test-file file-info other-read? ] unit-test
 
 [ t ]
-[ test-file { USER-ALL GROUP-ALL OTHER-EXECUTE } flags set-file-permissions perms OCT: 771 = ] unit-test
+[ test-file flags{ USER-ALL GROUP-ALL OTHER-EXECUTE } set-file-permissions perms OCT: 771 = ] unit-test
 
 prepare-test-file
 
index bf0a21f997921bd32b6256e3ea847571968b5669..e695345125ce8b058d888b3a3af7ea77e55b78de 100644 (file)
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: unix byte-arrays kernel io.backend.unix math.bitwise
 io.ports io.files io.files.private io.pathnames environment
-destructors system unix.ffi ;
+destructors system unix.ffi literals ;
 IN: io.files.unix
 
 M: unix cwd ( -- path )
@@ -12,15 +12,14 @@ M: unix cwd ( -- path )
 
 M: unix cd ( path -- ) [ chdir ] unix-system-call drop ;
 
-: read-flags ( -- n ) O_RDONLY ; inline
+CONSTANT: read-flags flags{ O_RDONLY }
 
-: open-read ( path -- fd ) O_RDONLY file-mode open-file ;
+: open-read ( path -- fd ) read-flags file-mode open-file ;
 
 M: unix (file-reader) ( path -- stream )
     open-read <fd> init-fd <input-port> ;
 
-: write-flags ( -- n )
-    { O_WRONLY O_CREAT O_TRUNC } flags ; inline
+CONSTANT: write-flags flags{ O_WRONLY O_CREAT O_TRUNC }
 
 : open-write ( path -- fd )
     write-flags file-mode open-file ;
@@ -28,8 +27,7 @@ M: unix (file-reader) ( path -- stream )
 M: unix (file-writer) ( path -- stream )
     open-write <fd> init-fd <output-port> ;
 
-: append-flags ( -- n )
-    { O_WRONLY O_APPEND O_CREAT } flags ; inline
+CONSTANT: append-flags flags{ O_WRONLY O_APPEND O_CREAT }
 
 : open-append ( path -- fd )
     [
index c4c848cb648ea92ff558d9ec97a6a16da0492c64..4fc2057a744e0c5187d8342f41011479d1ab8fd7 100644 (file)
@@ -6,7 +6,8 @@ io.backend.windows kernel math splitting fry alien.strings
 windows windows.kernel32 windows.time windows.types calendar
 combinators math.functions sequences namespaces make words
 system destructors accessors math.bitwise continuations
-windows.errors arrays byte-arrays generalizations alien.data ;
+windows.errors arrays byte-arrays generalizations alien.data
+literals ;
 IN: io.files.windows
 
 : open-file ( path access-mode create-mode flags -- handle )
@@ -16,7 +17,7 @@ IN: io.files.windows
     ] with-destructors ;
 
 : open-r/w ( path -- win32-file )
-    { GENERIC_READ GENERIC_WRITE } flags
+    flags{ GENERIC_READ GENERIC_WRITE }
     OPEN_EXISTING 0 open-file ;
 
 : open-read ( path -- win32-file )
@@ -29,7 +30,7 @@ IN: io.files.windows
     GENERIC_WRITE OPEN_ALWAYS 0 open-file ;
 
 : open-existing ( path -- win32-file )
-    { GENERIC_READ GENERIC_WRITE } flags
+    flags{ GENERIC_READ GENERIC_WRITE }
     share-mode
     f
     OPEN_EXISTING
@@ -38,7 +39,7 @@ IN: io.files.windows
 
 : maybe-create-file ( path -- win32-file ? )
     #! return true if file was just created
-    { GENERIC_READ GENERIC_WRITE } flags
+    flags{ GENERIC_READ GENERIC_WRITE }
     share-mode
     f
     OPEN_ALWAYS
index 3999a026c08f08baf6a2e35b2a0f1ed0ad78a376..dfbbd33d2e905fc7cc46f10aaac8bde1eabeb607 100755 (executable)
@@ -129,12 +129,8 @@ M: process-was-killed error.
 
 : (wait-for-process) ( process -- status )
     dup handle>>
-    [
-        dup [ processes get at push ] curry
-        "process" suspend drop
-    ] when
-    dup killed>>
-    [ process-was-killed ] [ status>> ] if ;
+    [ self over processes get at push "process" suspend drop ] when
+    dup killed>> [ process-was-killed ] [ status>> ] if ;
 
 : wait-for-process ( process -- status )
     [ (wait-for-process) ] with-timeout ;
index f426201b062d96eb9930f3aafe1e4c9bf6dcd675..84378efeb80292c3fd1c43f8fedaf2ed3a81c689 100644 (file)
@@ -1,6 +1,6 @@
 ! Copyright (C) 2007 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors destructors io.backend.unix io.mmap
+USING: accessors destructors io.backend.unix io.mmap literals
 io.mmap.private kernel locals math.bitwise system unix unix.ffi ;
 IN: io.mmap.unix
 
@@ -12,13 +12,13 @@ IN: io.mmap.unix
     ] with-destructors ;
 
 M: unix (mapped-file-r/w)
-    { PROT_READ PROT_WRITE } flags
-    { MAP_FILE MAP_SHARED } flags
+    flags{ PROT_READ PROT_WRITE }
+    flags{ MAP_FILE MAP_SHARED }
     O_RDWR mmap-open ;
 
 M: unix (mapped-file-reader)
-    { PROT_READ } flags
-    { MAP_FILE MAP_SHARED } flags
+    flags{ PROT_READ }
+    flags{ MAP_FILE MAP_SHARED }
     O_RDONLY mmap-open ;
 
 M: unix close-mapped-file ( mmap -- )
index e3e3116b59047f5852b9912f7cecdab773bce76a..b1191082b36d78f22b5f69e25ae0f08ef91c9bf2 100644 (file)
@@ -2,7 +2,7 @@ USING: alien alien.c-types arrays destructors generic io.mmap
 io.ports io.backend.windows io.files.windows io.backend.windows.privileges
 io.mmap.private kernel libc math math.bitwise namespaces quotations sequences
 windows windows.advapi32 windows.kernel32 io.backend system
-accessors locals windows.errors ;
+accessors locals windows.errors literals ;
 IN: io.mmap.windows
 
 : create-file-mapping ( hFile lpAttributes flProtect dwMaximumSizeHigh dwMaximumSizeLow lpName -- HANDLE )
@@ -29,9 +29,9 @@ C: <win32-mapped-file> win32-mapped-file
 
 M: windows (mapped-file-r/w)
     [
-        { GENERIC_WRITE GENERIC_READ } flags
+        flags{ GENERIC_WRITE GENERIC_READ }
         OPEN_ALWAYS
-        { PAGE_READWRITE SEC_COMMIT } flags
+        flags{ PAGE_READWRITE SEC_COMMIT }
         FILE_MAP_ALL_ACCESS mmap-open
         -rot <win32-mapped-file>
     ] with-destructors ;
@@ -40,7 +40,7 @@ M: windows (mapped-file-reader)
     [
         GENERIC_READ
         OPEN_ALWAYS
-        { PAGE_READONLY SEC_COMMIT } flags
+        flags{ PAGE_READONLY SEC_COMMIT }
         FILE_MAP_READ mmap-open
         -rot <win32-mapped-file>
     ] with-destructors ;
index 31442b7f0b09723b274f24e5f5243805f601a834..9b2440aec88edc8bb975d312224b215c0f779141 100644 (file)
@@ -5,7 +5,7 @@ io.files io.pathnames io.buffers io.ports io.timeouts
 io.backend.unix io.encodings.utf8 unix.linux.inotify assocs
 namespaces make threads continuations init math math.bitwise
 sets alien alien.strings alien.c-types vocabs.loader accessors
-system hashtables destructors unix classes.struct ;
+system hashtables destructors unix classes.struct literals ;
 FROM: namespaces => set ;
 IN: io.monitors.linux
 
@@ -65,13 +65,13 @@ M: linux-monitor dispose* ( monitor -- )
     tri ;
 
 : ignore-flags? ( mask -- ? )
-    {
+    flags{
         IN_DELETE_SELF
         IN_MOVE_SELF
         IN_UNMOUNT
         IN_Q_OVERFLOW
         IN_IGNORED
-    } flags bitand 0 > ;
+    } bitand 0 > ;
 
 : parse-action ( mask -- changed )
     [
index 4d061cbb1ad2df8a0c79cad79cf738509998ba4b..e6a055a9d62f998fc78da3606ee0b05bd5e9a26c 100644 (file)
@@ -5,7 +5,7 @@ locals kernel math assocs namespaces make continuations sequences
 hashtables sorting arrays combinators math.bitwise strings
 system accessors threads splitting io.backend io.backend.windows
 io.backend.windows.nt io.files.windows.nt io.monitors io.ports
-io.buffers io.files io.timeouts io.encodings.string
+io.buffers io.files io.timeouts io.encodings.string literals
 io.encodings.utf16n io windows.errors windows.kernel32 windows.types
 io.pathnames classes.struct ;
 IN: io.monitors.windows.nt
@@ -16,7 +16,7 @@ IN: io.monitors.windows.nt
     share-mode
     f
     OPEN_EXISTING
-    { FILE_FLAG_BACKUP_SEMANTICS FILE_FLAG_OVERLAPPED } flags
+    flags{ FILE_FLAG_BACKUP_SEMANTICS FILE_FLAG_OVERLAPPED }
     f
     CreateFile opened-file ;
 
index 7fce8b4de22bcab96332a5205a7cc11922ab10cf..d58e5e3d5f883b18334fb8df40c94cf286829443 100644 (file)
@@ -3,14 +3,14 @@
 USING: alien alien.c-types arrays destructors io io.backend.windows libc
 windows.types math.bitwise windows.kernel32 windows namespaces
 make kernel sequences windows.errors assocs math.parser system
-random combinators accessors io.pipes io.ports ;
+random combinators accessors io.pipes io.ports literals ;
 IN: io.pipes.windows.nt
 
 ! This code is based on
 ! http://twistedmatrix.com/trac/browser/trunk/twisted/internet/iocpreactor/process.py
 
 : create-named-pipe ( name -- handle )
-    { PIPE_ACCESS_INBOUND FILE_FLAG_OVERLAPPED } flags
+    flags{ PIPE_ACCESS_INBOUND FILE_FLAG_OVERLAPPED }
     PIPE_TYPE_BYTE
     1
     4096
@@ -21,7 +21,7 @@ IN: io.pipes.windows.nt
 
 : open-other-end ( name -- handle )
     GENERIC_WRITE
-    { FILE_SHARE_READ FILE_SHARE_WRITE } flags
+    flags{ FILE_SHARE_READ FILE_SHARE_WRITE }
     default-security-attributes
     OPEN_EXISTING
     FILE_FLAG_OVERLAPPED
index b89f4174bfa3776a4a8e7c8fbcee053f062c04db..74e96b08d3c82ef7481ef99afdba657f04dbe31e 100644 (file)
@@ -32,6 +32,10 @@ HELP: free
 { $values { "alien" c-ptr } }
 { $description "Deallocates a block of memory allocated by " { $link malloc } ", " { $link calloc } " or " { $link realloc } "." } ;
 
+HELP: (free)
+{ $values { "alien" c-ptr } }
+{ $description "Deallocates a block of memory allocated by an external C library." } ;
+
 HELP: &free
 { $values { "alien" c-ptr } }
 { $description "Marks the block of memory for unconditional deallocation at the end of the current " { $link with-destructors } " scope." } ;
index 5f6a808b2e1b2678796c1451a2b6e6a3c1698cc3..4a887e695ffff7f122b288a84c91df8807e0a647 100644 (file)
@@ -1,5 +1,5 @@
 ! Copyright (C) 2004, 2005 Mackenzie Straight
-! Copyright (C) 2007, 2009 Slava Pestov
+! Copyright (C) 2007, 2010 Slava Pestov
 ! Copyright (C) 2007, 2008 Doug Coleman
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien alien.c-types assocs continuations alien.destructors kernel
@@ -18,8 +18,6 @@ IN: libc
 : preserve-errno ( quot -- )
     errno [ call ] dip set-errno ; inline
 
-<PRIVATE
-
 : (malloc) ( size -- alien )
     void* "libc" "malloc" { ulong } alien-invoke ;
 
@@ -32,6 +30,8 @@ IN: libc
 : (realloc) ( alien size -- newalien )
     void* "libc" "realloc" { void* ulong } alien-invoke ;
 
+<PRIVATE
+
 ! We stick malloc-ptr instances in the global disposables set
 TUPLE: malloc-ptr value continuation ;
 
index a464d75b22bbe939c29e9d97d439ca6eff59c734..6fcf8a5e07c807970d6b510e9fef5704f0c68384 100644 (file)
@@ -1,6 +1,6 @@
 ! Copyright (C) 2008 Joe Groff.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: help.markup help.syntax kernel multiline ;
+USING: help.markup help.syntax kernel multiline sequences ;
 IN: literals
 
 HELP: $
@@ -62,6 +62,19 @@ ${ five six 7 } .
 
 { POSTPONE: $ POSTPONE: $[ POSTPONE: ${ } related-words
 
+HELP: flags{
+{ $values { "values" sequence } }
+{ $description "Constructs a constant flag value from a sequence of integers or words that output integers. The resulting constant is computed at parse-time, which makes this word as efficient as using a literal integer." }
+{ $examples
+    { $example "USING: literals kernel prettyprint ;"
+        "IN: scratchpad"
+        "CONSTANT: x HEX: 1"
+        "flags{ HEX: 20 x BIN: 100 } .h"
+        "25"
+    }
+} ;
+
+
 ARTICLE: "literals" "Interpolating code results into literal values"
 "The " { $vocab-link "literals" } " vocabulary contains words to run code at parse time and insert the results into more complex literal values."
 { $example """
index d7256a64b140f840b8197c2a8594b68035959955..4357198db6e45a68c2372d0a9e7e6612bca764b3 100644 (file)
@@ -1,4 +1,4 @@
-USING: kernel literals math tools.test ;
+USING: accessors kernel literals math tools.test ;
 IN: literals.tests
 
 <<
@@ -27,3 +27,16 @@ CONSTANT: constant-a 3
 : sixty-nine ( -- a b ) 6 9 ;
 
 [ { 6 9 } ] [ ${ sixty-nine } ] unit-test
+
+CONSTANT: a 1
+CONSTANT: b 2
+ALIAS: c b
+ALIAS: d c
+
+CONSTANT: foo flags{ a b d }
+
+[ 3 ] [ foo ] unit-test
+[ 3 ] [ flags{ a b d } ] unit-test
+\ foo def>> must-infer
+
+[ 1 ] [ flags{ 1 } ] unit-test
index 001c56525f3852c5884c7819d1d43ee16944f72f..42a7ab9668a68dc2fb5912d28a6c3b4f56f0a83b 100644 (file)
@@ -1,6 +1,6 @@
 ! (c) Joe Groff, see license for details
-USING: accessors continuations kernel parser words quotations
-vectors sequences fry ;
+USING: accessors combinators continuations fry kernel lexer
+math parser quotations sequences vectors words words.alias ;
 IN: literals
 
 <PRIVATE
@@ -8,8 +8,13 @@ IN: literals
 ! Use def>> call so that CONSTANT:s defined in the same file can
 ! be called
 
+: expand-alias ( obj -- obj' )
+    dup alias? [ def>> first expand-alias ] when ;
+
 : expand-literal ( seq obj -- seq' )
-    '[ _ dup word? [ def>> call ] when ] with-datastack ;
+    '[
+        _ expand-alias dup word? [ def>> call ] when
+    ] with-datastack ;
 
 : expand-literals ( seq -- seq' )
     [ [ { } ] dip expand-literal ] map concat ;
@@ -19,3 +24,8 @@ PRIVATE>
 SYNTAX: $ scan-word expand-literal >vector ;
 SYNTAX: $[ parse-quotation with-datastack >vector ;
 SYNTAX: ${ \ } [ expand-literals ] parse-literal ;
+SYNTAX: flags{
+    \ } [
+        expand-literals
+        0 [ bitor ] reduce
+    ] parse-literal ;
index 468671361f8fe34f63674e6ab30e94e38159ae74..d8a53b3c4e41d970e3d5e9d7037cf712f14b1fd1 100644 (file)
@@ -19,11 +19,6 @@ ERROR: local-writer-in-literal-error ;
 M: local-writer-in-literal-error summary
     drop "Local writer words not permitted inside literals" ;
 
-ERROR: local-word-in-literal-error ;
-
-M: local-word-in-literal-error summary
-    drop "Local words not permitted inside literals" ;
-
 ERROR: :>-outside-lambda-error ;
 
 M: :>-outside-lambda-error summary
index 8e940bfdd8b8100fb9eedc68c0253e0b8411d795..7d67881c47624227ddc86ddad7886c24812d3cae 100644 (file)
@@ -26,7 +26,5 @@ SYNTAX: MEMO:: (::) define-memoized ;
     "locals.fry"
 } [ require ] each
 
-"prettyprint" vocab [
-    "locals.definitions" require
-    "locals.prettyprint" require
-] when
+"prettyprint" "locals.definitions" require-when
+"prettyprint" "locals.prettyprint" require-when
index e742b4768a11fd21fdfa4aad315d9ddac06ff2f2..01be7bcd20ae44b13a380fab80a9d645d7c24670 100644 (file)
@@ -24,10 +24,6 @@ SYMBOL: in-lambda?
 : parse-local-defs ( -- words assoc )
     [ "|" [ make-local ] map-tokens ] H{ } make-assoc ;
 
-: make-local-word ( name def -- word )
-    [ <local-word> [ dup name>> set ] [ ] [ ] tri ] dip
-    "local-word-def" set-word-prop ;
-
 SINGLETON: lambda-parser
 
 SYMBOL: locals
index 4e91e3d87b5dbca91e603b6a925afa665ef54ee2..0b010a559163d837396deff89b8ca3f3c5b145dc 100644 (file)
@@ -21,8 +21,6 @@ M: local localize dupd read-local-quot ;
 
 M: quote localize dupd local>> read-local-quot ;
 
-M: local-word localize dupd read-local-quot [ call ] append ;
-
 M: local-reader localize dupd read-local-quot [ local-value ] append ;
 
 M: local-writer localize
index a8a12d2614d86c3e353e44e93ca76db7d9e3db76..9dfc733fffc0380cbbc1ac89a1cbba81204e7890 100644 (file)
@@ -82,9 +82,6 @@ M: local-reader rewrite-element , ;
 M: local-writer rewrite-element
     local-writer-in-literal-error ;
 
-M: local-word rewrite-element
-    local-word-in-literal-error ;
-
 M: word rewrite-element <wrapper> , ;
 
 : rewrite-wrapper ( wrapper -- )
index 424ef682439edad6faaa049f2aec34366b09533c..a930765b7cea34b8223498cef1298b19eba462c2 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2007, 2009 Slava Pestov, Eduardo Cavazos.
+! Copyright (C) 2007, 2010 Slava Pestov, Eduardo Cavazos.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors combinators kernel sequences words
 quotations ;
@@ -35,11 +35,6 @@ PREDICATE: local < word "local?" word-prop ;
 
 M: local literalize ;
 
-PREDICATE: local-word < word "local-word?" word-prop ;
-
-: <local-word> ( name -- word )
-    f <word> dup t "local-word?" set-word-prop ;
-
 PREDICATE: local-reader < word "local-reader?" word-prop ;
 
 : <local-reader> ( name -- word )
@@ -58,5 +53,5 @@ PREDICATE: local-writer < word "local-writer?" word-prop ;
         [ nip ]
     } 2cleave ;
 
-UNION: lexical local local-reader local-writer local-word ;
+UNION: lexical local local-reader local-writer ;
 UNION: special lexical quote def ;
index bbc72d99e446c974f0a9d7416d254335d30786a4..4024953070565cb0d725c036cd798bb41160da64 100644 (file)
@@ -135,18 +135,6 @@ HELP: clear-bit
     }
 } ;
 
-HELP: flags
-{ $values { "values" sequence } }
-{ $description "Constructs a constant flag value from a sequence of integers or words that output integers. The resulting constant is computed at compile-time, which makes this word as efficient as using a literal integer." }
-{ $examples
-    { $example "USING: math.bitwise kernel prettyprint ;"
-        "IN: scratchpad"
-        "CONSTANT: x HEX: 1"
-        "{ HEX: 20 x BIN: 100 } flags .h"
-        "25"
-    }
-} ;
-
 HELP: symbols>flags
 { $values { "symbols" sequence } { "assoc" assoc } { "flag-bits" integer } }
 { $description "Constructs an integer value by mapping the values in the " { $snippet "symbols" } " sequence to integer values using " { $snippet "assoc" } " and " { $link bitor } "ing the values together." }
@@ -375,6 +363,10 @@ $nl
     bit?
     bit-clear?
 }
+"Toggling a bit:"
+{ $subsections
+    toggle-bit
+}
 "Operations with bitmasks:"
 { $subsections
     mask
@@ -404,7 +396,6 @@ $nl
 }
 "Bitfields:"
 { $subsections
-    flags
     "math-bitfields"
 } ;
 
index a5919d3ec30bedca953e789e698b4ac60a4422e2..93d2d9e882fa62408a66a9d5a364abbd22bea0e3 100644 (file)
@@ -1,6 +1,6 @@
 USING: accessors math math.bitwise tools.test kernel words
 specialized-arrays alien.c-types math.vectors.simd
-sequences destructors libc ;
+sequences destructors libc literals ;
 SPECIALIZED-ARRAY: int
 IN: math.bitwise.tests
 
@@ -23,17 +23,6 @@ IN: math.bitwise.tests
 : test-1+ ( x -- y ) 1 + ;
 [ 512 ] [ 1 { { test-1+ 8 } } bitfield ] unit-test
 
-CONSTANT: a 1
-CONSTANT: b 2
-
-: foo ( -- flags ) { a b } flags ;
-
-[ 3 ] [ foo ] unit-test
-[ 3 ] [ { a b } flags ] unit-test
-\ foo def>> must-infer
-
-[ 1 ] [ { 1 } flags ] unit-test
-
 [ 8 ] [ 0 3 toggle-bit ] unit-test
 [ 0 ] [ 8 3 toggle-bit ] unit-test
 
index 15db425137a7bedfa2d0949555ec53d60f1c91ed..cd38c8513c9a0ebefe8159e1f75f72793dbbb407 100644 (file)
@@ -44,10 +44,6 @@ IN: math.bitwise
 : W- ( x y -- z ) - 64 bits ; inline
 : W* ( x y -- z ) * 64 bits ; inline
 
-! flags
-MACRO: flags ( values -- )
-    [ 0 ] [ [ ?execute bitor ] curry compose ] reduce ;
-
 : symbols>flags ( symbols assoc -- flag-bits )
     [ at ] curry map
     0 [ bitor ] reduce ;
index db3794cbb0edb3ead4e93397b78135d745207b19..78ac5457bcce14f59a18427935717d98449ec58a 100644 (file)
@@ -62,6 +62,6 @@ M: rect contains-point?
     [ [ dim>> ] dip (>>dim) ]
     2bi ; inline
 
-USING: vocabs vocabs.loader ;
+USE: vocabs.loader
 
-"prettyprint" vocab [ "math.rectangles.prettyprint" require ] when
+"prettyprint" "math.rectangles.prettyprint" require-when
index 8d804247d3af681298ff2acea8227e91c816f12c..65d6e113bfed1e5591cc05f12213dcfa68bdff6e 100644 (file)
@@ -339,6 +339,4 @@ M: short-8 v*hs+
 M: int-4 v*hs+
     int-4-rep [ (simd-v*hs+) ] [ call-next-method ] vv->v-op longlong-2-cast ; inline
 
-"mirrors" vocab [
-    "math.vectors.simd.mirrors" require
-] when
+"mirrors" "math.vectors.simd.mirrors" require-when
index 65978f0b46af4d4b68d93744740e2949c6f7d012..f12d34e1701bfb3005bc8d4f79bfa974d61ee0bf 100644 (file)
@@ -59,7 +59,3 @@ M: hashtable make-mirror ;
 M: integer make-mirror drop f ;
 M: enumerated-sequence make-mirror <enum> ;
 M: object make-mirror <mirror> ;
-
-"specialized-arrays" vocab [
-    "specialized-arrays.mirrors" require
-] when
index b4288891e0cb2d1477c77cf658cc25d9e0d7613d..29b26159a778fcc0100ca16ab76019bdfa1fe85b 100644 (file)
@@ -13,7 +13,7 @@ $nl
         "ui.gadgets.labels ui.gadgets.packs ui.gadgets.panes"\r
         "ui.gadgets.sliders ;"\r
         ""\r
-        ": <funny-model> ( -- model ) 0 10 0 100 <range> ;"\r
+        ": <funny-model> ( -- model ) 0 10 0 100 <range> ;"\r
         ": <funny-slider> ( model -- slider ) horizontal <slider> ;"\r
         ""\r
         "<funny-model> <funny-model> 2array"\r
index bfd59cde250ebff57ead1275ff87e71a076c2f90..96d235d271fc5c98f8842f900b72a98067747e45 100644 (file)
@@ -3,7 +3,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien alien.c-types alien.syntax combinators kernel
 system namespaces assocs parser lexer sequences words
-quotations math.bitwise alien.libraries ;
+quotations math.bitwise alien.libraries literals ;
 
 IN: openssl.libssl
 
@@ -258,15 +258,14 @@ CONSTANT: SSL_SESS_CACHE_OFF    HEX: 0000
 CONSTANT: SSL_SESS_CACHE_CLIENT HEX: 0001
 CONSTANT: SSL_SESS_CACHE_SERVER HEX: 0002
 
-: SSL_SESS_CACHE_BOTH ( -- n )
-    { SSL_SESS_CACHE_CLIENT SSL_SESS_CACHE_SERVER } flags ; inline
+CONSTANT: SSL_SESS_CACHE_BOTH flags{ SSL_SESS_CACHE_CLIENT SSL_SESS_CACHE_SERVER }
 
 CONSTANT: SSL_SESS_CACHE_NO_AUTO_CLEAR      HEX: 0080
 CONSTANT: SSL_SESS_CACHE_NO_INTERNAL_LOOKUP HEX: 0100
 CONSTANT: SSL_SESS_CACHE_NO_INTERNAL_STORE  HEX: 0200
 
-: SSL_SESS_CACHE_NO_INTERNAL ( -- n )
-    { SSL_SESS_CACHE_NO_INTERNAL_LOOKUP SSL_SESS_CACHE_NO_INTERNAL_STORE } flags ; inline
+CONSTANT: SSL_SESS_CACHE_NO_INTERNAL
+    flags{ SSL_SESS_CACHE_NO_INTERNAL_LOOKUP SSL_SESS_CACHE_NO_INTERNAL_STORE }
 
 ! ===============================================
 ! x509_vfy.h
index cc480c30b2cfe56e1c36757ffae06e225bb3806e..ca7d28bb97a18d9f29a7a1995631813c95d4ec6d 100644 (file)
@@ -630,6 +630,4 @@ SYNTAX: PEG:
 
 USING: vocabs vocabs.loader ;
 
-"debugger" vocab [
-    "peg.debugger" require
-] when
+"debugger" "peg.debugger" require-when
index 30b169bfedc1ac841f67f138a53b70362d91b5c7..72b908a32fcfefd3b3bed953080d18418ffb539e 100644 (file)
@@ -36,7 +36,7 @@ CONSTANT: factor-crypto-container "FactorCryptoContainer"
     ] if ;
 
 : create-crypto-context ( provider type -- handle )
-    { CRYPT_MACHINE_KEYSET CRYPT_NEWKEYSET } flags
+    flags{ CRYPT_MACHINE_KEYSET CRYPT_NEWKEYSET }
     (acquire-crypto-context) win32-error=0/f *void* ;
 
 ERROR: acquire-crypto-context-failed provider type ;
index 0025b89d56d8119912f5bad662d22a6c75396b5c..a038351cb0cf6bb167f14c57fa0c831a0fe9491a 100644 (file)
@@ -133,7 +133,7 @@ CharacterInBracket = !("}") Character
 QuotedCharacter = !("\\E") .
 
 Escape = "p{" CharacterInBracket*:s "}" => [[ s name>class <primitive-class> ]]
-       | "P{" CharacterInBracket*:s "}" => [[ s name>class <primitive-class> <negation> ]]
+       | "P{" CharacterInBracket*:s "}" => [[ s name>class <primitive-class> <not-class> ]]
        | "Q" QuotedCharacter*:s "\\E" => [[ s <concatenation> ]]
        | "u" Character:a Character:b Character:c Character:d
             => [[ { a b c d } hex> ensure-number ]]
index 1f72fa04bad26ff9ef8900920eb6f2f5414fb739..2488f568dacb004a214d3fcb2764255c6b58d88a 100644 (file)
@@ -530,3 +530,8 @@ IN: regexp-tests
 [ f ] [ "Ï€" R/ [\p{script=latin}--\p{lower}]/ matches? ] unit-test
 [ t ] [ "A" R/ [\p{script=latin}--\p{lower}]/ matches? ] unit-test
 [ f ] [ "3" R/ [\p{script=latin}--\p{lower}]/ matches? ] unit-test
+
+[ t ] [ " " R/ \P{alpha}/ matches? ] unit-test
+[ f ] [ "" R/ \P{alpha}/ matches? ] unit-test
+[ f ] [ "a " R/ \P{alpha}/ matches? ] unit-test
+[ f ] [ "a" R/ \P{alpha}/ matches? ] unit-test
index e5ac1df1514b5ea64e02a107306114bb502c15a2..eea0a26ea5fa4aebe59a692b04befae601d427d2 100644 (file)
@@ -218,6 +218,4 @@ SYNTAX: R| CHAR: | parsing-regexp ;
 
 USING: vocabs vocabs.loader ;
 
-"prettyprint" vocab [
-    "regexp.prettyprint" require
-] when
+"prettyprint" "regexp.prettyprint" require-when
index 11b050d5fcbb32d4147fc0b826dfda19cccad023..c82ebd78c80f71560c5f277eb4ef3da90a37b29c 100644 (file)
@@ -173,10 +173,6 @@ SYNTAX: SPECIALIZED-ARRAYS:
 SYNTAX: SPECIALIZED-ARRAY:
     scan-c-type define-array-vocab use-vocab ;
 
-"prettyprint" vocab [
-    "specialized-arrays.prettyprint" require
-] when
+"prettyprint" "specialized-arrays.prettyprint" require-when
 
-"mirrors" vocab [
-    "specialized-arrays.mirrors" require
-] when
+"mirrors" "specialized-arrays.mirrors" require-when
index 51b5f0cdaf6cf58d1294727c17df26534d36f7b7..7a18133efff7463117a4369910eae64a240958b6 100644 (file)
@@ -151,13 +151,6 @@ M: bad-call summary
 : required-stack-effect ( word -- effect )
     dup stack-effect [ ] [ missing-effect ] ?if ;
 
-: infer-word ( word -- )
-    {
-        { [ dup macro? ] [ do-not-compile ] }
-        { [ dup "no-compile" word-prop ] [ do-not-compile ] }
-        [ dup required-stack-effect apply-word/effect ]
-    } cond ;
-
 : with-infer ( quot -- effect visitor )
     [
         init-inference
index 58ce20035c3440d180cf1d9f49cc55da95fcc61f..5eca37ffbef4ebc690b64159a3dd19085ebf7944 100644 (file)
@@ -1,5 +1,6 @@
-! Copyright (C) 2006, 2009 Slava Pestov.
+! Copyright (C) 2006, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
+USING: vocabs.loader ;
 IN: stack-checker.errors
 
 TUPLE: inference-error ;
@@ -34,3 +35,4 @@ ERROR: bad-declaration-error < inference-error declaration ;
 
 ERROR: unbalanced-branches-error < inference-error word quots declareds actuals ;
 
+"debugger" "stack-checker.errors.prettyprint" require-when
index d0cbb05919210556a66597c0206ea35f08dcc7c9..15895184df8c25d7698831cf452f16c386b01df1 100644 (file)
@@ -1,19 +1,20 @@
 ! Copyright (C) 2004, 2010 Slava Pestov, Daniel Ehrenberg.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: fry accessors alien alien.accessors arrays byte-arrays
-classes continuations.private effects generic hashtables
-hashtables.private io io.backend io.files io.files.private
-io.streams.c kernel kernel.private math math.private
-math.parser.private memory memory.private namespaces
-namespaces.private parser quotations quotations.private sbufs
-sbufs.private sequences sequences.private slots.private strings
-strings.private system threads.private classes.tuple
-classes.tuple.private vectors vectors.private words
-words.private definitions assocs summary compiler.units
-system.private combinators combinators.short-circuit locals
-locals.backend locals.types combinators.private
-stack-checker.values generic.single generic.single.private
-alien.libraries tools.dispatch.private tools.profiler.private
+USING: fry accessors alien alien.accessors alien.private arrays
+byte-arrays classes continuations.private effects generic
+hashtables hashtables.private io io.backend io.files
+io.files.private io.streams.c kernel kernel.private math
+math.private math.parser.private memory memory.private
+namespaces namespaces.private parser quotations
+quotations.private sbufs sbufs.private sequences
+sequences.private slots.private strings strings.private system
+threads.private classes.tuple classes.tuple.private vectors
+vectors.private words words.private definitions assocs summary
+compiler.units system.private combinators
+combinators.short-circuit locals locals.backend locals.types
+combinators.private stack-checker.values generic.single
+generic.single.private alien.libraries tools.dispatch.private
+tools.profiler.private macros
 stack-checker.alien
 stack-checker.state
 stack-checker.errors
@@ -26,11 +27,37 @@ stack-checker.recursive-state
 stack-checker.row-polymorphism ;
 IN: stack-checker.known-words
 
-: infer-primitive ( word -- )
-    dup
-    [ "input-classes" word-prop ]
-    [ "default-output-classes" word-prop ] bi <effect>
-    apply-word/effect ;
+: infer-special ( word -- )
+    [ current-word set ] [ "special" word-prop call( -- ) ] bi ;
+
+: infer-shuffle ( shuffle -- )
+    [ in>> length consume-d ] keep ! inputs shuffle
+    [ drop ] [ shuffle dup copy-values dup output-d ] 2bi ! inputs outputs copies
+    [ nip f f ] [ swap zip ] 2bi ! in-d out-d in-r out-r mapping
+    #shuffle, ;
+
+: infer-shuffle-word ( word -- )
+    "shuffle" word-prop infer-shuffle ;
+
+: infer-local-reader ( word -- )
+    (( -- value )) apply-word/effect ;
+
+: infer-local-writer ( word -- )
+    (( value -- )) apply-word/effect ;
+
+: non-inline-word ( word -- )
+    dup depends-on-effect
+    {
+        { [ dup "shuffle" word-prop ] [ infer-shuffle-word ] }
+        { [ dup "special" word-prop ] [ infer-special ] }
+        { [ dup "transform-quot" word-prop ] [ apply-transform ] }
+        { [ dup macro? ] [ apply-macro ] }
+        { [ dup local? ] [ infer-local-reader ] }
+        { [ dup local-reader? ] [ infer-local-reader ] }
+        { [ dup local-writer? ] [ infer-local-writer ] }
+        { [ dup "no-compile" word-prop ] [ do-not-compile ] }
+        [ dup required-stack-effect apply-word/effect ]
+    } cond ;
 
 {
     { drop  (( x     --             )) }
@@ -50,15 +77,6 @@ IN: stack-checker.known-words
     { swap  (( x y   -- y x         )) }
 } [ "shuffle" set-word-prop ] assoc-each
 
-: infer-shuffle ( shuffle -- )
-    [ in>> length consume-d ] keep ! inputs shuffle
-    [ drop ] [ shuffle dup copy-values dup output-d ] 2bi ! inputs outputs copies
-    [ nip f f ] [ swap zip ] 2bi ! in-d out-d in-r out-r mapping
-    #shuffle, ;
-
-: infer-shuffle-word ( word -- )
-    "shuffle" word-prop infer-shuffle ;
-
 : check-declaration ( declaration -- declaration )
     dup { [ array? ] [ [ class? ] all? ] } 1&&
     [ bad-declaration-error ] unless ;
@@ -179,11 +197,6 @@ M: bad-executable summary
 
 \ call-effect-unsafe [ infer-call-effect-unsafe ] "special" set-word-prop
 
-: infer-exit ( -- )
-    \ exit (( n -- * )) apply-word/effect ;
-
-\ exit [ infer-exit ] "special" set-word-prop
-
 : infer-load-locals ( -- )
     pop-literal nip
     consume-d dup copy-values dup output-r
@@ -246,25 +259,12 @@ M: bad-executable summary
     unwind-native-frames
     lazy-jit-compile
     c-to-factor
-    call-clear
 } [ dup '[ _ do-not-compile ] "special" set-word-prop ] each
 
-: infer-special ( word -- )
-    [ current-word set ] [ "special" word-prop call( -- ) ] bi ;
-
-: infer-local-reader ( word -- )
-    (( -- value )) apply-word/effect ;
-
-: infer-local-writer ( word -- )
-    (( value -- )) apply-word/effect ;
-
-: infer-local-word ( word -- )
-    "local-word-def" word-prop infer-quot-here ;
-
 {
     declare call (call) dip 2dip 3dip curry compose
     execute (execute) call-effect-unsafe execute-effect-unsafe if
-    dispatch <tuple-boa> exit load-local load-locals get-local
+    dispatch <tuple-boa> load-local load-locals get-local
     drop-locals do-primitive alien-invoke alien-indirect
     alien-callback
 } [ t "no-compile" set-word-prop ] each
@@ -276,476 +276,190 @@ M: bad-executable summary
 ! More words not to compile
 \ clear t "no-compile" set-word-prop
 
-: non-inline-word ( word -- )
-    dup depends-on-effect
-    {
-        { [ dup "shuffle" word-prop ] [ infer-shuffle-word ] }
-        { [ dup "special" word-prop ] [ infer-special ] }
-        { [ dup "primitive" word-prop ] [ infer-primitive ] }
-        { [ dup "transform-quot" word-prop ] [ apply-transform ] }
-        { [ dup "macro" word-prop ] [ apply-macro ] }
-        { [ dup local? ] [ infer-local-reader ] }
-        { [ dup local-reader? ] [ infer-local-reader ] }
-        { [ dup local-writer? ] [ infer-local-writer ] }
-        { [ dup local-word? ] [ infer-local-word ] }
-        [ infer-word ]
-    } cond ;
-
 : define-primitive ( word inputs outputs -- )
-    [ 2drop t "primitive" set-word-prop ]
-    [ drop "input-classes" set-word-prop ]
-    [ nip "default-output-classes" set-word-prop ]
-    3tri ;
+    [ "input-classes" set-word-prop ]
+    [ "default-output-classes" set-word-prop ]
+    bi-curry* bi ;
 
 ! Stack effects for all primitives
-\ fixnum< { fixnum fixnum } { object } define-primitive
-\ fixnum< make-foldable
-
-\ fixnum<= { fixnum fixnum } { object } define-primitive
-\ fixnum<= make-foldable
-
-\ fixnum> { fixnum fixnum } { object } define-primitive
-\ fixnum> make-foldable
-
-\ fixnum>= { fixnum fixnum } { object } define-primitive
-\ fixnum>= make-foldable
-
-\ eq? { object object } { object } define-primitive
-\ eq? make-foldable
-
-\ bignum>fixnum { bignum } { fixnum } define-primitive
-\ bignum>fixnum make-foldable
-
-\ float>fixnum { float } { fixnum } define-primitive
-\ bignum>fixnum make-foldable
-
-\ fixnum>bignum { fixnum } { bignum } define-primitive
-\ fixnum>bignum make-foldable
-
-\ float>bignum { float } { bignum } define-primitive
-\ float>bignum make-foldable
-
-\ fixnum>float { fixnum } { float } define-primitive
-\ fixnum>float make-foldable
-
-\ bignum>float { bignum } { float } define-primitive
-\ bignum>float make-foldable
-
-\ (float>string) { float } { byte-array } define-primitive
-\ (float>string) make-foldable
-
-\ float>bits { real } { integer } define-primitive
-\ float>bits make-foldable
-
-\ double>bits { real } { integer } define-primitive
-\ double>bits make-foldable
-
-\ bits>float { integer } { float } define-primitive
-\ bits>float make-foldable
-
-\ bits>double { integer } { float } define-primitive
-\ bits>double make-foldable
-
-\ both-fixnums? { object object } { object } define-primitive
-
-\ fixnum+ { fixnum fixnum } { integer } define-primitive
-\ fixnum+ make-foldable
-
-\ fixnum+fast { fixnum fixnum } { fixnum } define-primitive
-\ fixnum+fast make-foldable
-
-\ fixnum- { fixnum fixnum } { integer } define-primitive
-\ fixnum- make-foldable
-
-\ fixnum-fast { fixnum fixnum } { fixnum } define-primitive
-\ fixnum-fast make-foldable
-
-\ fixnum* { fixnum fixnum } { integer } define-primitive
-\ fixnum* make-foldable
-
-\ fixnum*fast { fixnum fixnum } { fixnum } define-primitive
-\ fixnum*fast make-foldable
-
-\ fixnum/i { fixnum fixnum } { integer } define-primitive
-\ fixnum/i make-foldable
-
-\ fixnum/i-fast { fixnum fixnum } { fixnum } define-primitive
-\ fixnum/i-fast make-foldable
-
-\ fixnum-mod { fixnum fixnum } { fixnum } define-primitive
-\ fixnum-mod make-foldable
-
-\ fixnum/mod { fixnum fixnum } { integer fixnum } define-primitive
-\ fixnum/mod make-foldable
-
-\ fixnum/mod-fast { fixnum fixnum } { fixnum fixnum } define-primitive
-\ fixnum/mod-fast make-foldable
-
-\ fixnum-bitand { fixnum fixnum } { fixnum } define-primitive
-\ fixnum-bitand make-foldable
-
-\ fixnum-bitor { fixnum fixnum } { fixnum } define-primitive
-\ fixnum-bitor make-foldable
-
-\ fixnum-bitxor { fixnum fixnum } { fixnum } define-primitive
-\ fixnum-bitxor make-foldable
-
-\ fixnum-bitnot { fixnum } { fixnum } define-primitive
-\ fixnum-bitnot make-foldable
-
-\ fixnum-shift { fixnum fixnum } { integer } define-primitive
-\ fixnum-shift make-foldable
-
-\ fixnum-shift-fast { fixnum fixnum } { fixnum } define-primitive
-\ fixnum-shift-fast make-foldable
-
-\ bignum= { bignum bignum } { object } define-primitive
-\ bignum= make-foldable
-
-\ bignum+ { bignum bignum } { bignum } define-primitive
-\ bignum+ make-foldable
-
-\ bignum- { bignum bignum } { bignum } define-primitive
-\ bignum- make-foldable
-
-\ bignum* { bignum bignum } { bignum } define-primitive
-\ bignum* make-foldable
-
-\ bignum/i { bignum bignum } { bignum } define-primitive
-\ bignum/i make-foldable
-
-\ bignum-mod { bignum bignum } { bignum } define-primitive
-\ bignum-mod make-foldable
-
-\ bignum/mod { bignum bignum } { bignum bignum } define-primitive
-\ bignum/mod make-foldable
-
-\ bignum-bitand { bignum bignum } { bignum } define-primitive
-\ bignum-bitand make-foldable
-
-\ bignum-bitor { bignum bignum } { bignum } define-primitive
-\ bignum-bitor make-foldable
-
-\ bignum-bitxor { bignum bignum } { bignum } define-primitive
-\ bignum-bitxor make-foldable
-
-\ bignum-bitnot { bignum } { bignum } define-primitive
-\ bignum-bitnot make-foldable
-
-\ bignum-shift { bignum fixnum } { bignum } define-primitive
-\ bignum-shift make-foldable
-
-\ bignum< { bignum bignum } { object } define-primitive
-\ bignum< make-foldable
-
-\ bignum<= { bignum bignum } { object } define-primitive
-\ bignum<= make-foldable
-
-\ bignum> { bignum bignum } { object } define-primitive
-\ bignum> make-foldable
-
-\ bignum>= { bignum bignum } { object } define-primitive
-\ bignum>= make-foldable
-
-\ bignum-bit? { bignum integer } { object } define-primitive
-\ bignum-bit? make-foldable
-
-\ bignum-log2 { bignum } { bignum } define-primitive
-\ bignum-log2 make-foldable
-
-\ byte-array>bignum { byte-array } { bignum } define-primitive
-\ byte-array>bignum make-foldable
-
-\ float= { float float } { object } define-primitive
-\ float= make-foldable
-
-\ float+ { float float } { float } define-primitive
-\ float+ make-foldable
-
-\ float- { float float } { float } define-primitive
-\ float- make-foldable
-
-\ float* { float float } { float } define-primitive
-\ float* make-foldable
-
-\ float/f { float float } { float } define-primitive
-\ float/f make-foldable
-
-\ float-mod { float float } { float } define-primitive
-\ float-mod make-foldable
-
-\ float< { float float } { object } define-primitive
-\ float< make-foldable
-
-\ float<= { float float } { object } define-primitive
-\ float<= make-foldable
-
-\ float> { float float } { object } define-primitive
-\ float> make-foldable
-
-\ float>= { float float } { object } define-primitive
-\ float>= make-foldable
-
-\ float-u< { float float } { object } define-primitive
-\ float-u< make-foldable
-
-\ float-u<= { float float } { object } define-primitive
-\ float-u<= make-foldable
-
-\ float-u> { float float } { object } define-primitive
-\ float-u> make-foldable
-
-\ float-u>= { float float } { object } define-primitive
-\ float-u>= make-foldable
-
-\ (word) { object object object } { word } define-primitive
-\ (word) make-flushable
-
-\ word-code { word } { integer integer } define-primitive
-\ word-code make-flushable
-
-\ special-object { fixnum } { object } define-primitive
-\ special-object make-flushable
-
-\ set-special-object { object fixnum } { } define-primitive
-
-\ context-object { fixnum } { object } define-primitive
-\ context-object make-flushable
-
-\ set-context-object { object fixnum } { } define-primitive
-
+\ (byte-array) { integer } { byte-array } define-primitive \ (byte-array) make-flushable
+\ (clone) { object } { object } define-primitive \ (clone) make-flushable
+\ (code-blocks) { } { array } define-primitive \ (code-blocks)  make-flushable
+\ (dlopen) { byte-array } { dll } define-primitive
+\ (dlsym) { byte-array object } { c-ptr } define-primitive
 \ (exists?) { string } { object } define-primitive
-
-\ minor-gc { } { } define-primitive
-
-\ gc { } { } define-primitive
-
-\ compact-gc { } { } define-primitive
-
+\ (exit) { integer } { } define-primitive
+\ (float>string) { float } { byte-array } define-primitive \ (float>string) make-foldable
+\ (fopen) { byte-array byte-array } { alien } define-primitive
+\ (identity-hashcode) { object } { fixnum } define-primitive
 \ (save-image) { byte-array byte-array } { } define-primitive
-
 \ (save-image-and-exit) { byte-array byte-array } { } define-primitive
-
-\ data-room { } { byte-array } define-primitive
-\ data-room make-flushable
-
-\ (code-blocks) { } { array } define-primitive
-\ (code-blocks)  make-flushable
-
-\ code-room { } { byte-array } define-primitive
-\ code-room  make-flushable
-
-\ system-micros { } { integer } define-primitive
-\ system-micros make-flushable
-
-\ nano-count { } { integer } define-primitive
-\ nano-count make-flushable
-
-\ tag { object } { fixnum } define-primitive
-\ tag make-foldable
-
-\ (dlopen) { byte-array } { dll } define-primitive
-
-\ (dlsym) { byte-array object } { c-ptr } define-primitive
-
-\ dlclose { dll } { } define-primitive
-
-\ <byte-array> { integer } { byte-array } define-primitive
-\ <byte-array> make-flushable
-
-\ (byte-array) { integer } { byte-array } define-primitive
-\ (byte-array) make-flushable
-
-\ <displaced-alien> { integer c-ptr } { c-ptr } define-primitive
-\ <displaced-alien> make-flushable
-
-\ alien-signed-cell { c-ptr integer } { integer } define-primitive
-\ alien-signed-cell make-flushable
-
-\ set-alien-signed-cell { integer c-ptr integer } { } define-primitive
-
-\ alien-unsigned-cell { c-ptr integer } { integer } define-primitive
-\ alien-unsigned-cell make-flushable
-
-\ set-alien-unsigned-cell { integer c-ptr integer } { } define-primitive
-
-\ alien-signed-8 { c-ptr integer } { integer } define-primitive
-\ alien-signed-8 make-flushable
-
-\ set-alien-signed-8 { integer c-ptr integer } { } define-primitive
-
-\ alien-unsigned-8 { c-ptr integer } { integer } define-primitive
-\ alien-unsigned-8 make-flushable
-
-\ set-alien-unsigned-8 { integer c-ptr integer } { } define-primitive
-
-\ alien-signed-4 { c-ptr integer } { integer } define-primitive
-\ alien-signed-4 make-flushable
-
-\ set-alien-signed-4 { integer c-ptr integer } { } define-primitive
-
-\ alien-unsigned-4 { c-ptr integer } { integer } define-primitive
-\ alien-unsigned-4 make-flushable
-
-\ set-alien-unsigned-4 { integer c-ptr integer } { } define-primitive
-
-\ alien-signed-2 { c-ptr integer } { fixnum } define-primitive
-\ alien-signed-2 make-flushable
-
-\ set-alien-signed-2 { integer c-ptr integer } { } define-primitive
-
-\ alien-unsigned-2 { c-ptr integer } { fixnum } define-primitive
-\ alien-unsigned-2 make-flushable
-
-\ set-alien-unsigned-2 { integer c-ptr integer } { } define-primitive
-
-\ alien-signed-1 { c-ptr integer } { fixnum } define-primitive
-\ alien-signed-1 make-flushable
-
-\ set-alien-signed-1 { integer c-ptr integer } { } define-primitive
-
-\ alien-unsigned-1 { c-ptr integer } { fixnum } define-primitive
-\ alien-unsigned-1 make-flushable
-
-\ set-alien-unsigned-1 { integer c-ptr integer } { } define-primitive
-
-\ alien-float { c-ptr integer } { float } define-primitive
-\ alien-float make-flushable
-
-\ set-alien-float { float c-ptr integer } { } define-primitive
-
-\ alien-double { c-ptr integer } { float } define-primitive
-\ alien-double make-flushable
-
-\ set-alien-double { float c-ptr integer } { } define-primitive
-
-\ alien-cell { c-ptr integer } { pinned-c-ptr } define-primitive
-\ alien-cell make-flushable
-
-\ set-alien-cell { c-ptr c-ptr integer } { } define-primitive
-
-\ alien-address { alien } { integer } define-primitive
-\ alien-address make-flushable
-
-\ slot { object fixnum } { object } define-primitive
-\ slot make-flushable
-
-\ set-slot { object object fixnum } { } define-primitive
-
-\ string-nth { fixnum string } { fixnum } define-primitive
-\ string-nth make-flushable
-
-\ set-string-nth-slow { fixnum fixnum string } { } define-primitive
-\ set-string-nth-fast { fixnum fixnum string } { } define-primitive
-
-\ resize-array { integer array } { array } define-primitive
-\ resize-array make-flushable
-
-\ resize-byte-array { integer byte-array } { byte-array } define-primitive
-\ resize-byte-array make-flushable
-
-\ resize-string { integer string } { string } define-primitive
-\ resize-string make-flushable
-
-\ <array> { integer object } { array } define-primitive
-\ <array> make-flushable
-
+\ (set-context) { object alien } { object } define-primitive
+\ (set-context-and-delete) { object alien } { } define-primitive
+\ (sleep) { integer } { } define-primitive
+\ (start-context) { object quotation } { object } define-primitive
+\ (start-context-and-delete) { object quotation } { } define-primitive
+\ (word) { object object object } { word } define-primitive \ (word) make-flushable
+\ <array> { integer object } { array } define-primitive \ <array> make-flushable
+\ <byte-array> { integer } { byte-array } define-primitive \ <byte-array> make-flushable
+\ <callback> { integer word } { alien } define-primitive
+\ <displaced-alien> { integer c-ptr } { c-ptr } define-primitive \ <displaced-alien> make-flushable
+\ <string> { integer integer } { string } define-primitive \ <string> make-flushable
+\ <tuple> { tuple-layout } { tuple } define-primitive \ <tuple> make-flushable
+\ <wrapper> { object } { wrapper } define-primitive \ <wrapper> make-foldable
+\ alien-address { alien } { integer } define-primitive \ alien-address make-flushable
+\ alien-cell { c-ptr integer } { pinned-c-ptr } define-primitive \ alien-cell make-flushable
+\ alien-double { c-ptr integer } { float } define-primitive \ alien-double make-flushable
+\ alien-float { c-ptr integer } { float } define-primitive \ alien-float make-flushable
+\ alien-signed-1 { c-ptr integer } { fixnum } define-primitive \ alien-signed-1 make-flushable
+\ alien-signed-2 { c-ptr integer } { fixnum } define-primitive \ alien-signed-2 make-flushable
+\ alien-signed-4 { c-ptr integer } { integer } define-primitive \ alien-signed-4 make-flushable
+\ alien-signed-8 { c-ptr integer } { integer } define-primitive \ alien-signed-8 make-flushable
+\ alien-signed-cell { c-ptr integer } { integer } define-primitive \ alien-signed-cell make-flushable
+\ alien-unsigned-1 { c-ptr integer } { fixnum } define-primitive \ alien-unsigned-1 make-flushable
+\ alien-unsigned-2 { c-ptr integer } { fixnum } define-primitive \ alien-unsigned-2 make-flushable
+\ alien-unsigned-4 { c-ptr integer } { integer } define-primitive \ alien-unsigned-4 make-flushable
+\ alien-unsigned-8 { c-ptr integer } { integer } define-primitive \ alien-unsigned-8 make-flushable
+\ alien-unsigned-cell { c-ptr integer } { integer } define-primitive \ alien-unsigned-cell make-flushable
 \ all-instances { } { array } define-primitive
-
-\ size { object } { fixnum } define-primitive
-\ size make-flushable
-
+\ array>quotation { array } { quotation } define-primitive \ array>quotation make-foldable
+\ become { array array } { } define-primitive
+\ bignum* { bignum bignum } { bignum } define-primitive \ bignum* make-foldable
+\ bignum+ { bignum bignum } { bignum } define-primitive \ bignum+ make-foldable
+\ bignum- { bignum bignum } { bignum } define-primitive \ bignum- make-foldable
+\ bignum-bit? { bignum integer } { object } define-primitive \ bignum-bit? make-foldable
+\ bignum-bitand { bignum bignum } { bignum } define-primitive \ bignum-bitand make-foldable
+\ bignum-bitnot { bignum } { bignum } define-primitive \ bignum-bitnot make-foldable
+\ bignum-bitor { bignum bignum } { bignum } define-primitive \ bignum-bitor make-foldable
+\ bignum-bitxor { bignum bignum } { bignum } define-primitive \ bignum-bitxor make-foldable
+\ bignum-log2 { bignum } { bignum } define-primitive \ bignum-log2 make-foldable
+\ bignum-mod { bignum bignum } { bignum } define-primitive \ bignum-mod make-foldable
+\ bignum-shift { bignum fixnum } { bignum } define-primitive \ bignum-shift make-foldable
+\ bignum/i { bignum bignum } { bignum } define-primitive \ bignum/i make-foldable
+\ bignum/mod { bignum bignum } { bignum bignum } define-primitive \ bignum/mod make-foldable
+\ bignum< { bignum bignum } { object } define-primitive \ bignum< make-foldable
+\ bignum<= { bignum bignum } { object } define-primitive \ bignum<= make-foldable
+\ bignum= { bignum bignum } { object } define-primitive \ bignum= make-foldable
+\ bignum> { bignum bignum } { object } define-primitive \ bignum> make-foldable
+\ bignum>= { bignum bignum } { object } define-primitive \ bignum>= make-foldable
+\ bignum>fixnum { bignum } { fixnum } define-primitive \ bignum>fixnum make-foldable
+\ bignum>float { bignum } { float } define-primitive \ bignum>float make-foldable
+\ bits>double { integer } { float } define-primitive \ bits>double make-foldable
+\ bits>float { integer } { float } define-primitive \ bits>float make-foldable
+\ both-fixnums? { object object } { object } define-primitive
+\ byte-array>bignum { byte-array } { bignum } define-primitive \ byte-array>bignum make-foldable
+\ callstack { } { callstack } define-primitive \ callstack make-flushable
+\ callstack-for { c-ptr } { callstack } define-primitive \ callstack make-flushable
+\ callstack>array { callstack } { array } define-primitive \ callstack>array make-flushable
+\ check-datastack { array integer integer } { object } define-primitive \ check-datastack make-flushable
+\ code-room { } { byte-array } define-primitive \ code-room  make-flushable
+\ compact-gc { } { } define-primitive
+\ compute-identity-hashcode { object } { } define-primitive
+\ context-object { fixnum } { object } define-primitive \ context-object make-flushable
+\ context-object-for { fixnum c-ptr } { object } define-primitive \ context-object-for make-flushable
+\ current-callback { } { fixnum } define-primitive \ current-callback make-flushable
+\ data-room { } { byte-array } define-primitive \ data-room make-flushable
+\ datastack { } { array } define-primitive \ datastack make-flushable
+\ datastack-for { c-ptr } { array } define-primitive \ datastack-for make-flushable
 \ die { } { } define-primitive
-
-\ (fopen) { byte-array byte-array } { alien } define-primitive
-
+\ disable-gc-events { } { object } define-primitive
+\ dispatch-stats { } { byte-array } define-primitive
+\ dlclose { dll } { } define-primitive
+\ dll-valid? { object } { object } define-primitive
+\ double>bits { real } { integer } define-primitive \ double>bits make-foldable
+\ enable-gc-events { } { } define-primitive
+\ eq? { object object } { object } define-primitive \ eq? make-foldable
+\ fclose { alien } { } define-primitive
+\ fflush { alien } { } define-primitive
 \ fgetc { alien } { object } define-primitive
-
-\ fwrite { c-ptr integer alien } { } define-primitive
-
+\ fixnum* { fixnum fixnum } { integer } define-primitive \ fixnum* make-foldable
+\ fixnum*fast { fixnum fixnum } { fixnum } define-primitive \ fixnum*fast make-foldable
+\ fixnum+ { fixnum fixnum } { integer } define-primitive \ fixnum+ make-foldable
+\ fixnum+fast { fixnum fixnum } { fixnum } define-primitive \ fixnum+fast make-foldable
+\ fixnum- { fixnum fixnum } { integer } define-primitive \ fixnum- make-foldable
+\ fixnum-bitand { fixnum fixnum } { fixnum } define-primitive \ fixnum-bitand make-foldable
+\ fixnum-bitnot { fixnum } { fixnum } define-primitive \ fixnum-bitnot make-foldable
+\ fixnum-bitor { fixnum fixnum } { fixnum } define-primitive \ fixnum-bitor make-foldable
+\ fixnum-bitxor { fixnum fixnum } { fixnum } define-primitive \ fixnum-bitxor make-foldable
+\ fixnum-fast { fixnum fixnum } { fixnum } define-primitive \ fixnum-fast make-foldable
+\ fixnum-mod { fixnum fixnum } { fixnum } define-primitive \ fixnum-mod make-foldable
+\ fixnum-shift { fixnum fixnum } { integer } define-primitive \ fixnum-shift make-foldable
+\ fixnum-shift-fast { fixnum fixnum } { fixnum } define-primitive \ fixnum-shift-fast make-foldable
+\ fixnum/i { fixnum fixnum } { integer } define-primitive \ fixnum/i make-foldable
+\ fixnum/i-fast { fixnum fixnum } { fixnum } define-primitive \ fixnum/i-fast make-foldable
+\ fixnum/mod { fixnum fixnum } { integer fixnum } define-primitive \ fixnum/mod make-foldable
+\ fixnum/mod-fast { fixnum fixnum } { fixnum fixnum } define-primitive \ fixnum/mod-fast make-foldable
+\ fixnum< { fixnum fixnum } { object } define-primitive \ fixnum< make-foldable
+\ fixnum<= { fixnum fixnum } { object } define-primitive \ fixnum<= make-foldable
+\ fixnum> { fixnum fixnum } { object } define-primitive \ fixnum> make-foldable
+\ fixnum>= { fixnum fixnum } { object } define-primitive \ fixnum>= make-foldable
+\ fixnum>bignum { fixnum } { bignum } define-primitive \ fixnum>bignum make-foldable
+\ fixnum>float { fixnum } { float } define-primitive \ fixnum>float make-foldable
+\ float* { float float } { float } define-primitive \ float* make-foldable
+\ float+ { float float } { float } define-primitive \ float+ make-foldable
+\ float- { float float } { float } define-primitive \ float- make-foldable
+\ float-mod { float float } { float } define-primitive \ float-mod make-foldable
+\ float-u< { float float } { object } define-primitive \ float-u< make-foldable
+\ float-u<= { float float } { object } define-primitive \ float-u<= make-foldable
+\ float-u> { float float } { object } define-primitive \ float-u> make-foldable
+\ float-u>= { float float } { object } define-primitive \ float-u>= make-foldable
+\ float/f { float float } { float } define-primitive \ float/f make-foldable
+\ float< { float float } { object } define-primitive \ float< make-foldable
+\ float<= { float float } { object } define-primitive \ float<= make-foldable
+\ float= { float float } { object } define-primitive \ float= make-foldable
+\ float> { float float } { object } define-primitive \ float> make-foldable
+\ float>= { float float } { object } define-primitive \ float>= make-foldable
+\ float>bignum { float } { bignum } define-primitive \ float>bignum make-foldable
+\ float>bits { real } { integer } define-primitive \ float>bits make-foldable
+\ float>fixnum { float } { fixnum } define-primitive \ bignum>fixnum make-foldable
 \ fputc { object alien } { } define-primitive
-
 \ fread { integer alien } { object } define-primitive
-
-\ fflush { alien } { } define-primitive
-
 \ fseek { integer integer alien } { } define-primitive
-
 \ ftell { alien } { integer } define-primitive
-
-\ fclose { alien } { } define-primitive
-
-\ <wrapper> { object } { wrapper } define-primitive
-\ <wrapper> make-foldable
-
-\ (clone) { object } { object } define-primitive
-\ (clone) make-flushable
-
-\ <string> { integer integer } { string } define-primitive
-\ <string> make-flushable
-
-\ array>quotation { array } { quotation } define-primitive
-\ array>quotation make-flushable
-
-\ quotation-code { quotation } { integer integer } define-primitive
-\ quotation-code make-flushable
-
-\ <tuple> { tuple-layout } { tuple } define-primitive
-\ <tuple> make-flushable
-
-\ datastack { } { array } define-primitive
-\ datastack make-flushable
-
-\ check-datastack { array integer integer } { object } define-primitive
-\ check-datastack make-flushable
-
-\ retainstack { } { array } define-primitive
-\ retainstack make-flushable
-
-\ callstack { } { callstack } define-primitive
-\ callstack make-flushable
-
-\ callstack>array { callstack } { array } define-primitive
-\ callstack>array make-flushable
-
-\ (sleep) { integer } { } define-primitive
-
-\ become { array array } { } define-primitive
-
+\ fwrite { c-ptr integer alien } { } define-primitive
+\ gc { } { } define-primitive
 \ innermost-frame-executing { callstack } { object } define-primitive
-
 \ innermost-frame-scan { callstack } { fixnum } define-primitive
-
-\ set-innermost-frame-quot { quotation callstack } { } define-primitive
-
-\ dll-valid? { object } { object } define-primitive
-
-\ modify-code-heap { array object object } { } define-primitive
-
-\ unimplemented { } { } define-primitive
-
 \ jit-compile { quotation } { } define-primitive
-
 \ lookup-method { object array } { word } define-primitive
-
-\ reset-dispatch-stats { } { } define-primitive
-\ dispatch-stats { } { byte-array } define-primitive
-
+\ minor-gc { } { } define-primitive
+\ modify-code-heap { array object object } { } define-primitive
+\ nano-count { } { integer } define-primitive \ nano-count make-flushable
 \ optimized? { word } { object } define-primitive
-
-\ strip-stack-traces { } { } define-primitive
-
-\ <callback> { integer word } { alien } define-primitive
-
-\ enable-gc-events { } { } define-primitive
-\ disable-gc-events { } { object } define-primitive
-
 \ profiling { object } { } define-primitive
-
-\ (identity-hashcode) { object } { fixnum } define-primitive
-
-\ compute-identity-hashcode { object } { } define-primitive
-
-\ (exit) { integer } { } define-primitive
-
 \ quot-compiled? { quotation } { object } define-primitive
+\ quotation-code { quotation } { integer integer } define-primitive \ quotation-code make-flushable
+\ reset-dispatch-stats { } { } define-primitive
+\ resize-array { integer array } { array } define-primitive \ resize-array make-flushable
+\ resize-byte-array { integer byte-array } { byte-array } define-primitive \ resize-byte-array make-flushable
+\ resize-string { integer string } { string } define-primitive \ resize-string make-flushable
+\ retainstack { } { array } define-primitive \ retainstack make-flushable
+\ retainstack-for { c-ptr } { array } define-primitive \ retainstack-for make-flushable
+\ set-alien-cell { c-ptr c-ptr integer } { } define-primitive
+\ set-alien-double { float c-ptr integer } { } define-primitive
+\ set-alien-float { float c-ptr integer } { } define-primitive
+\ set-alien-signed-1 { integer c-ptr integer } { } define-primitive
+\ set-alien-signed-2 { integer c-ptr integer } { } define-primitive
+\ set-alien-signed-4 { integer c-ptr integer } { } define-primitive
+\ set-alien-signed-8 { integer c-ptr integer } { } define-primitive
+\ set-alien-signed-cell { integer c-ptr integer } { } define-primitive
+\ set-alien-unsigned-1 { integer c-ptr integer } { } define-primitive
+\ set-alien-unsigned-2 { integer c-ptr integer } { } define-primitive
+\ set-alien-unsigned-4 { integer c-ptr integer } { } define-primitive
+\ set-alien-unsigned-8 { integer c-ptr integer } { } define-primitive
+\ set-alien-unsigned-cell { integer c-ptr integer } { } define-primitive
+\ set-context-object { object fixnum } { } define-primitive
+\ set-innermost-frame-quot { quotation callstack } { } define-primitive
+\ set-slot { object object fixnum } { } define-primitive
+\ set-special-object { object fixnum } { } define-primitive
+\ set-string-nth-fast { fixnum fixnum string } { } define-primitive
+\ set-string-nth-slow { fixnum fixnum string } { } define-primitive
+\ size { object } { fixnum } define-primitive \ size make-flushable
+\ slot { object fixnum } { object } define-primitive \ slot make-flushable
+\ special-object { fixnum } { object } define-primitive \ special-object make-flushable
+\ string-nth { fixnum string } { fixnum } define-primitive \ string-nth make-flushable
+\ strip-stack-traces { } { } define-primitive
+\ system-micros { } { integer } define-primitive \ system-micros make-flushable
+\ tag { object } { fixnum } define-primitive \ tag make-foldable
+\ unimplemented { } { } define-primitive
+\ word-code { word } { integer integer } define-primitive \ word-code make-flushable
index 995fc867e71c94f9160fa25f607187ff032d241e..3e63a81d9abaf326445d879fd869b420751b188a 100644 (file)
@@ -1,6 +1,6 @@
 USING: help.markup help.syntax kernel kernel.private io
-threads.private continuations init quotations strings
-assocs heaps boxes namespaces deques dlists system ;
+threads.private init quotations strings assocs heaps boxes
+namespaces deques dlists system ;
 IN: threads
 
 ARTICLE: "threads-start/stop" "Starting and stopping threads"
@@ -48,7 +48,7 @@ ARTICLE: "thread-state" "Thread-local state and variables"
 $nl
 "Global hashtable of all threads, keyed by " { $snippet "id" } ":"
 { $subsections threads }
-"Threads have an identity independent of continuations. If a continuation is refied in one thread and then resumed in another thread, the code running in that continuation will observe a change in the value output by " { $link self } "." ;
+"Threads have an identity independent of continuations. If a continuation is reified in one thread and then reflected in another thread, the code running in that continuation will observe a change in the value output by " { $link self } "." ;
 
 ARTICLE: "thread-impl" "Thread implementation"
 "Thread implementation:"
@@ -57,10 +57,8 @@ ARTICLE: "thread-impl" "Thread implementation"
     sleep-queue
 } ;
 
-ARTICLE: "threads" "Lightweight co-operative threads"
-"Factor supports lightweight co-operative threads implemented on top of " { $link "continuations" } ". A thread will yield while waiting for input/output operations to complete, or when a yield has been explicitly requested."
-$nl
-"Factor threads are very lightweight. Each thread can take as little as 900 bytes of memory. This library has been tested running hundreds of thousands of simple threads."
+ARTICLE: "threads" "Co-operative threads"
+"Factor supports co-operative threads. A thread will yield while waiting for input/output operations to complete, or when a yield has been explicitly requested."
 $nl
 "Words for working with threads are in the " { $vocab-link "threads" } " vocabulary."
 { $subsections
@@ -78,7 +76,7 @@ HELP: thread
         { { $snippet "id" } " - a unique identifier assigned to each thread." }
         { { $snippet "name" } " - the name passed to " { $link spawn } "." }
         { { $snippet "quot" } " - the initial quotation passed to " { $link spawn } "." }
-        { { $snippet "continuation" } " - a " { $link box } "; if the thread is ready to run, the box holds the continuation, otherwise it is empty." }
+        { { $snippet "status" } " - a " { $link string } " indicating what the thread is waiting for, or " { $link f } ". This slot is intended to be used for debugging purposes." }
     }
 } ;
 
@@ -142,10 +140,8 @@ HELP: interrupt
 { $description "Interrupts a sleeping thread." } ;
 
 HELP: suspend
-{ $values { "quot" { $quotation "( thread -- )" } } { "state" string } { "obj" object } }
-{ $description "Suspends the current thread and passes it to the quotation."
-$nl
-"After the quotation returns, control yields to the next runnable thread and the current thread does not execute again until it is resumed, and so the quotation must arrange for another thread to later resume the suspended thread with a call to " { $link resume } " or " { $link resume-with } "."
+{ $values { "state" string } { "obj" object } }
+{ $description "Suspends the current thread. Control yields to the next runnable thread and the current thread does not execute again until it is resumed, and so the caller of this word must arrange for another thread to later resume the suspended thread with a call to " { $link resume } " or " { $link resume-with } "."
 $nl
 "The status string is for debugging purposes; see " { $link "tools.threads" } "." } ;
 
index 4568b7c491c76cf73b077f5ffdd3108107ed076c..01578d4e64a8767e49918de6d1d81b1d46496874 100644 (file)
@@ -13,9 +13,7 @@ yield
 [ ] [ 0.3 sleep ] unit-test
 [ "hey" sleep ] must-fail
 
-[ 3 ] [
-    [ 3 swap resume-with ] "Test suspend" suspend
-] unit-test
+[ 3 ] [ 3 self resume-with "Test suspend" suspend ] unit-test
 
 [ f ] [ f get-global ] unit-test
 
@@ -29,8 +27,6 @@ yield
     ] parallel-map
 ] unit-test
 
-[ [ 3 throw ] "A" suspend ] [ 3 = ] must-fail-with
-
 :: spawn-namespace-test ( -- ? )
     <promise> :> p gensym :> g
     [
@@ -44,3 +40,22 @@ yield
 [ "a" [ 1 1 + ] spawn 100 sleep ] must-fail
 
 [ ] [ 0.1 seconds sleep ] unit-test
+
+! Test thread-local variables
+<promise> "p" set
+
+5 "x" tset
+
+[ 5 ] [ "x" tget ] unit-test
+
+[ ] [ "x" [ 1 + ] tchange ] unit-test
+
+[ 6 ] [ "x" tget ] unit-test
+
+! Are they truly thread-local?
+[ "x" tget "p" get fulfill ] in-thread
+
+[ f ] [ "p" get ?promise ] unit-test
+
+! Test system traps inside threads
+[ ] [ [ dup ] in-thread yield ] unit-test
index 952652d801dbeeb036e200ef1337694732eb4165..330b4abd6cae99b88a9b61d9302f061f3d8e8739 100644 (file)
@@ -1,12 +1,49 @@
-! Copyright (C) 2004, 2009 Slava Pestov.
+! Copyright (C) 2004, 2010 Slava Pestov.
 ! Copyright (C) 2005 Mackenzie Straight.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays hashtables heaps kernel kernel.private math
 namespaces sequences vectors continuations continuations.private
-dlists assocs system combinators combinators.private init boxes
-accessors math.order deques strings quotations fry ;
+dlists assocs system combinators init boxes accessors math.order
+deques strings quotations fry ;
 IN: threads
 
+<PRIVATE
+
+! Wrap sub-primitives; we don't want them inlined into callers
+! since their behavior depends on what frames are on the callstack
+: context ( -- context )
+    2 context-object ; inline
+
+: set-context ( obj context -- obj' )
+    (set-context) ; inline
+
+: start-context ( obj quot: ( obj -- * ) -- obj' )
+    (start-context) ; inline
+
+: set-context-and-delete ( obj context -- * )
+    (set-context-and-delete) ; inline
+
+: start-context-and-delete ( obj quot: ( obj -- * ) -- * )
+    (start-context-and-delete) ; inline
+
+! Context introspection
+: namestack-for ( context -- namestack )
+    [ 0 ] dip context-object-for ;
+
+: catchstack-for ( context -- catchstack )
+    [ 1 ] dip context-object-for ;
+
+: continuation-for ( context -- continuation )
+    {
+        [ datastack-for ]
+        [ callstack-for ]
+        [ retainstack-for ]
+        [ namestack-for ]
+        [ catchstack-for ]
+    } cleave <continuation> ;
+
+PRIVATE>
+
 SYMBOL: initial-thread
 
 TUPLE: thread
@@ -14,82 +51,75 @@ TUPLE: thread
 { quot callable initial: [ ] }
 { exit-handler callable initial: [ ] }
 { id integer }
-continuation
+{ context box }
 state
 runnable
 mailbox
-variables
+{ variables hashtable }
 sleep-entry ;
 
-: self ( -- thread ) 63 special-object ; inline
+: self ( -- thread )
+    63 special-object { thread } declare ; inline
+
+: thread-continuation ( thread -- continuation )
+    context>> check-box value>> continuation-for ;
 
 ! Thread-local storage
 : tnamespace ( -- assoc )
-    self variables>> [ H{ } clone dup self (>>variables) ] unless* ;
+    self variables>> ; inline
 
 : tget ( key -- value )
-    self variables>> at ;
+    tnamespace at ;
 
 : tset ( value key -- )
     tnamespace set-at ;
 
 : tchange ( key quot -- )
-    tnamespace swap change-at ; inline
+    [ tnamespace ] dip change-at ; inline
 
-: threads ( -- assoc ) 64 special-object ;
-
-: thread ( id -- thread ) threads at ;
+: threads ( -- assoc )
+    64 special-object { hashtable } declare ; inline
 
 : thread-registered? ( thread -- ? )
     id>> threads key? ;
 
-ERROR: already-stopped thread ;
-
-: check-unregistered ( thread -- thread )
-    dup thread-registered? [ already-stopped ] when ;
-
-ERROR: not-running thread ;
-
-: check-registered ( thread -- thread )
-    dup thread-registered? [ not-running ] unless ;
-
 <PRIVATE
 
 : register-thread ( thread -- )
-    check-unregistered dup id>> threads set-at ;
+    dup id>> threads set-at ;
 
 : unregister-thread ( thread -- )
-    check-registered id>> threads delete-at ;
+    id>> threads delete-at ;
 
 : set-self ( thread -- ) 63 set-special-object ; inline
 
 PRIVATE>
 
+: run-queue ( -- dlist )
+    65 special-object { dlist } declare ; inline
+
+: sleep-queue ( -- heap )
+    66 special-object { min-heap } declare ; inline
+
 : new-thread ( quot name class -- thread )
     new
         swap >>name
         swap >>quot
         \ thread counter >>id
-        <box> >>continuation ; inline
+        H{ } clone >>variables
+        <box> >>context ; inline
 
 : <thread> ( quot name -- thread )
     \ thread new-thread ;
 
-: run-queue ( -- dlist ) 65 special-object ;
-
-: sleep-queue ( -- heap ) 66 special-object ;
-
 : resume ( thread -- )
-    f >>state
-    check-registered run-queue push-front ;
+    f >>state run-queue push-front ;
 
 : resume-now ( thread -- )
-    f >>state
-    check-registered run-queue push-back ;
+    f >>state run-queue push-back ;
 
 : resume-with ( obj thread -- )
-    f >>state
-    check-registered 2array run-queue push-front ;
+    f >>state 2array run-queue push-front ;
 
 : sleep-time ( -- nanos/f )
     {
@@ -98,107 +128,89 @@ PRIVATE>
         [ sleep-queue heap-peek nip nano-count [-] ]
     } cond ;
 
+: interrupt ( thread -- )
+    dup state>> [
+        dup sleep-entry>> [ sleep-queue heap-delete ] when*
+        f >>sleep-entry
+        dup resume
+    ] when drop ;
+
 DEFER: stop
 
 <PRIVATE
 
 : schedule-sleep ( thread dt -- )
-    [ check-registered dup ] dip sleep-queue heap-push*
-    >>sleep-entry drop ;
+    dupd sleep-queue heap-push* >>sleep-entry drop ;
 
-: expire-sleep? ( heap -- ? )
-    dup heap-empty?
+: expire-sleep? ( -- ? )
+    sleep-queue dup heap-empty?
     [ drop f ] [ heap-peek nip nano-count <= ] if ;
 
 : expire-sleep ( thread -- )
     f >>sleep-entry resume ;
 
 : expire-sleep-loop ( -- )
-    sleep-queue
-    [ dup expire-sleep? ]
-    [ dup heap-pop drop expire-sleep ]
-    while
-    drop ;
+    [ expire-sleep? ]
+    [ sleep-queue heap-pop drop expire-sleep ]
+    while ;
 
-: start ( namestack thread -- * )
+CONSTANT: [start]
     [
-        set-self
         set-namestack
-        V{ } set-catchstack
-        { } set-retainstack
-        { } set-datastack
-        self quot>> [ call stop ] call-clear
-    ] (( namestack thread -- * )) call-effect-unsafe ;
-
-DEFER: next
-
-: no-runnable-threads ( -- * )
-    ! We should never be in a state where the only threads
-    ! are sleeping; the I/O wait thread is always runnable.
-    ! However, if it dies, we handle this case
-    ! semi-gracefully.
-    !
-    ! And if sleep-time outputs f, there are no sleeping
-    ! threads either... so WTF.
-    sleep-time {
-        { [ dup not ] [ drop die ] }
-        { [ dup 0 = ] [ drop ] }
-        [ (sleep) ]
-    } cond next ;
-
-: (next) ( arg thread -- * )
-    f >>state
-    dup set-self
-    dup runnable>> [
-        continuation>> box> continue-with
-    ] [
-        t >>runnable start
-    ] if ;
-
-: next ( -- * )
+        init-catchstack
+        self quot>> call
+        stop
+    ]
+
+: no-runnable-threads ( -- ) die ;
+
+GENERIC: (next) ( obj thread -- obj' )
+
+M: thread (next)
+    dup runnable>>
+    [ context>> box> set-context ]
+    [ t >>runnable drop [start] start-context ] if ;
+
+: (stop) ( obj thread -- * )
+    dup runnable>>
+    [ context>> box> set-context-and-delete ]
+    [ t >>runnable drop [start] start-context-and-delete ] if ;
+
+: next ( -- obj thread )
     expire-sleep-loop
-    run-queue dup deque-empty? [
-        drop no-runnable-threads
-    ] [
-        pop-back dup array? [ first2 ] [ f swap ] if (next)
-    ] if ;
+    run-queue pop-back
+    dup array? [ first2 ] [ [ f ] dip ] if
+    f >>state
+    dup set-self ;
 
 PRIVATE>
 
-: stop ( -- )
-    self [ exit-handler>> call( -- ) ] [ unregister-thread ] bi next ;
+: stop ( -- * )
+    self [ exit-handler>> call( -- ) ] [ unregister-thread ] bi
+    next (stop) ;
 
-: suspend ( quot state -- obj )
-    [
-        [ [ self swap call ] dip self (>>state) ] dip
-        self continuation>> >box
-        next
-    ] callcc1 2nip ; inline
+: suspend ( state -- obj )
+    [ self ] dip >>state
+    [ context ] dip context>> >box
+    next (next) ;
 
-: yield ( -- ) [ resume ] f suspend drop ;
+: yield ( -- ) self resume f suspend drop ;
 
 GENERIC: sleep-until ( n/f -- )
 
 M: integer sleep-until
-    '[ _ schedule-sleep ] "sleep" suspend drop ;
+    [ self ] dip schedule-sleep "sleep" suspend drop ;
 
 M: f sleep-until
-    drop [ drop ] "interrupt" suspend drop ;
+    drop "standby" suspend drop ;
 
 GENERIC: sleep ( dt -- )
 
 M: real sleep
     >integer nano-count + sleep-until ;
 
-: interrupt ( thread -- )
-    dup state>> [
-        dup sleep-entry>> [ sleep-queue heap-delete ] when*
-        f >>sleep-entry
-        dup resume
-    ] when drop ;
-
 : (spawn) ( thread -- )
-    [ register-thread ] [ namestack swap resume-with ] bi ;
+    [ register-thread ] [ [ namestack ] dip resume-with ] bi ;
 
 : spawn ( quot name -- thread )
     <thread> [ (spawn) ] keep ;
@@ -208,24 +220,29 @@ M: real sleep
 
 : in-thread ( quot -- )
     [ datastack ] dip
-    '[ _ set-datastack _ call ]
+    '[ _ set-datastack @ ]
     "Thread" spawn drop ;
 
 GENERIC: error-in-thread ( error thread -- )
 
 <PRIVATE
 
-: init-threads ( -- )
+: init-thread-state ( -- )
     H{ } clone 64 set-special-object
     <dlist> 65 set-special-object
-    <min-heap> 66 set-special-object
-    initial-thread global
-    [ drop [ ] "Initial" <thread> ] cache
-    <box> >>continuation
+    <min-heap> 66 set-special-object ;
+
+: init-initial-thread ( -- )
+    [ ] "Initial" <thread>
     t >>runnable
-    f >>state
-    dup register-thread
-    set-self ;
+    [ initial-thread set-global ]
+    [ register-thread ]
+    [ set-self ]
+    tri ;
+
+: init-threads ( -- )
+    init-thread-state
+    init-initial-thread ;
 
 PRIVATE>
 
index 15fdb9f9b551b5b431e2d1d8da76412f754d770f..6f748cdb311c61240f6ad8e64cd0a0ce8620774b 100644 (file)
@@ -1,10 +1,11 @@
-! Copyright (C) 2009 Slava Pestov.
+! Copyright (C) 2009, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: threads kernel namespaces continuations combinators
-sequences math namespaces.private continuations.private
-concurrency.messaging quotations kernel.private words
-sequences.private assocs models models.arrow arrays accessors
-generic generic.single definitions make sbufs tools.crossref fry ;
+USING: threads threads.private kernel namespaces continuations
+combinators sequences math namespaces.private
+continuations.private concurrency.messaging quotations
+kernel.private words sequences.private assocs models
+models.arrow arrays accessors generic generic.single definitions
+make sbufs tools.crossref fry ;
 IN: tools.continuations
 
 <PRIVATE
@@ -126,6 +127,7 @@ PRIVATE>
     >n ndrop >c c>
     continue continue-with
     stop suspend (spawn)
+    set-context start-context
 } [ don't-step-into ] each
 
 \ break [ break ] "step-into" set-word-prop
index 976fc253576204943b433cd1ae470ed5d324a028..27c5bbccf108096a8f87c85eb9e3a9b5344ea976 100755 (executable)
@@ -17,7 +17,7 @@ $nl
 
 ARTICLE: "tools.deploy.usage" "Deploy tool usage"
 "Once the necessary deployment flags have been set, the application can be deployed:"
-{ $subsections deploy }
+{ $subsections deploy deploy-image-only }
 "For example, you can deploy the " { $vocab-link "hello-ui" } " demo which comes with Factor. Note that this demo already has a deployment configuration, so nothing needs to be configured:"
 { $code "\"hello-ui\" deploy" }
 { $list
@@ -61,4 +61,10 @@ ABOUT: "tools.deploy"
 
 HELP: deploy
 { $values { "vocab" "a vocabulary specifier" } }
-{ $description "Deploys " { $snippet "vocab" } ", saving the deployed image as " { $snippet { $emphasis "vocab" } ".image" } "." } ;
+{ $description "Deploys " { $snippet "vocab" } " into a packaged application. This will create a directory containing the Factor VM, a deployed image set up to run the " { $link POSTPONE: MAIN: } " entry point of " { $snippet "vocab" } " at startup, and any " { $link "deploy-resources" } " and shared libraries the application depends on. On Mac OS X, the deployment directory will be a standard " { $snippet ".app" } " bundle executable from Finder. To only generate the Factor image, use " { $link deploy-image-only } "." } ;
+
+HELP: deploy-image-only
+{ $values { "vocab" "a vocabulary specifier" } { "image" "a pathname" } }
+{ $description "Deploys " { $snippet "vocab" } ", saving the deployed image to the location specified by " { $snippet "image" } ". This only builds the Factor image for the vocabulary; to create a complete packaged application, use " { $link deploy } "." } ;
+
+{ deploy deploy-image-only } related-words
index e57cc1f04b1322dfe083d5de7745b4d31f71364b..9430802803fda3e723a1f3bdea115ed28495e3b6 100644 (file)
@@ -1,13 +1,16 @@
 ! Copyright (C) 2007, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: tools.deploy.backend system vocabs.loader kernel
-combinators ;
+combinators tools.deploy.config.editor ;
 IN: tools.deploy
 
 : deploy ( vocab -- ) deploy* ;
 
+: deploy-image-only ( vocab image -- ) 
+    [ vm ] 2dip swap dup deploy-config make-deploy-image drop ;
+
 {
     { [ os macosx? ] [ "tools.deploy.macosx" ] }
     { [ os winnt? ] [ "tools.deploy.windows" ] }
     { [ os unix? ] [ "tools.deploy.unix" ] }
-} cond require
\ No newline at end of file
+} cond require
index c02642ba1d1c5db792d5e865a23108b472e656f4..446f453709090bb0161053e55afaac037145f8d3 100644 (file)
@@ -34,9 +34,6 @@ IN: tools.deploy.macosx
     "Contents/Info.plist" append-path
     write-plist ;
 
-: copy-dll ( bundle-name -- )
-    "Frameworks/libfactor.dylib" copy-bundle-dir ;
-
 : copy-nib ( bundle-name -- )
     deploy-ui? get [
         "Resources/English.lproj/MiniFactor.nib" copy-bundle-dir
@@ -50,11 +47,10 @@ IN: tools.deploy.macosx
 : create-app-dir ( vocab bundle-name -- vm )
     {
         [
-            nip {
-                [ copy-dll ]
-                [ copy-nib ]
-                [ "Contents/Resources" append-path make-directories ]
-            } cleave
+            nip
+            [ copy-nib ]
+            [ "Contents/Resources" append-path make-directories ]
+            [ "Contents/Frameworks" append-path make-directories ] tri
         ]
         [ copy-icns ]
         [ create-app-plist ]
index 6fb6ab91ecef2e6daf648d99effb48204559af69..a2a2dbbc86d964574118179d969c478dbdcd34eb 100755 (executable)
@@ -42,12 +42,8 @@ IN: tools.deploy.shaker
     deploy-threads? get [
         "threads" startup-hooks get delete-at
     ] unless
-    native-io? [
-        "io.thread" startup-hooks get delete-at
-    ] unless
     strip-io? [
         "io.backend" startup-hooks get delete-at
-        "io.thread" startup-hooks get delete-at
     ] when
     strip-dictionary? [
         {
@@ -175,7 +171,6 @@ IN: tools.deploy.shaker
                 "predicate"
                 "predicate-definition"
                 "predicating"
-                "primitive"
                 "reader"
                 "reading"
                 "recursive"
@@ -397,16 +392,15 @@ IN: tools.deploy.shaker
     ] [ drop ] if ;
 
 : strip-c-io ( -- )
+    ! On all platforms, if deploy-io is 1, we strip out C streams.
+    ! On Unix, if deploy-io is 3, we strip out C streams as well.
+    ! On Windows, even if deploy-io is 3, C streams are still used
+    ! for the console, so don't strip it there.
     strip-io?
     deploy-io get 3 = os windows? not and
     or [
-        [
-            c-io-backend forget
-            "io.streams.c" forget-vocab
-            "io-thread-running?" "io.thread" lookup [
-                global delete-at
-            ] when*
-        ] with-compilation-unit
+        "Stripping C I/O" show
+        "vocab:tools/deploy/shaker/strip-c-io.factor" run-file
     ] when ;
 
 : compress ( pred post-process string -- )
diff --git a/basis/tools/deploy/shaker/strip-c-io.factor b/basis/tools/deploy/shaker/strip-c-io.factor
new file mode 100644 (file)
index 0000000..44c63c5
--- /dev/null
@@ -0,0 +1,10 @@
+USING: compiler.units definitions io.backend io.streams.c kernel
+math threads.private vocabs ;
+
+[
+    c-io-backend forget
+    "io.streams.c" forget-vocab
+] with-compilation-unit
+
+M: object io-multiplex
+    dup 0 = [ drop ] [ 60 60 * 1000 * 1000 * or (sleep) ] if ;
index 5945d9915c97a484cccd5af0e18ef04247ae44f5..7981859573b570c4a139b5e326c6bd3d6a65e418 100755 (executable)
@@ -11,17 +11,13 @@ IN: tools.deploy.windows
 
 CONSTANT: app-icon-resource-id "APPICON"
 
-: copy-dll ( bundle-name -- )
-    "resource:factor.dll" swap copy-file-into ;
-
 :: copy-vm ( executable bundle-name extension -- vm )
     vm "." split1-last drop extension append
     bundle-name executable ".exe" append append-path
     [ copy-file ] keep ;
 
 : create-exe-dir ( vocab bundle-name -- vm )
-    dup copy-dll
-    deploy-console? get ".exe" ".com" ? copy-vm ;
+    deploy-console? get ".com" ".exe" ? copy-vm ;
 
 : open-in-explorer ( dir -- )
     [ f "open" ] dip absolute-path normalize-separators
index ea85fb1129c3e02ecb8e29bf39abed0784e02f8f..1bb0918b82e977ce190c72cb12edb4eb00f1e86d 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2008 Slava Pestov.\r
+! Copyright (C) 2008, 2010 Slava Pestov.\r
 ! See http://factorcode.org/license.txt for BSD license.\r
 USING: threads kernel prettyprint prettyprint.config\r
 io io.styles sequences assocs namespaces sorting boxes\r
@@ -7,7 +7,9 @@ IN: tools.threads
 \r
 : thread. ( thread -- )\r
     dup id>> pprint-cell\r
-    dup name>> over [ write-object ] with-cell\r
+    dup name>> [\r
+        over write-object\r
+    ] with-cell\r
     dup state>> [\r
         [ dup self eq? "running" "yield" ? ] unless*\r
         write\r
index 6ab4e0334de98af8508bea547f95ff05378f9af1..df46303b796df3a2ad46324eb06324fdd8686861 100644 (file)
@@ -166,4 +166,4 @@ SYNTAX: TYPED::
 
 USING: vocabs vocabs.loader ;
 
-"prettyprint" vocab [ "typed.prettyprint" require ] when
+"prettyprint" "typed.prettyprint" require-when
index 8a4ae9853f28f618f0a9d838e6a4e8fa4cccadc8..c0829e5c8dada706571cf4c3e319899aedfcc526 100644 (file)
@@ -628,7 +628,7 @@ M: windows-ui-backend do-events
     WNDCLASSEX <struct> f GetModuleHandle
     class-name-ptr pick GetClassInfoEx 0 = [
         WNDCLASSEX heap-size >>cbSize
-        { CS_HREDRAW CS_VREDRAW CS_OWNDC } flags >>style
+        flags{ CS_HREDRAW CS_VREDRAW CS_OWNDC } >>style
         ui-wndproc >>lpfnWndProc
         0 >>cbClsExtra
         0 >>cbWndExtra
@@ -811,8 +811,7 @@ M: windows-ui-backend (ungrab-input) ( handle -- )
     f ClipCursor drop
     1 ShowCursor drop ;
 
-: fullscreen-flags ( -- n )
-    { WS_CAPTION WS_BORDER WS_THICKFRAME } flags ; inline
+CONSTANT: fullscreen-flags { WS_CAPTION WS_BORDER WS_THICKFRAME }
 
 : enter-fullscreen ( world -- )
     handle>> hWnd>>
@@ -838,7 +837,7 @@ M: windows-ui-backend (ungrab-input) ( handle -- )
         [
             f
             over hwnd>RECT get-RECT-dimensions
-            { SWP_NOMOVE SWP_NOSIZE SWP_NOZORDER SWP_FRAMECHANGED } flags
+            flags{ SWP_NOMOVE SWP_NOSIZE SWP_NOZORDER SWP_FRAMECHANGED }
             SetWindowPos win32-error=0/f
         ]
         [ SW_RESTORE ShowWindow win32-error=0/f ]
index d0d25a063083b4e39609e5717c205ac2a0eba059..4a68b47f15fdf14ec67bf8c2a5b6ada1a5aeafdd 100644 (file)
@@ -220,8 +220,8 @@ TUPLE: radio-control < button value ;
 M: radio-control model-changed
     2dup [ value>> ] bi@ = >>selected? relayout-1 drop ;
 
-:: <radio-controls> ( parent model assoc quot: ( value model label -- gadget ) -- parent )
-    assoc model [ parent swap quot call add-gadget ] assoc-each ; inline
+:: <radio-controls> ( model assoc parent quot: ( value model label -- gadget ) -- parent )
+    parent assoc [ model swap quot call add-gadget ] assoc-each ; inline
 
 PRIVATE>
 
index 7e47bf627ba83b7652dab0a3cecddb772e5ffc20..dca340cd3b26fb8525d4da66d451d1067e29d9e2 100644 (file)
@@ -393,6 +393,6 @@ M: f request-focus-on 2drop ;
 : focus-path ( gadget -- seq )
     [ focus>> ] follow ;
 
-USING: vocabs vocabs.loader ;
+USE: vocabs.loader
 
-"prettyprint" vocab [ "ui.gadgets.prettyprint" require ] when
+"prettyprint" "ui.gadgets.prettyprint" require-when
index 53d3bec56e4088def4cdf3d880219c6d930716a3..ffd0c4cd0ed16d774931ad8157d6fa7feb233624 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2005, 2009 Slava Pestov.
+! Copyright (C) 2005, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors arrays assocs calendar combinators locals
 source-files.errors colors.constants combinators.short-circuit
@@ -30,7 +30,7 @@ output history flag mailbox thread waiting token-model word-model popup ;
     drop ;
 
 : interactor-continuation ( interactor -- continuation )
-    thread>> continuation>> value>> ;
+    thread>> thread-continuation ;
 
 : interactor-busy? ( interactor -- ? )
     #! We're busy if there's no thread to resume.
index 3019de4e21f2dced2352d4d77208536759d70aea..9d8e50c615cbd162c8d55c4b2a3d56413e8e4e19 100644 (file)
@@ -62,10 +62,7 @@ IN: ui.tools.operations
 
 ! Thread
 : com-thread-traceback-window ( thread -- )
-    continuation>> dup occupied>>
-    [ value>> traceback-window ]
-    [ drop beep ]
-    if ;
+    thread-continuation traceback-window ;
 
 [ thread? ] \ com-thread-traceback-window H{
     { +primary+ t }
index c296cc81661f9c0c5bae2eff13612c6097f80463..947191e7dd458e65597226d25dd694a5b15f8e9c 100644 (file)
@@ -1,6 +1,7 @@
 ! Copyright (C) 2008 Slava Pestov.\r
 ! See http://factorcode.org/license.txt for BSD license.\r
-USING: alien.c-types alien.syntax math math.bitwise classes.struct ;\r
+USING: alien.c-types alien.syntax math math.bitwise classes.struct\r
+literals ;\r
 IN: unix.linux.inotify\r
 \r
 STRUCT: inotify-event\r
@@ -27,8 +28,8 @@ CONSTANT: IN_UNMOUNT HEX: 2000     ! Backing fs was unmounted
 CONSTANT: IN_Q_OVERFLOW HEX: 4000  ! Event queued overflowed\r
 CONSTANT: IN_IGNORED HEX: 8000     ! File was ignored\r
 \r
-: IN_CLOSE ( -- n ) { IN_CLOSE_WRITE IN_CLOSE_NOWRITE } flags ; foldable ! close\r
-: IN_MOVE ( -- n ) { IN_MOVED_FROM IN_MOVED_TO } flags        ; foldable ! moves\r
+CONSTANT: IN_CLOSE flags{ IN_CLOSE_WRITE IN_CLOSE_NOWRITE }\r
+CONSTANT: IN_MOVE flags{ IN_MOVED_FROM IN_MOVED_TO }\r
 \r
 CONSTANT: IN_ONLYDIR HEX: 1000000     ! only watch the path if it is a directory\r
 CONSTANT: IN_DONT_FOLLOW HEX: 2000000 ! don't follow a sym link\r
@@ -36,20 +37,20 @@ CONSTANT: IN_MASK_ADD HEX: 20000000   ! add to the mask of an already existing w
 CONSTANT: IN_ISDIR HEX: 40000000      ! event occurred against dir\r
 CONSTANT: IN_ONESHOT HEX: 80000000    ! only send event once\r
 \r
-: IN_CHANGE_EVENTS ( -- n )\r
-    {\r
+CONSTANT: IN_CHANGE_EVENTS \r
+    flags{\r
         IN_MODIFY IN_ATTRIB IN_MOVED_FROM\r
         IN_MOVED_TO IN_DELETE IN_CREATE IN_DELETE_SELF\r
         IN_MOVE_SELF\r
-    } flags ; foldable\r
+    }\r
 \r
-: IN_ALL_EVENTS ( -- n )\r
-    {\r
+CONSTANT: IN_ALL_EVENTS\r
+    flags{\r
         IN_ACCESS IN_MODIFY IN_ATTRIB IN_CLOSE_WRITE\r
         IN_CLOSE_NOWRITE IN_OPEN IN_MOVED_FROM\r
         IN_MOVED_TO IN_DELETE IN_CREATE IN_DELETE_SELF\r
         IN_MOVE_SELF\r
-    } flags ; foldable\r
+    }\r
 \r
 FUNCTION: int inotify_init ( ) ;\r
 FUNCTION: int inotify_add_watch ( int fd, c-string name, uint mask  ) ;\r
index 75b231da967d4b62e01f13fb524e639ed5db9c65..b5ae2c222327d78541ed9b9a9ab312403d017c05 100644 (file)
@@ -3,7 +3,7 @@
 USING: alien.c-types io.encodings.utf8 io.encodings.string
 kernel sequences unix.stat accessors unix combinators math
 grouping system alien.strings math.bitwise alien.syntax
-unix.types classes.struct unix.ffi ;
+unix.types classes.struct unix.ffi literals ;
 IN: unix.statfs.macosx
 
 CONSTANT: MNT_RDONLY  HEX: 00000001
@@ -29,8 +29,8 @@ CONSTANT: MNT_MULTILABEL  HEX: 04000000
 CONSTANT: MNT_NOATIME HEX: 10000000
 ALIAS: MNT_UNKNOWNPERMISSIONS MNT_IGNORE_OWNERSHIP
 
-: MNT_VISFLAGMASK ( -- n )
-    {
+CONSTANT: MNT_VISFLAGMASK
+    flags{
         MNT_RDONLY MNT_SYNCHRONOUS MNT_NOEXEC
         MNT_NOSUID MNT_NODEV MNT_UNION
         MNT_ASYNC MNT_EXPORTED MNT_QUARANTINE
@@ -38,14 +38,13 @@ ALIAS: MNT_UNKNOWNPERMISSIONS MNT_IGNORE_OWNERSHIP
         MNT_ROOTFS MNT_DOVOLFS MNT_DONTBROWSE
         MNT_IGNORE_OWNERSHIP MNT_AUTOMOUNTED MNT_JOURNALED
         MNT_NOUSERXATTR MNT_DEFWRITE MNT_MULTILABEL MNT_NOATIME
-    } flags ; inline
+    }
 
 CONSTANT: MNT_UPDATE  HEX: 00010000
 CONSTANT: MNT_RELOAD  HEX: 00040000
 CONSTANT: MNT_FORCE   HEX: 00080000
 
-: MNT_CMDFLAGS ( -- n )
-    { MNT_UPDATE MNT_RELOAD MNT_FORCE } flags ; inline
+CONSTANT: MNT_CMDFLAGS flags{ MNT_UPDATE MNT_RELOAD MNT_FORCE }
 
 CONSTANT: VFS_GENERIC 0
 CONSTANT: VFS_NUMMNTOPS 1
index 4e77a41713a64a50beb95b9c0dc565ff8a6a5678..e747e4843393518605288bfe0342ffb92644f886 100644 (file)
@@ -74,8 +74,6 @@ M: unix open-file [ open ] unix-system-call ;
 
 <<
 
-"debugger" vocab [
-    "unix.debugger" require
-] when
+"debugger" "unix.debugger" require-when
 
 >>
index bf4a9bb76c9d6cd83cd1c3bf815fa333468fa737..cd470a451ab346f715ed166f750b9b8d0450d8ae 100644 (file)
@@ -183,8 +183,6 @@ PRIVATE>
 ! Literal syntax
 SYNTAX: URL" lexer get skip-blank parse-string >url suffix! ;
 
-USING: vocabs vocabs.loader ;
+USE: vocabs.loader
 
-"prettyprint" vocab [
-    "urls.prettyprint" require
-] when
+"prettyprint" "urls.prettyprint" require-when
index acdcdda5d2b27954b3b7732cd13adafe55de4826..6b5936977f433bae7745c8cc48c1a2660301242f 100644 (file)
@@ -2,17 +2,12 @@ IN: validators.tests
 USING: kernel sequences tools.test validators accessors
 namespaces assocs ;
 
-[ "" v-one-line ] must-fail
-[ "hello world" ] [ "hello world" v-one-line ] unit-test
-[ "hello\nworld" v-one-line ] must-fail
-
-[ "" v-one-word ] must-fail
-[ "hello" ] [ "hello" v-one-word ] unit-test
-[ "hello world" v-one-word ] must-fail
-
 [ t ] [ "on" v-checkbox ] unit-test
 [ f ] [ "off" v-checkbox ] unit-test
 
+[ "default test" ] [ "" "default test" v-default ] unit-test
+[ "blah" ] [ "blah" "default test" v-default ] unit-test
+
 [ "foo" v-number ] must-fail
 [ 123 ] [ "123" v-number ] unit-test
 [ 123 ] [ "123" v-integer ] unit-test
@@ -42,6 +37,14 @@ namespaces assocs ;
 [ "http:/www.factorcode.org" v-url ]
 [ "invalid URL" = ] must-fail-with
 
+[ "" v-one-line ] must-fail
+[ "hello world" ] [ "hello world" v-one-line ] unit-test
+[ "hello\nworld" v-one-line ] must-fail
+
+[ "" v-one-word ] must-fail
+[ "hello" ] [ "hello" v-one-word ] unit-test
+[ "hello world" v-one-word ] must-fail
+
 [ 4561261212345467 ] [ "4561261212345467" v-credit-card ] unit-test
 
 [ 4561261212345467 ] [ "4561-2612-1234-5467" v-credit-card ] unit-test
index cf45e7b13f899654b8849e8310c759845605d844..45287a60c6641ef7e45fffd4610e86dc4166cdd0 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2006, 2008 Slava Pestov
+! Copyright (C) 2006, 2010 Slava Pestov
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel continuations sequences math namespaces make sets
 math.parser math.ranges assocs regexp unicode.categories arrays
@@ -9,7 +9,7 @@ IN: validators
     >lower "on" = ;
 
 : v-default ( str def -- str/def )
-    [ nip empty? ] 2keep ? ;
+    [ drop empty? not ] 2keep ? ;
 
 : v-required ( str -- str )
     dup empty? [ "required" throw ] when ;
index cc4a291a8b089922fda2dd93bb77174c2e827e1d..b4c5734810482dbba47e48e07ffd38fcf3757bd6 100644 (file)
@@ -10,12 +10,11 @@ STRUCT: context
 { callstack-bottom void* }
 { datastack cell }
 { retainstack cell }
-{ magic-frame void* }
+{ callstack-save cell }
 { datastack-region void* }
 { retainstack-region void* }
-{ catchstack-save cell }
-{ current-callback-save cell }
-{ next context* } ;
+{ callstack-region void* }
+{ context-objects cell[10] } ;
 
 : context-field-offset ( field -- offset ) context offset-of ; inline
 
@@ -27,6 +26,7 @@ STRUCT: zone
 
 STRUCT: vm
 { ctx context* }
+{ spare-ctx context* }
 { nursery zone }
 { cards-offset cell }
 { decks-offset cell }
old mode 100644 (file)
new mode 100755 (executable)
index d5fe33b..7276997
@@ -1,28 +1,9 @@
-USING: alien.c-types alien.syntax kernel math windows.types
-windows.kernel32 math.bitwise classes.struct ;
+USING: alien.c-types alien.syntax classes.struct kernel
+literals math math.bitwise windows.kernel32 windows.types ;
 IN: windows.advapi32
 
 LIBRARY: advapi32
 
-CONSTANT: PROV_RSA_FULL       1
-CONSTANT: PROV_RSA_SIG        2
-CONSTANT: PROV_DSS            3
-CONSTANT: PROV_FORTEZZA       4
-CONSTANT: PROV_MS_EXCHANGE    5
-CONSTANT: PROV_SSL            6
-CONSTANT: PROV_RSA_SCHANNEL  12
-CONSTANT: PROV_DSS_DH        13
-CONSTANT: PROV_EC_ECDSA_SIG  14
-CONSTANT: PROV_EC_ECNRA_SIG  15
-CONSTANT: PROV_EC_ECDSA_FULL 16
-CONSTANT: PROV_EC_ECNRA_FULL 17
-CONSTANT: PROV_DH_SCHANNEL   18
-CONSTANT: PROV_SPYRUS_LYNKS  20
-CONSTANT: PROV_RNG           21
-CONSTANT: PROV_INTEL_SEC     22
-CONSTANT: PROV_REPLACE_OWF   23
-CONSTANT: PROV_RSA_AES       24
-
 CONSTANT: MS_DEF_DH_SCHANNEL_PROV "Microsoft DH Schannel Cryptographic Provider"
 
 CONSTANT: MS_DEF_DSS_DH_PROV
@@ -56,12 +37,6 @@ CONSTANT: MS_SCARD_PROV
 CONSTANT: MS_STRONG_PROV
     "Microsoft Strong Cryptographic Provider"
 
-CONSTANT: CRYPT_VERIFYCONTEXT  HEX: F0000000
-CONSTANT: CRYPT_NEWKEYSET      HEX: 8
-CONSTANT: CRYPT_DELETEKEYSET   HEX: 10
-CONSTANT: CRYPT_MACHINE_KEYSET HEX: 20
-CONSTANT: CRYPT_SILENT         HEX: 40
-
 STRUCT: ACL
     { AclRevision BYTE }
     { Sbz1 BYTE }
@@ -361,18 +336,18 @@ CONSTANT: TOKEN_IMPERSONATE            HEX: 0004
 CONSTANT: TOKEN_QUERY                  HEX: 0008
 CONSTANT: TOKEN_QUERY_SOURCE           HEX: 0010
 CONSTANT: TOKEN_ADJUST_DEFAULT         HEX: 0080
-: TOKEN_READ ( -- n ) { STANDARD_RIGHTS_READ TOKEN_QUERY } flags ;
+CONSTANT: TOKEN_READ flags{ STANDARD_RIGHTS_READ TOKEN_QUERY }
 
-: TOKEN_WRITE ( -- n )
-    {
+CONSTANT: TOKEN_WRITE
+    flags{
         STANDARD_RIGHTS_WRITE
         TOKEN_ADJUST_PRIVILEGES
         TOKEN_ADJUST_GROUPS
         TOKEN_ADJUST_DEFAULT
-    } flags ; foldable
+    }
 
-: TOKEN_ALL_ACCESS ( -- n )
-    {
+CONSTANT: TOKEN_ALL_ACCESS
+    flags{
         STANDARD_RIGHTS_REQUIRED
         TOKEN_ASSIGN_PRIMARY
         TOKEN_DUPLICATE
@@ -383,7 +358,7 @@ CONSTANT: TOKEN_ADJUST_DEFAULT         HEX: 0080
         TOKEN_ADJUST_GROUPS
         TOKEN_ADJUST_SESSIONID
         TOKEN_ADJUST_DEFAULT
-    } flags ; foldable
+    }
 
 CONSTANT: HKEY_CLASSES_ROOT        HEX: 80000000
 CONSTANT: HKEY_CURRENT_USER        HEX: 80000001
@@ -426,6 +401,305 @@ CONSTANT: REG_QWORD_LITTLE_ENDIAN         11
 CONSTANT: REG_CREATED_NEW_KEY     1
 CONSTANT: REG_OPENED_EXISTING_KEY 2
 
+
+
+CONSTANT: ALG_CLASS_ANY 0
+CONSTANT: ALG_CLASS_SIGNATURE  8192
+CONSTANT: ALG_CLASS_MSG_ENCRYPT  16384
+CONSTANT: ALG_CLASS_DATA_ENCRYPT  24576
+CONSTANT: ALG_CLASS_HASH  32768
+CONSTANT: ALG_CLASS_KEY_EXCHANGE  40960
+CONSTANT: ALG_CLASS_ALL 57344
+CONSTANT: ALG_TYPE_ANY 0
+CONSTANT: ALG_TYPE_DSS 512
+CONSTANT: ALG_TYPE_RSA 1024
+CONSTANT: ALG_TYPE_BLOCK 1536
+CONSTANT: ALG_TYPE_STREAM  2048
+CONSTANT: ALG_TYPE_DH 2560
+CONSTANT: ALG_TYPE_SECURECHANNEL 3072
+CONSTANT: ALG_SID_ANY 0
+CONSTANT: ALG_SID_RSA_ANY 0
+CONSTANT: ALG_SID_RSA_PKCS 1
+CONSTANT: ALG_SID_RSA_MSATWORK 2
+CONSTANT: ALG_SID_RSA_ENTRUST 3
+CONSTANT: ALG_SID_RSA_PGP 4
+CONSTANT: ALG_SID_DSS_ANY 0
+CONSTANT: ALG_SID_DSS_PKCS 1
+CONSTANT: ALG_SID_DSS_DMS 2
+CONSTANT: ALG_SID_DES 1
+CONSTANT: ALG_SID_3DES 3
+CONSTANT: ALG_SID_DESX 4
+CONSTANT: ALG_SID_IDEA 5
+CONSTANT: ALG_SID_CAST 6
+CONSTANT: ALG_SID_SAFERSK64 7
+CONSTANT: ALG_SID_SAFERSK128 8
+CONSTANT: ALG_SID_3DES_112 9
+CONSTANT: ALG_SID_SKIPJACK 10
+CONSTANT: ALG_SID_TEK 11
+CONSTANT: ALG_SID_CYLINK_MEK 12
+CONSTANT: ALG_SID_RC5 13
+CONSTANT: ALG_SID_RC2 2
+CONSTANT: ALG_SID_RC4 1
+CONSTANT: ALG_SID_SEAL 2
+CONSTANT: ALG_SID_MD2 1
+CONSTANT: ALG_SID_MD4 2
+CONSTANT: ALG_SID_MD5 3
+CONSTANT: ALG_SID_SHA 4
+CONSTANT: ALG_SID_MAC 5
+CONSTANT: ALG_SID_RIPEMD 6
+CONSTANT: ALG_SID_RIPEMD160 7
+CONSTANT: ALG_SID_SSL3SHAMD5 8
+CONSTANT: ALG_SID_HMAC 9
+CONSTANT: ALG_SID_TLS1PRF 10
+CONSTANT: ALG_SID_EXAMPLE 80
+
+CONSTANT: CALG_MD2 flags{ ALG_CLASS_HASH ALG_TYPE_ANY ALG_SID_MD2 }
+CONSTANT: CALG_MD4 flags{ ALG_CLASS_HASH ALG_TYPE_ANY ALG_SID_MD4 }
+CONSTANT: CALG_MD5 flags{ ALG_CLASS_HASH ALG_TYPE_ANY ALG_SID_MD5 }
+CONSTANT: CALG_SHA flags{ ALG_CLASS_HASH ALG_TYPE_ANY ALG_SID_SHA }
+CONSTANT: CALG_MAC flags{ ALG_CLASS_HASH ALG_TYPE_ANY ALG_SID_MAC }
+CONSTANT: CALG_3DES flags{ ALG_CLASS_DATA_ENCRYPT ALG_TYPE_BLOCK 3 }
+CONSTANT: CALG_CYLINK_MEK flags{ ALG_CLASS_DATA_ENCRYPT ALG_TYPE_BLOCK 12 }
+CONSTANT: CALG_SKIPJACK flags{ ALG_CLASS_DATA_ENCRYPT ALG_TYPE_BLOCK 10 }
+CONSTANT: CALG_KEA_KEYX flags{ ALG_CLASS_KEY_EXCHANGE ALG_TYPE_STREAM ALG_TYPE_DSS 4 }
+CONSTANT: CALG_RSA_SIGN flags{ ALG_CLASS_SIGNATURE ALG_TYPE_RSA ALG_SID_RSA_ANY }
+CONSTANT: CALG_DSS_SIGN flags{ ALG_CLASS_SIGNATURE ALG_TYPE_DSS ALG_SID_DSS_ANY }
+CONSTANT: CALG_RSA_KEYX flags{ ALG_CLASS_KEY_EXCHANGE ALG_TYPE_RSA ALG_SID_RSA_ANY }
+CONSTANT: CALG_DES flags{ ALG_CLASS_DATA_ENCRYPT ALG_TYPE_BLOCK ALG_SID_DES }
+CONSTANT: CALG_RC2 flags{ ALG_CLASS_DATA_ENCRYPT ALG_TYPE_BLOCK ALG_SID_RC2 }
+CONSTANT: CALG_RC4 flags{ ALG_CLASS_DATA_ENCRYPT ALG_TYPE_STREAM ALG_SID_RC4 }
+CONSTANT: CALG_SEAL flags{ ALG_CLASS_DATA_ENCRYPT ALG_TYPE_STREAM ALG_SID_SEAL }
+CONSTANT: CALG_DH_EPHEM flags{ ALG_CLASS_KEY_EXCHANGE ALG_TYPE_STREAM ALG_TYPE_DSS ALG_SID_DSS_DMS }
+CONSTANT: CALG_DESX flags{ ALG_CLASS_DATA_ENCRYPT ALG_TYPE_BLOCK ALG_SID_DESX }
+! CONSTANT: CALG_TLS1PRF flags{ ALG_CLASS_DHASH ALG_TYPE_ANY ALG_SID_TLS1PRF }
+
+CONSTANT: CRYPT_VERIFYCONTEXT HEX: F0000000
+CONSTANT: CRYPT_NEWKEYSET 8
+CONSTANT: CRYPT_DELETEKEYSET 16
+CONSTANT: CRYPT_MACHINE_KEYSET 32
+CONSTANT: CRYPT_SILENT 64
+CONSTANT: CRYPT_EXPORTABLE 1
+CONSTANT: CRYPT_USER_PROTECTED 2
+CONSTANT: CRYPT_CREATE_SALT 4
+CONSTANT: CRYPT_UPDATE_KEY 8
+CONSTANT: AT_KEYEXCHANGE 1
+CONSTANT: AT_SIGNATURE 2
+CONSTANT: CRYPT_USERDATA 1
+CONSTANT: KP_IV 1
+CONSTANT: KP_SALT 2
+CONSTANT: KP_PADDING 3
+CONSTANT: KP_MODE 4
+CONSTANT: KP_MODE_BITS 5
+CONSTANT: KP_PERMISSIONS 6
+CONSTANT: KP_ALGID 7
+CONSTANT: KP_BLOCKLEN 8
+CONSTANT: PKCS5_PADDING 1
+CONSTANT: CRYPT_MODE_CBC 1
+CONSTANT: CRYPT_MODE_ECB 2
+CONSTANT: CRYPT_MODE_OFB 3
+CONSTANT: CRYPT_MODE_CFB 4
+CONSTANT: CRYPT_MODE_CTS 5
+CONSTANT: CRYPT_MODE_CBCI 6
+CONSTANT: CRYPT_MODE_CFBP 7
+CONSTANT: CRYPT_MODE_OFBP 8
+CONSTANT: CRYPT_MODE_CBCOFM 9
+CONSTANT: CRYPT_MODE_CBCOFMI 10
+CONSTANT: CRYPT_ENCRYPT 1
+CONSTANT: CRYPT_DECRYPT 2
+CONSTANT: CRYPT_EXPORT 4
+CONSTANT: CRYPT_READ 8
+CONSTANT: CRYPT_WRITE 16
+CONSTANT: CRYPT_MAC 32
+CONSTANT: HP_ALGID 1
+CONSTANT: HP_HASHVAL 2
+CONSTANT: HP_HASHSIZE 4
+CONSTANT: PP_ENUMALGS 1
+CONSTANT: PP_ENUMCONTAINERS 2
+CONSTANT: PP_IMPTYPE 3
+CONSTANT: PP_NAME 4
+CONSTANT: PP_VERSION 5
+CONSTANT: PP_CONTAINER 6
+CONSTANT: PP_ENUMMANDROOTS 25
+CONSTANT: PP_ENUMELECTROOTS 26
+CONSTANT: PP_KEYSET_TYPE 27
+CONSTANT: PP_ADMIN_PIN 31
+CONSTANT: PP_KEYEXCHANGE_PIN 32
+CONSTANT: PP_SIGNATURE_PIN 33
+CONSTANT: PP_SIG_KEYSIZE_INC 34
+CONSTANT: PP_KEYX_KEYSIZE_INC 35
+CONSTANT: PP_UNIQUE_CONTAINER 36
+CONSTANT: PP_SGC_INFO 37
+CONSTANT: PP_USE_HARDWARE_RNG 38
+CONSTANT: PP_KEYSPEC 39
+CONSTANT: PP_ENUMEX_SIGNING_PROT 40
+CONSTANT: CRYPT_FIRST 1
+CONSTANT: CRYPT_NEXT 2
+CONSTANT: CRYPT_IMPL_HARDWARE 1
+CONSTANT: CRYPT_IMPL_SOFTWARE 2
+CONSTANT: CRYPT_IMPL_MIXED 3
+CONSTANT: CRYPT_IMPL_UNKNOWN 4
+CONSTANT: PROV_RSA_FULL 1
+CONSTANT: PROV_RSA_SIG 2
+CONSTANT: PROV_DSS 3
+CONSTANT: PROV_FORTEZZA 4
+CONSTANT: PROV_MS_MAIL 5
+CONSTANT: PROV_SSL 6
+CONSTANT: PROV_STT_MER 7
+CONSTANT: PROV_STT_ACQ 8
+CONSTANT: PROV_STT_BRND 9
+CONSTANT: PROV_STT_ROOT 10
+CONSTANT: PROV_STT_ISS 11
+CONSTANT: PROV_RSA_SCHANNEL 12
+CONSTANT: PROV_DSS_DH 13
+CONSTANT: PROV_EC_ECDSA_SIG 14
+CONSTANT: PROV_EC_ECNRA_SIG 15
+CONSTANT: PROV_EC_ECDSA_FULL 16
+CONSTANT: PROV_EC_ECNRA_FULL 17
+CONSTANT: PROV_DH_SCHANNEL 18
+CONSTANT: PROV_SPYRUS_LYNKS 20
+CONSTANT: PROV_RNG 21
+CONSTANT: PROV_INTEL_SEC 22
+CONSTANT: PROV_REPLACE_OWF 23
+CONSTANT: PROV_RSA_AES 24
+CONSTANT: MAXUIDLEN 64
+CONSTANT: CUR_BLOB_VERSION 2
+CONSTANT: X509_ASN_ENCODING 1
+CONSTANT: PKCS_7_ASN_ENCODING  65536
+CONSTANT: CERT_V1 0
+CONSTANT: CERT_V2 1
+CONSTANT: CERT_V3 2
+CONSTANT: CERT_E_CHAINING -2146762486
+CONSTANT: CERT_E_CN_NO_MATCH -2146762481
+CONSTANT: CERT_E_EXPIRED -2146762495
+CONSTANT: CERT_E_PURPOSE -2146762490
+CONSTANT: CERT_E_REVOCATION_FAILURE -2146762482
+CONSTANT: CERT_E_REVOKED -2146762484
+CONSTANT: CERT_E_ROLE -2146762493
+CONSTANT: CERT_E_UNTRUSTEDROOT -2146762487
+CONSTANT: CERT_E_UNTRUSTEDTESTROOT -2146762483
+CONSTANT: CERT_E_VALIDITYPERIODNESTING -2146762494
+CONSTANT: CERT_E_WRONG_USAGE -2146762480
+CONSTANT: CERT_E_PATHLENCONST -2146762492
+CONSTANT: CERT_E_CRITICAL -2146762491
+CONSTANT: CERT_E_ISSUERCHAINING -2146762489
+CONSTANT: CERT_E_MALFORMED -2146762488
+CONSTANT: CRYPT_E_REVOCATION_OFFLINE -2146885613
+CONSTANT: CRYPT_E_REVOKED -2146885616
+CONSTANT: TRUST_E_BASIC_CONSTRAINTS -2146869223
+CONSTANT: TRUST_E_CERT_SIGNATURE -2146869244
+CONSTANT: TRUST_E_FAIL -2146762485
+CONSTANT: CERT_TRUST_NO_ERROR 0
+CONSTANT: CERT_TRUST_IS_NOT_TIME_VALID 1
+CONSTANT: CERT_TRUST_IS_NOT_TIME_NESTED 2
+CONSTANT: CERT_TRUST_IS_REVOKED 4
+CONSTANT: CERT_TRUST_IS_NOT_SIGNATURE_VALID 8
+CONSTANT: CERT_TRUST_IS_NOT_VALID_FOR_USAGE 16
+CONSTANT: CERT_TRUST_IS_UNTRUSTED_ROOT 32
+CONSTANT: CERT_TRUST_REVOCATION_STATUS_UNKNOWN 64
+CONSTANT: CERT_TRUST_IS_CYCLIC 128
+CONSTANT: CERT_TRUST_IS_PARTIAL_CHAIN 65536
+CONSTANT: CERT_TRUST_CTL_IS_NOT_TIME_VALID 131072
+CONSTANT: CERT_TRUST_CTL_IS_NOT_SIGNATURE_VALID 262144
+CONSTANT: CERT_TRUST_CTL_IS_NOT_VALID_FOR_USAGE 524288
+CONSTANT: CERT_TRUST_HAS_EXACT_MATCH_ISSUER 1
+CONSTANT: CERT_TRUST_HAS_KEY_MATCH_ISSUER 2
+CONSTANT: CERT_TRUST_HAS_NAME_MATCH_ISSUER 4
+CONSTANT: CERT_TRUST_IS_SELF_SIGNED 8
+CONSTANT: CERT_TRUST_IS_COMPLEX_CHAIN 65536
+CONSTANT: CERT_CHAIN_POLICY_BASE 1
+CONSTANT: CERT_CHAIN_POLICY_AUTHENTICODE 2
+CONSTANT: CERT_CHAIN_POLICY_AUTHENTICODE_TS 3
+CONSTANT: CERT_CHAIN_POLICY_SSL 4
+CONSTANT: CERT_CHAIN_POLICY_BASIC_CONSTRAINTS 5
+CONSTANT: CERT_CHAIN_POLICY_NT_AUTH 6
+CONSTANT: USAGE_MATCH_TYPE_AND 0
+CONSTANT: USAGE_MATCH_TYPE_OR 1
+CONSTANT: CERT_SIMPLE_NAME_STR 1
+CONSTANT: CERT_OID_NAME_STR 2
+CONSTANT: CERT_X500_NAME_STR 3
+CONSTANT: CERT_NAME_STR_SEMICOLON_FLAG 1073741824
+CONSTANT: CERT_NAME_STR_CRLF_FLAG 134217728
+CONSTANT: CERT_NAME_STR_NO_PLUS_FLAG 536870912
+CONSTANT: CERT_NAME_STR_NO_QUOTING_FLAG 268435456
+CONSTANT: CERT_NAME_STR_REVERSE_FLAG 33554432
+CONSTANT: CERT_NAME_STR_ENABLE_T61_UNICODE_FLAG 131072
+CONSTANT: CERT_FIND_ANY 0
+CONSTANT: CERT_FIND_CERT_ID 1048576
+CONSTANT: CERT_FIND_CTL_USAGE 655360
+CONSTANT: CERT_FIND_ENHKEY_USAGE 655360
+CONSTANT: CERT_FIND_EXISTING 851968
+CONSTANT: CERT_FIND_HASH 65536
+CONSTANT: CERT_FIND_ISSUER_ATTR 196612
+CONSTANT: CERT_FIND_ISSUER_NAME 131076
+CONSTANT: CERT_FIND_ISSUER_OF 786432
+CONSTANT: CERT_FIND_KEY_IDENTIFIER 983040
+CONSTANT: CERT_FIND_KEY_SPEC 589824
+CONSTANT: CERT_FIND_MD5_HASH 262144
+CONSTANT: CERT_FIND_PROPERTY 327680
+CONSTANT: CERT_FIND_PUBLIC_KEY 393216
+CONSTANT: CERT_FIND_SHA1_HASH 65536
+CONSTANT: CERT_FIND_SIGNATURE_HASH 917504
+CONSTANT: CERT_FIND_SUBJECT_ATTR 196615
+CONSTANT: CERT_FIND_SUBJECT_CERT 720896
+CONSTANT: CERT_FIND_SUBJECT_NAME 131079
+CONSTANT: CERT_FIND_SUBJECT_STR_A 458759
+CONSTANT: CERT_FIND_SUBJECT_STR_W 524295
+CONSTANT: CERT_FIND_ISSUER_STR_A 458756
+CONSTANT: CERT_FIND_ISSUER_STR_W 524292
+CONSTANT: CERT_FIND_OR_ENHKEY_USAGE_FLAG 16
+CONSTANT: CERT_FIND_OPTIONAL_ENHKEY_USAGE_FLAG  1
+CONSTANT: CERT_FIND_NO_ENHKEY_USAGE_FLAG  8
+CONSTANT: CERT_FIND_VALID_ENHKEY_USAGE_FLAG  32
+CONSTANT: CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG  2
+CONSTANT: CERT_CASE_INSENSITIVE_IS_RDN_ATTRS_FLAG  2
+CONSTANT: CERT_UNICODE_IS_RDN_ATTRS_FLAG 1
+CONSTANT: CERT_CHAIN_FIND_BY_ISSUER 1
+CONSTANT: CERT_CHAIN_FIND_BY_ISSUER_COMPARE_KEY_FLAG 1
+CONSTANT: CERT_CHAIN_FIND_BY_ISSUER_COMPLEX_CHAIN_FLAG 2
+CONSTANT: CERT_CHAIN_FIND_BY_ISSUER_CACHE_ONLY_FLAG 32768
+CONSTANT: CERT_CHAIN_FIND_BY_ISSUER_CACHE_ONLY_URL_FLAG 4
+CONSTANT: CERT_CHAIN_FIND_BY_ISSUER_LOCAL_MACHINE_FLAG 8
+CONSTANT: CERT_CHAIN_FIND_BY_ISSUER_NO_KEY_FLAG 16384
+CONSTANT: CERT_STORE_PROV_SYSTEM 10
+CONSTANT: CERT_SYSTEM_STORE_LOCAL_MACHINE 131072
+CONSTANT: szOID_PKIX_KP_SERVER_AUTH "4235600"
+CONSTANT: szOID_SERVER_GATED_CRYPTO "4235658"
+CONSTANT: szOID_SGC_NETSCAPE "2.16.840.1.113730.4.1"
+CONSTANT: szOID_PKIX_KP_CLIENT_AUTH "1.3.6.1.5.5.7.3.2"
+
+CONSTANT: CRYPT_NOHASHOID HEX: 00000001
+CONSTANT: CRYPT_NO_SALT HEX: 10
+CONSTANT: CRYPT_PREGEN HEX: 40
+CONSTANT: CRYPT_RECIPIENT HEX: 10
+CONSTANT: CRYPT_INITIATOR HEX: 40
+CONSTANT: CRYPT_ONLINE HEX: 80
+CONSTANT: CRYPT_SF HEX: 100
+CONSTANT: CRYPT_CREATE_IV HEX: 200
+CONSTANT: CRYPT_KEK HEX: 400
+CONSTANT: CRYPT_DATA_KEY HEX: 800
+CONSTANT: CRYPT_VOLATILE HEX: 1000
+CONSTANT: CRYPT_SGCKEY HEX: 2000
+
+CONSTANT: KEYSTATEBLOB HEX: C
+CONSTANT: OPAQUEKEYBLOB HEX: 9
+CONSTANT: PLAINTEXTKEYBLOB HEX: 8
+CONSTANT: PRIVATEKEYBLOB HEX: 7
+CONSTANT: PUBLICKEYBLOB HEX: 6
+CONSTANT: PUBLICKEYBLOBEX HEX: A
+CONSTANT: SIMPLEBLOB HEX: 1
+CONSTANT: SYMMETRICWRAPKEYBLOB HEX: B
+
+TYPEDEF: uint ALG_ID
+
+STRUCT: PUBLICKEYSTRUC
+    { bType BYTE }
+    { bVersion BYTE }
+    { reserved WORD }
+    { aiKeyAlg ALG_ID } ;
+
+TYPEDEF: PUBLICKEYSTRUC BLOBHEADER
+TYPEDEF: LONG HCRYPTHASH
+TYPEDEF: LONG HCRYPTKEY
 TYPEDEF: DWORD REGSAM
 
 ! : I_ScGetCurrentGroupStateW ;
@@ -590,7 +864,7 @@ FUNCTION: BOOL CryptAcquireContextW ( HCRYPTPROV* phProv,
 ALIAS: CryptAcquireContext CryptAcquireContextW
 
 ! : CryptContextAddRef ;
-! : CryptCreateHash ;
+FUNCTION: BOOL CryptCreateHash ( HCRYPTPROV hProv, ALG_ID Algid, HCRYPTKEY hKey, DWORD dwFlags, HCRYPTHASH *pHash ) ;
 ! : CryptDecrypt ;
 ! : CryptDeriveKey ;
 ! : CryptDestroyHash ;
@@ -613,7 +887,7 @@ FUNCTION: BOOL CryptGenRandom ( HCRYPTPROV hProv, DWORD dwLen, BYTE* pbBuffer )
 ! : CryptGetUserKey ;
 ! : CryptHashData ;
 ! : CryptHashSessionKey ;
-! : CryptImportKey ;
+FUNCTION: BOOL CryptImportKey ( HCRYPTPROV hProv, BYTE *pbData, DWORD dwDataLen, HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey ) ;
 FUNCTION: BOOL CryptReleaseContext ( HCRYPTPROV hProv, DWORD dwFlags ) ;
 ! : CryptSetHashParam ;
 ! : CryptSetKeyParam ;
index 49c9272d9bb7d742c1f8be0006e815b6c07769ca..78a3c0e6d2c5280c2a7f577c48bb3c29c5c0328e 100644 (file)
@@ -94,8 +94,6 @@ SYNTAX: COM-INTERFACE:
 
 SYNTAX: GUID: scan string>guid suffix! ;
 
-USING: vocabs vocabs.loader ;
+USE: vocabs.loader
 
-"prettyprint" vocab [
-    "windows.com.prettyprint" require
-] when
+"prettyprint" "windows.com.prettyprint" require-when
index dc0284955309d6279cb592a2db8ff06b6cea61be..618d3c79e541d68e7c9b721575dad604ed995e6e 100644 (file)
@@ -1,5 +1,5 @@
 USING: alien.syntax windows.types classes.struct math alien.c-types
-math.bitwise kernel locals windows.kernel32 ;
+math.bitwise kernel locals windows.kernel32 literals ;
 IN: windows.directx.d3d9types
 
 TYPEDEF: DWORD D3DCOLOR
@@ -54,19 +54,21 @@ CONSTANT: D3DCS_PLANE3      HEX: 00000200
 CONSTANT: D3DCS_PLANE4      HEX: 00000400
 CONSTANT: D3DCS_PLANE5      HEX: 00000800
 
-: D3DCS_ALL ( -- n )
-    { D3DCS_LEFT
-      D3DCS_RIGHT
-      D3DCS_TOP
-      D3DCS_BOTTOM
-      D3DCS_FRONT
-      D3DCS_BACK
-      D3DCS_PLANE0
-      D3DCS_PLANE1
-      D3DCS_PLANE2
-      D3DCS_PLANE3
-      D3DCS_PLANE4
-      D3DCS_PLANE5 } flags ; inline
+CONSTANT: D3DCS_ALL
+    flags{
+        D3DCS_LEFT
+        D3DCS_RIGHT
+        D3DCS_TOP
+        D3DCS_BOTTOM
+        D3DCS_FRONT
+        D3DCS_BACK
+        D3DCS_PLANE0
+        D3DCS_PLANE1
+        D3DCS_PLANE2
+        D3DCS_PLANE3
+        D3DCS_PLANE4
+        D3DCS_PLANE5
+    }
 
 STRUCT: D3DCLIPSTATUS9
     { ClipUnion        DWORD }
@@ -777,8 +779,7 @@ CONSTANT: D3DVS_SWIZZLE_MASK      HEX: 00FF0000
 : D3DVS_W_Z ( -- n ) 2 D3DVS_SWIZZLE_SHIFT 6 + shift ; inline
 : D3DVS_W_W ( -- n ) 3 D3DVS_SWIZZLE_SHIFT 6 + shift ; inline
 
-: D3DVS_NOSWIZZLE ( -- n )
-    { D3DVS_X_X D3DVS_Y_Y D3DVS_Z_Z D3DVS_W_W } flags ; inline
+CONSTANT: D3DVS_NOSWIZZLE flags{ D3DVS_X_X D3DVS_Y_Y D3DVS_Z_Z D3DVS_W_W }
 
 CONSTANT: D3DSP_SWIZZLE_SHIFT     16
 CONSTANT: D3DSP_SWIZZLE_MASK      HEX: 00FF0000
old mode 100644 (file)
new mode 100755 (executable)
index c5dedb0..a3dbaf4
@@ -705,10 +705,10 @@ CONSTANT: FORMAT_MESSAGE_MAX_WIDTH_MASK   HEX: 000000FF
 
 ERROR: error-message-failed id ;
 :: n>win32-error-string ( id -- string )
-    {
+    flags{
         FORMAT_MESSAGE_FROM_SYSTEM
         FORMAT_MESSAGE_ARGUMENT_ARRAY
-    } flags
+    }
     f
     id
     LANG_NEUTRAL SUBLANG_DEFAULT make-lang-id
@@ -719,8 +719,10 @@ ERROR: error-message-failed id ;
 : win32-error-string ( -- str )
     GetLastError n>win32-error-string ;
 
+ERROR: windows-error n string ;
+
 : (win32-error) ( n -- )
-    [ win32-error-string throw ] unless-zero ;
+    [ dup win32-error-string windows-error ] unless-zero ;
 
 : win32-error ( -- )
     GetLastError (win32-error) ;
index 43307cb6bac99561b4cb939761724fe07fc516d5..93784ea3708aaab2ab7c9e646c4031e10d65c12e 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2005, 2006 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien alien.c-types alien.syntax alien.destructors
-kernel windows.types math.bitwise ;
+kernel windows.types math.bitwise literals ;
 IN: windows.gdi32
 
 CONSTANT: BI_RGB 0
@@ -818,7 +818,7 @@ CONSTANT: TA_RIGHT 2
 CONSTANT: TA_RTLREADING 256
 CONSTANT: TA_NOUPDATECP 0
 CONSTANT: TA_UPDATECP 1
-: TA_MASK ( -- n ) { TA_BASELINE TA_CENTER TA_UPDATECP TA_RTLREADING } flags ; foldable
+CONSTANT: TA_MASK flags{ TA_BASELINE TA_CENTER TA_UPDATECP TA_RTLREADING }
 CONSTANT: VTA_BASELINE 24
 CONSTANT: VTA_CENTER 6
 ALIAS: VTA_LEFT TA_BOTTOM
index 1c23c360712f5ff9e965dfe5a0ee26462e63bda9..54d31bb12b97927113760aa9e41c8a0e9ab2c6f1 100644 (file)
@@ -33,18 +33,17 @@ CONSTANT: WS_MINIMIZEBOX      HEX: 00020000
 CONSTANT: WS_MAXIMIZEBOX      HEX: 00010000
 
 ! Common window styles
-: WS_OVERLAPPEDWINDOW ( -- n )
-    {
+CONSTANT: WS_OVERLAPPEDWINDOW
+    flags{
         WS_OVERLAPPED
         WS_CAPTION
         WS_SYSMENU
         WS_THICKFRAME
         WS_MINIMIZEBOX
         WS_MAXIMIZEBOX
-    } flags ; foldable
+    }
 
-: WS_POPUPWINDOW ( -- n )
-    { WS_POPUP WS_BORDER WS_SYSMENU } flags ; foldable
+CONSTANT: WS_POPUPWINDOW flags{ WS_POPUP WS_BORDER WS_SYSMENU }
 
 ALIAS: WS_CHILDWINDOW      WS_CHILD
 
@@ -76,11 +75,11 @@ CONSTANT: WS_EX_CONTROLPARENT     HEX: 00010000
 CONSTANT: WS_EX_STATICEDGE        HEX: 00020000
 CONSTANT: WS_EX_APPWINDOW         HEX: 00040000
 
-: WS_EX_OVERLAPPEDWINDOW ( -- n )
-    WS_EX_WINDOWEDGE WS_EX_CLIENTEDGE bitor ; foldable
+CONSTANT: WS_EX_OVERLAPPEDWINDOW
+    flags{ WS_EX_WINDOWEDGE WS_EX_CLIENTEDGE }
 
-: WS_EX_PALETTEWINDOW ( -- n )
-    { WS_EX_WINDOWEDGE WS_EX_TOOLWINDOW WS_EX_TOPMOST } flags ; foldable
+CONSTANT: WS_EX_PALETTEWINDOW 
+    flags{ WS_EX_WINDOWEDGE WS_EX_TOOLWINDOW WS_EX_TOPMOST }
 
 CONSTANT: CS_VREDRAW          HEX: 0001
 CONSTANT: CS_HREDRAW          HEX: 0002
index b58cbcacbd0e944fb4188e6c42029b81d4175647..49a3d6e9faf861ce2fb98d31c6f905502b47a365 100644 (file)
@@ -3,7 +3,7 @@
 USING: alien alien.c-types alien.strings alien.syntax arrays
 byte-arrays kernel literals math sequences windows.types
 windows.kernel32 windows.errors math.bitwise io.encodings.utf16n
-classes.struct windows.com.syntax init ;
+classes.struct windows.com.syntax init literals ;
 FROM: alien.c-types => short ;
 IN: windows.winsock
 
@@ -73,8 +73,7 @@ CONSTANT: AI_PASSIVE     1
 CONSTANT: AI_CANONNAME   2
 CONSTANT: AI_NUMERICHOST 4
 
-: AI_MASK ( -- n )
-    { AI_PASSIVE AI_CANONNAME AI_NUMERICHOST } flags ; inline
+CONSTANT: AI_MASK flags{ AI_PASSIVE AI_CANONNAME AI_NUMERICHOST }
 
 CONSTANT: NI_NUMERICHOST 1
 CONSTANT: NI_NUMERICSERV 2
index ad0a8b11a67e06aef97f7add0082c4b8864056b4..fb267ef4bbe128f8aeb104d3c64ca8fb440e23ef 100644 (file)
@@ -2,18 +2,18 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors kernel math math.bitwise math.vectors
 namespaces sequences x11 x11.xlib x11.constants x11.glx arrays
-fry classes.struct ;
+fry classes.struct literals ;
 IN: x11.windows
 
-: create-window-mask ( -- n )
-    { CWBackPixel CWBorderPixel CWColormap CWEventMask } flags ;
+CONSTANT: create-window-mask
+    flags{ CWBackPixel CWBorderPixel CWColormap CWEventMask }
 
 : create-colormap ( visinfo -- colormap )
     [ dpy get root get ] dip visual>> AllocNone
     XCreateColormap ;
 
-: event-mask ( -- n )
-    {
+CONSTANT: event-mask
+    flags{
         ExposureMask
         StructureNotifyMask
         KeyPressMask
@@ -25,7 +25,7 @@ IN: x11.windows
         EnterWindowMask
         LeaveWindowMask
         PropertyChangeMask
-    } flags ;
+    }
 
 : window-attributes ( visinfo -- attributes )
     XSetWindowAttributes <struct>
index 09328c6f6ea895a6b13a087b6fd6b0799961da1b..e91c6a690973a63cf0d98833faab0cc6c3271f1b 100644 (file)
@@ -33,4 +33,4 @@ SYMBOL: root
 : with-x ( display-string quot -- )
     [ init-x ] dip [ close-x ] [ ] cleanup ; inline
 
-"io.backend.unix" vocab [ "x11.io.unix" require ] when
\ No newline at end of file
+"io.backend.unix" "x11.io.unix" require-when
index 1c5ff2e3ef1571af3251c2d1ed8b7d3160e20adf..ac9e5591dc30544d2e9bbdf3287bc1c920ec8f1d 100644 (file)
@@ -12,7 +12,8 @@
 ! and note the section.
 USING: accessors kernel arrays alien alien.c-types alien.data
 alien.strings alien.syntax classes.struct math math.bitwise words
-sequences namespaces continuations io io.encodings.ascii x11.syntax ;
+sequences namespaces continuations io io.encodings.ascii x11.syntax
+literals ;
 FROM: alien.c-types => short ;
 IN: x11.xlib
 
@@ -1134,8 +1135,8 @@ X-FUNCTION: Status XWithdrawWindow (
 : PAspect      ( -- n ) 7 2^ ; inline
 : PBaseSize    ( -- n ) 8 2^ ; inline
 : PWinGravity  ( -- n ) 9 2^ ; inline
-: PAllHints    ( -- n )
-    { PPosition PSize PMinSize PMaxSize PResizeInc PAspect } flags ; foldable
+CONSTANT: PAllHints
+    flags{ PPosition PSize PMinSize PMaxSize PResizeInc PAspect }
 
 STRUCT: XSizeHints
     { flags long }
diff --git a/basis/xml/syntax/inverse/inverse.factor b/basis/xml/syntax/inverse/inverse.factor
new file mode 100644 (file)
index 0000000..002f60a
--- /dev/null
@@ -0,0 +1,75 @@
+! Copyright (C) 2005, 2009 Daniel Ehrenberg
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors arrays assocs combinators
+combinators.short-circuit fry generalizations inverse kernel
+namespaces sequences sorting strings unicode.categories
+xml.data xml.syntax xml.syntax.private ;
+IN: xml.syntax.inverse
+
+: remove-blanks ( seq -- newseq )
+    [ { [ string? not ] [ [ blank? ] all? not ] } 1|| ] filter ;
+
+GENERIC: >xml ( xml -- tag )
+M: xml >xml body>> ;
+M: tag >xml ;
+M: xml-chunk >xml
+    remove-blanks
+    [ length 1 =/fail ]
+    [ first dup tag? [ fail ] unless ] bi ;
+M: object >xml fail ;
+
+: 1chunk ( object -- xml-chunk )
+    1array <xml-chunk> ;
+
+GENERIC: >xml-chunk ( xml -- chunk )
+M: xml >xml-chunk body>> 1chunk ;
+M: xml-chunk >xml-chunk ;
+M: object >xml-chunk 1chunk ;
+
+GENERIC: [undo-xml] ( xml -- quot )
+
+M: xml [undo-xml]
+    body>> [undo-xml] '[ >xml @ ] ;
+
+M: xml-chunk [undo-xml]
+    seq>> [undo-xml] '[ >xml-chunk @ ] ;
+
+: undo-attrs ( attrs -- quot: ( attrs -- ) )
+    [
+        [ main>> ] dip dup interpolated?
+        [ var>> '[ _ attr _ set ] ]
+        [ '[ _ attr _ =/fail ] ] if
+    ] { } assoc>map '[ _ cleave ] ;
+
+M: tag [undo-xml] ( tag -- quot: ( tag -- ) )
+    {
+        [ name>> main>> '[ name>> main>> _ =/fail ] ]
+        [ attrs>> undo-attrs ] 
+        [ children>> [undo-xml] '[ children>> @ ] ]
+    } cleave '[ _ _ _ tri ] ;
+
+: firstn-strong ( seq n -- ... )
+    [ swap length =/fail ]
+    [ firstn ] 2bi ; inline
+
+M: sequence [undo-xml] ( sequence -- quot: ( seq -- ) )
+    remove-blanks [ length ] [ [ [undo-xml] ] { } map-as ] bi
+    '[ remove-blanks _ firstn-strong _ spread ] ;
+
+M: string [undo-xml] ( string -- quot: ( string -- ) )
+    '[ _ =/fail ] ;
+
+M: xml-data [undo-xml] ( datum -- quot: ( datum -- ) )
+    '[ _ =/fail ] ;
+
+M: interpolated [undo-xml]
+    var>> '[ _ set ] ;
+
+: >enum ( assoc -- enum )
+    ! Assumes keys are 0..n
+    >alist sort-keys values <enum> ;
+
+: undo-xml ( xml -- quot )
+    [undo-xml] '[ H{ } clone [ _ bind ] keep >enum ] ;
+
+\ interpolate-xml 1 [ undo-xml ] define-pop-inverse
index c56dd23db75b1eb26864dafeec1a777f6efb6cc9..a58526faa36c7cfbff04b2abc68d6e204cf7ad80 100644 (file)
@@ -4,7 +4,7 @@ USING: words assocs kernel accessors parser vocabs.parser effects.parser
 sequences summary lexer splitting combinators locals
 memoize sequences.deep xml.data xml.state xml namespaces present
 arrays generalizations strings make math macros multiline
-inverse combinators.short-circuit sorting fry unicode.categories
+combinators.short-circuit sorting fry unicode.categories
 effects ;
 IN: xml.syntax
 
@@ -175,74 +175,6 @@ SYNTAX: <XML
 SYNTAX: [XML
     "XML]" [ string>chunk ] parse-def ;
 
-<PRIVATE
-
-: remove-blanks ( seq -- newseq )
-    [ { [ string? not ] [ [ blank? ] all? not ] } 1|| ] filter ;
-
-GENERIC: >xml ( xml -- tag )
-M: xml >xml body>> ;
-M: tag >xml ;
-M: xml-chunk >xml
-    remove-blanks
-    [ length 1 =/fail ]
-    [ first dup tag? [ fail ] unless ] bi ;
-M: object >xml fail ;
-
-: 1chunk ( object -- xml-chunk )
-    1array <xml-chunk> ;
-
-GENERIC: >xml-chunk ( xml -- chunk )
-M: xml >xml-chunk body>> 1chunk ;
-M: xml-chunk >xml-chunk ;
-M: object >xml-chunk 1chunk ;
-
-GENERIC: [undo-xml] ( xml -- quot )
+USE: vocabs.loader
 
-M: xml [undo-xml]
-    body>> [undo-xml] '[ >xml @ ] ;
-
-M: xml-chunk [undo-xml]
-    seq>> [undo-xml] '[ >xml-chunk @ ] ;
-
-: undo-attrs ( attrs -- quot: ( attrs -- ) )
-    [
-        [ main>> ] dip dup interpolated?
-        [ var>> '[ _ attr _ set ] ]
-        [ '[ _ attr _ =/fail ] ] if
-    ] { } assoc>map '[ _ cleave ] ;
-
-M: tag [undo-xml] ( tag -- quot: ( tag -- ) )
-    {
-        [ name>> main>> '[ name>> main>> _ =/fail ] ]
-        [ attrs>> undo-attrs ] 
-        [ children>> [undo-xml] '[ children>> @ ] ]
-    } cleave '[ _ _ _ tri ] ;
-
-: firstn-strong ( seq n -- ... )
-    [ swap length =/fail ]
-    [ firstn ] 2bi ; inline
-
-M: sequence [undo-xml] ( sequence -- quot: ( seq -- ) )
-    remove-blanks [ length ] [ [ [undo-xml] ] { } map-as ] bi
-    '[ remove-blanks _ firstn-strong _ spread ] ;
-
-M: string [undo-xml] ( string -- quot: ( string -- ) )
-    '[ _ =/fail ] ;
-
-M: xml-data [undo-xml] ( datum -- quot: ( datum -- ) )
-    '[ _ =/fail ] ;
-
-M: interpolated [undo-xml]
-    var>> '[ _ set ] ;
-
-: >enum ( assoc -- enum )
-    ! Assumes keys are 0..n
-    >alist sort-keys values <enum> ;
-
-: undo-xml ( xml -- quot )
-    [undo-xml] '[ H{ } clone [ _ bind ] keep >enum ] ;
-
-\ interpolate-xml 1 [ undo-xml ] define-pop-inverse
-
-PRIVATE>
+"inverse" "xml.syntax.inverse" require-when
index 3a5fb4e253eb0819d4d28c2ee480ee42f164bb60..68d138c3eff5fd33d0353f1a04911f9c8f40859d 100755 (executable)
@@ -68,7 +68,7 @@ set_downloader() {
     if [[ $? -ne 0 ]] ; then
         DOWNLOADER=wget
     else
-        DOWNLOADER="curl -O"
+        DOWNLOADER="curl -f -O"
     fi
 }
 
@@ -291,9 +291,15 @@ set_build_info() {
     elif [[ $OS == winnt && $ARCH == x86 && $WORD == 64 ]] ; then
         MAKE_IMAGE_TARGET=winnt-x86.64
         MAKE_TARGET=winnt-x86-64
+    elif [[ $OS == winnt && $ARCH == x86 && $WORD == 32 ]] ; then
+        MAKE_IMAGE_TARGET=winnt-x86.32
+        MAKE_TARGET=winnt-x86-32
     elif [[ $ARCH == x86 && $WORD == 64 ]] ; then
         MAKE_IMAGE_TARGET=unix-x86.64
         MAKE_TARGET=$OS-x86-64
+    elif [[ $ARCH == x86 && $WORD == 32 ]] ; then
+        MAKE_IMAGE_TARGET=unix-x86.32
+        MAKE_TARGET=$OS-x86-32
     else
         MAKE_IMAGE_TARGET=$ARCH.$WORD
         MAKE_TARGET=$OS-$ARCH-$WORD
index 191886393a3537c25e2b4b77c2c1ad85e3508caf..a44d703fbc316b083097f2163617b7daf0652f7f 100644 (file)
@@ -94,26 +94,21 @@ SYMBOL: callbacks
 
 [ H{ } clone callbacks set-global ] "alien" add-startup-hook
 
-! Every context object in the VM is identified from the Factor
-! side by a unique identifier
-TUPLE: context-id < identity-tuple ;
-
-C: <context-id> context-id
-
-: context-id ( -- id ) 2 context-object ;
-
-: set-context-id ( id -- ) 2 set-context-object ;
-
-: wait-to-return ( yield-quot id -- )
-    dup context-id eq?
+! Every callback invocation has a unique identifier in the VM.
+! We make sure that the current callback is the right one before
+! returning from it, to avoid a bad interaction between threads
+! and callbacks. See basis/compiler/tests/alien.factor for a
+! test case.
+: wait-to-return ( yield-quot callback-id -- )
+    dup current-callback eq?
     [ 2drop ] [ over call( -- ) wait-to-return ] if ;
 
 ! Used by compiler.codegen to wrap callback bodies
 : do-callback ( callback-quot yield-quot -- )
     init-namespaces
     init-catchstack
-    <context-id>
-    [ set-context-id drop call ] [ wait-to-return drop ] 3bi ; inline
+    current-callback
+    [ 2drop call ] [ wait-to-return drop ] 3bi ; inline
 
 ! A utility for defining global variables that are recompiled in
 ! every session
index 19a179a6b1baecad0e81f3f07b8acd793d260255..87963848bf32ccdba218b0ce17dcaf27a57cc913 100644 (file)
@@ -18,7 +18,8 @@ H{ } clone sub-primitives set
 "vocab:bootstrap/syntax.factor" parse-file
 
 architecture get {
-    { "x86.32" "x86/32" }
+    { "winnt-x86.32" "x86/32/winnt" }
+    { "unix-x86.32" "x86/32/unix" }
     { "winnt-x86.64" "x86/64/winnt" }
     { "unix-x86.64" "x86/64/unix" }
     { "linux-ppc" "ppc/linux" }
@@ -63,6 +64,7 @@ call( -- )
     "alien"
     "alien.accessors"
     "alien.libraries"
+    "alien.private"
     "arrays"
     "byte-arrays"
     "classes.private"
@@ -342,7 +344,7 @@ tuple
     { "(execute)" "kernel.private" (( word -- )) }
     { "(call)" "kernel.private" (( quot -- )) }
     { "unwind-native-frames" "kernel.private" (( -- )) }
-    { "set-callstack" "kernel.private" (( cs -- * )) }
+    { "set-callstack" "kernel.private" (( callstack -- * )) }
     { "lazy-jit-compile" "kernel.private" (( -- )) }
     { "c-to-factor" "kernel.private" (( -- )) }
     { "slot" "slots.private" (( obj m -- value )) }
@@ -368,6 +370,10 @@ tuple
     { "fixnum<=" "math.private" (( x y -- z )) }
     { "fixnum>" "math.private" (( x y -- ? )) }
     { "fixnum>=" "math.private" (( x y -- ? )) }
+    { "(set-context)" "threads.private" (( obj context -- obj' )) }
+    { "(set-context-and-delete)" "threads.private" (( obj context -- * )) }
+    { "(start-context)" "threads.private" (( obj quot -- obj' )) }
+    { "(start-context-and-delete)" "threads.private" (( obj quot -- * )) }
 } [ first3 make-sub-primitive ] each
 
 ! Primitive words
@@ -415,6 +421,7 @@ tuple
     { "(dlsym)" "alien.libraries" "primitive_dlsym" (( name dll -- alien )) }
     { "dlclose" "alien.libraries" "primitive_dlclose" (( dll -- )) }
     { "dll-valid?" "alien.libraries" "primitive_dll_validp" (( dll -- ? )) }
+    { "current-callback" "alien.private" "primitive_current_callback" (( -- n )) }
     { "<array>" "arrays" "primitive_array" (( n elt -- array )) }
     { "resize-array" "arrays" "primitive_resize_array" (( n array -- newarray )) }
     { "(byte-array)" "byte-arrays" "primitive_uninitialized_byte_array" (( n -- byte-array )) }
@@ -437,23 +444,22 @@ tuple
     { "fwrite" "io.streams.c" "primitive_fwrite" (( data length alien -- )) }
     { "(clone)" "kernel" "primitive_clone" (( obj -- newobj )) }
     { "<wrapper>" "kernel" "primitive_wrapper" (( obj -- wrapper )) }
-    { "callstack" "kernel" "primitive_callstack" (( -- cs )) }
+    { "callstack" "kernel" "primitive_callstack" (( -- callstack )) }
     { "callstack>array" "kernel" "primitive_callstack_to_array" (( callstack -- array )) }
-    { "datastack" "kernel" "primitive_datastack" (( -- ds )) }
+    { "datastack" "kernel" "primitive_datastack" (( -- array )) }
     { "die" "kernel" "primitive_die" (( -- )) }
-    { "retainstack" "kernel" "primitive_retainstack" (( -- rs )) }
+    { "retainstack" "kernel" "primitive_retainstack" (( -- array )) }
     { "(identity-hashcode)" "kernel.private" "primitive_identity_hashcode" (( obj -- code )) }
     { "become" "kernel.private" "primitive_become" (( old new -- )) }
-    { "call-clear" "kernel.private" "primitive_call_clear" (( quot -- * )) }
     { "check-datastack" "kernel.private" "primitive_check_datastack" (( array in# out# -- ? )) }
     { "compute-identity-hashcode" "kernel.private" "primitive_compute_identity_hashcode" (( obj -- )) }
     { "context-object" "kernel.private" "primitive_context_object" (( n -- obj )) }
     { "innermost-frame-executing" "kernel.private" "primitive_innermost_stack_frame_executing" (( callstack -- obj )) }
     { "innermost-frame-scan" "kernel.private" "primitive_innermost_stack_frame_scan" (( callstack -- n )) }
     { "set-context-object" "kernel.private" "primitive_set_context_object" (( obj n -- )) }
-    { "set-datastack" "kernel.private" "primitive_set_datastack" (( ds -- )) }
+    { "set-datastack" "kernel.private" "primitive_set_datastack" (( array -- )) }
     { "set-innermost-frame-quot" "kernel.private" "primitive_set_innermost_stack_frame_quot" (( n callstack -- )) }
-    { "set-retainstack" "kernel.private" "primitive_set_retainstack" (( rs -- )) }
+    { "set-retainstack" "kernel.private" "primitive_set_retainstack" (( array -- )) }
     { "set-special-object" "kernel.private" "primitive_set_special_object" (( obj n -- )) }
     { "special-object" "kernel.private" "primitive_special_object" (( n -- obj )) }
     { "strip-stack-traces" "kernel.private" "primitive_strip_stack_traces" (( -- )) }
@@ -528,16 +534,20 @@ tuple
     { "set-string-nth-fast" "strings.private" "primitive_set_string_nth_fast" (( ch n string -- )) }
     { "set-string-nth-slow" "strings.private" "primitive_set_string_nth_slow" (( ch n string -- )) }
     { "string-nth" "strings.private" "primitive_string_nth" (( n string -- ch )) }
-    { "(exit)" "system" "primitive_exit" (( n -- )) }
+    { "(exit)" "system" "primitive_exit" (( n -- )) }
     { "nano-count" "system" "primitive_nano_count" (( -- ns )) }
     { "system-micros" "system" "primitive_system_micros" (( -- us )) }
     { "(sleep)" "threads.private" "primitive_sleep" (( nanos -- )) }
+    { "callstack-for" "threads.private" "primitive_callstack_for" (( context -- array )) }
+    { "context-object-for" "threads.private" "primitive_context_object_for" (( n context -- obj )) }
+    { "datastack-for" "threads.private" "primitive_datastack_for" (( context -- array )) }
+    { "retainstack-for" "threads.private" "primitive_retainstack_for" (( context -- array )) }
     { "dispatch-stats" "tools.dispatch.private" "primitive_dispatch_stats" (( -- stats )) }
     { "reset-dispatch-stats" "tools.dispatch.private" "primitive_reset_dispatch_stats" (( -- )) }
     { "profiling" "tools.profiler.private" "primitive_profiling" (( ? -- )) }
     { "optimized?" "words" "primitive_optimized_p" (( word -- ? )) }
     { "word-code" "words" "primitive_word_code" (( word -- start end )) }
-    { "(word)" "words.private" "primitive_word" (( name vocab -- word )) }
+    { "(word)" "words.private" "primitive_word" (( name vocab hashcode -- word )) }
 } [ first4 make-primitive ] each
 
 ! Bump build number
index 371068026943a05f1125930c53841a2d169550bc..8775e599a6cdc19f207a911beeac9e04353c27be 100644 (file)
@@ -235,7 +235,7 @@ HELP: save-error
 $low-level-note ;
 
 HELP: with-datastack
-{ $values { "stack" sequence } { "quot" quotation } { "newstack" sequence } }
+{ $values { "stack" sequence } { "quot" quotation } { "new-stack" sequence } }
 { $description "Executes the quotation with the given data stack contents, and outputs the new data stack after the word returns. The input sequence is not modified; a new sequence is produced. Does not affect the data stack in surrounding code, other than consuming the two inputs and pushing the output." }
 { $examples
     { $example "USING: continuations math prettyprint ;" "{ 3 7 } [ + ] with-datastack ." "{ 10 }" }
index cfceb1f71574ba1e3e69a2ef4fc8ecea9df6738e..196a12d0d2765fce3f71222683dd72a2bef0382c 100644 (file)
@@ -1,10 +1,17 @@
-! Copyright (C) 2003, 2009 Slava Pestov.
+! Copyright (C) 2003, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays vectors kernel kernel.private sequences
 namespaces make math splitting sorting quotations assocs
 combinators combinators.private accessors words ;
 IN: continuations
 
+: with-datastack ( stack quot -- new-stack )
+    [
+        [ [ datastack ] dip swap [ { } like set-datastack ] dip ] dip
+        swap [ call datastack ] dip
+        swap [ set-datastack ] dip
+    ] (( stack quot -- new-stack )) call-effect-unsafe ;
+
 SYMBOL: error
 SYMBOL: error-continuation
 SYMBOL: error-thread
@@ -90,14 +97,6 @@ SYMBOL: return-continuation
 : return ( -- * )
     return-continuation get continue ;
 
-: with-datastack ( stack quot -- newstack )
-    [
-        [
-            [ [ { } like set-datastack ] dip call datastack ] dip
-            continue-with
-        ] (( stack quot continuation -- * )) call-effect-unsafe
-    ] callcc1 2nip ;
-
 GENERIC: compute-restarts ( error -- seq )
 
 <PRIVATE
index e771442932108e959b33358ea9925b88bbf8fce2..d59ebeca1037685f4bbac001a5282276d39cf380 100644 (file)
@@ -2,9 +2,9 @@ USING: help.markup help.syntax sequences ;
 IN: hash-sets
 
 ARTICLE: "hash-sets" "Hash sets"
-"The " { $vocab-link "hash-sets" } " vocabulary implements hashtable-backed sets. These are of the class:"
+"The " { $vocab-link "hash-sets" } " vocabulary implements hashtable-backed sets. Hash sets form a class:"
 { $subsection hash-set }
-"They can be instantiated with the word"
+"Constructing new hash sets:"
 { $subsection <hash-set> }
 "The syntax for hash sets is described in " { $link "syntax-hash-sets" } "." ;
 
index 8512700852270f1d1498c4080074f25aee789e12..064978f99bf805bd12640e87dd07a8a1b2e164e6 100644 (file)
@@ -26,28 +26,28 @@ HELP: -rot  ( x y z -- z x y ) $complex-shuffle ;
 HELP: dupd  ( x y -- x x y )   $complex-shuffle ;
 HELP: swapd ( x y z -- y x z ) $complex-shuffle ;
 
-HELP: datastack ( -- ds )
-{ $values { "ds" array } }
+HELP: datastack ( -- array )
+{ $values { "array" array } }
 { $description "Outputs an array containing a copy of the data stack contents right before the call to this word, with the top of the stack at the end of the array." } ;
 
-HELP: set-datastack ( ds -- )
-{ $values { "ds" array } }
+HELP: set-datastack ( array -- )
+{ $values { "array" array } }
 { $description "Replaces the data stack contents with a copy of an array. The end of the array becomes the top of the stack." } ;
 
-HELP: retainstack ( -- rs )
-{ $values { "rs" array } }
+HELP: retainstack ( -- array )
+{ $values { "array" array } }
 { $description "Outputs an array containing a copy of the retain stack contents right before the call to this word, with the top of the stack at the end of the array." } ;
 
-HELP: set-retainstack ( rs -- )
-{ $values { "rs" array } }
+HELP: set-retainstack ( array -- )
+{ $values { "array" array } }
 { $description "Replaces the retain stack contents with a copy of an array. The end of the array becomes the top of the stack." } ;
 
-HELP: callstack ( -- cs )
-{ $values { "cs" callstack } }
+HELP: callstack ( -- callstack )
+{ $values { "callstack" callstack } }
 { $description "Outputs a copy of the call stack contents, with the top of the stack at the end of the vector. The stack frame of the caller word is " { $emphasis "not" } " included." } ;
 
-HELP: set-callstack ( cs -- * )
-{ $values { "cs" callstack } }
+HELP: set-callstack ( callstack -- * )
+{ $values { "callstack" callstack } }
 { $description "Replaces the call stack contents. Control flow is transferred immediately to the innermost frame of the new call stack." } ;
 
 HELP: clear
@@ -208,11 +208,6 @@ HELP: call
 
 { call POSTPONE: call( } related-words
 
-HELP: call-clear ( quot -- * )
-{ $values { "quot" callable } }
-{ $description "Calls a quotation with an empty call stack. If the quotation returns, Factor will exit.." }
-{ $notes "Used to implement " { $link "threads" } "." } ;
-
 HELP: keep
 { $values { "x" object } { "quot" { $quotation "( ..a x -- ..b )" } } }
 { $description "Call a quotation with a value on the stack, restoring the value when the quotation returns." }
index ca8aa8286b20e464e9c549b25ccce3ff90fd7028..7d5f7b538b875ca3c4f29d6ad27021ad997deb4a 100644 (file)
@@ -1,7 +1,8 @@
 USING: arrays byte-arrays kernel kernel.private math memory
 namespaces sequences tools.test math.private quotations
 continuations prettyprint io.streams.string debugger assocs
-sequences.private accessors locals.backend grouping words ;
+sequences.private accessors locals.backend grouping words
+system ;
 IN: kernel.tests
 
 [ 0 ] [ f size ] unit-test
@@ -46,6 +47,15 @@ IN: kernel.tests
 
 [ ] [ :c ] unit-test
 
+: overflow-c ( -- ) overflow-c overflow-c ;
+
+! The VM cannot recover from callstack overflow on Windows or
+! OpenBSD, because no facility exists to run memory protection
+! fault handlers on an alternate callstack.
+os [ windows? ] [ openbsd? ] bi or [
+    [ overflow-c ] [ { "kernel-error" 15 f f } = ] must-fail-with
+] unless
+
 [ -7 <byte-array> ] must-fail
 
 [ 3 ] [ t 3 and ] unit-test
index 7f6324c251c8853b9db16e4066db490cb2ac9050..7939a49d7a3e0eb27cc97590699151442f991287 100644 (file)
@@ -86,8 +86,7 @@ M: lexer skip-word ( lexer -- )
 
 : scan ( -- str/f ) lexer get parse-token ;
 
-PREDICATE: unexpected-eof < unexpected
-    got>> not ;
+PREDICATE: unexpected-eof < unexpected got>> not ;
 
 : unexpected-eof ( word -- * ) f unexpected ;
 
@@ -97,14 +96,15 @@ PREDICATE: unexpected-eof < unexpected
     [ unexpected-eof ]
     if* ;
 
-: (each-token) ( end quot -- pred quot )
-    [ [ [ scan dup ] ] dip [ = not ] curry [ [ f ] if* ] curry compose ] dip ; inline
-
 : each-token ( ... end quot: ( ... token -- ... ) -- ... )
-    (each-token) while drop ; inline
+    [ scan ] 2dip {
+        { [ 2over = ] [ 3drop ] }
+        { [ pick not ] [ drop unexpected-eof ] }
+        [ [ nip call ] [ each-token ] 2bi ]
+    } cond ; inline recursive
 
 : map-tokens ( ... end quot: ( ... token -- ... elt ) -- ... seq )
-    (each-token) produce nip ; inline
+    collector [ each-token ] dip { } like ; inline
 
 : parse-tokens ( end -- seq )
     [ ] map-tokens ;
@@ -112,6 +112,7 @@ PREDICATE: unexpected-eof < unexpected
 TUPLE: lexer-error line column line-text parsing-words error ;
 
 M: lexer-error error-file error>> error-file ;
+
 M: lexer-error error-line [ error>> error-line ] [ line>> ] bi or ;
 
 : <lexer-error> ( msg -- error )
index 266a65b957b7cae55b02c158116dd4f72a2415cf..ac2310d3f989489ade42c99ac2abe1dfc9c78e96 100644 (file)
@@ -7,332 +7,334 @@ vocabs.parser words.symbol multiline source-files.errors
 tools.crossref grouping ;
 IN: parser.tests
 
+[ 1 [ 2 [ 3 ] 4 ] 5 ]
+[ "1\n[\n2\n[\n3\n]\n4\n]\n5" eval( -- a b c ) ]
+unit-test
+
+[ t t f f ]
+[ "t t f f" eval( -- ? ? ? ? ) ]
+unit-test
+
+[ "hello world" ]
+[ "\"hello world\"" eval( -- string ) ]
+unit-test
+
+[ "\n\r\t\\" ]
+[ "\"\\n\\r\\t\\\\\"" eval( -- string ) ]
+unit-test
+
+[ "hello world" ]
 [
-    [ 1 [ 2 [ 3 ] 4 ] 5 ]
-    [ "1\n[\n2\n[\n3\n]\n4\n]\n5" eval( -- a b c ) ]
-    unit-test
+    "IN: parser.tests : hello ( -- str ) \"hello world\" ;"
+    eval( -- ) "USE: parser.tests hello" eval( -- string )
+] unit-test
 
-    [ t t f f ]
-    [ "t t f f" eval( -- ? ? ? ? ) ]
-    unit-test
+[ ]
+[ "! This is a comment, people." eval( -- ) ]
+unit-test
 
-    [ "hello world" ]
-    [ "\"hello world\"" eval( -- string ) ]
-    unit-test
+! Test escapes
 
-    [ "\n\r\t\\" ]
-    [ "\"\\n\\r\\t\\\\\"" eval( -- string ) ]
-    unit-test
+[ " " ]
+[ "\"\\u000020\"" eval( -- string ) ]
+unit-test
 
-    [ "hello world" ]
-    [
-        "IN: parser.tests : hello ( -- str ) \"hello world\" ;"
-        eval( -- ) "USE: parser.tests hello" eval( -- string )
-    ] unit-test
+[ "'" ]
+[ "\"\\u000027\"" eval( -- string ) ]
+unit-test
 
-    [ ]
-    [ "! This is a comment, people." eval( -- ) ]
-    unit-test
+! Test EOL comments in multiline strings.
+[ "Hello" ] [ "#! This calls until-eol.\n\"Hello\"" eval( -- string ) ] unit-test
 
-    ! Test escapes
+[ word ] [ \ f class ] unit-test
 
-    [ " " ]
-    [ "\"\\u000020\"" eval( -- string ) ]
-    unit-test
+! Test stack effect parsing
 
-    [ "'" ]
-    [ "\"\\u000027\"" eval( -- string ) ]
-    unit-test
+: effect-parsing-test ( a b -- c ) + ;
 
-    ! Test EOL comments in multiline strings.
-    [ "Hello" ] [ "#! This calls until-eol.\n\"Hello\"" eval( -- string ) ] unit-test
+[ t ] [
+    "effect-parsing-test" "parser.tests" lookup
+    \ effect-parsing-test eq?
+] unit-test
 
-    [ word ] [ \ f class ] unit-test
+[ T{ effect f { "a" "b" } { "c" } f } ]
+[ \ effect-parsing-test "declared-effect" word-prop ] unit-test
 
-    ! Test stack effect parsing
+: baz ( a b -- * ) 2array throw ;
 
-    : effect-parsing-test ( a b -- c ) + ;
+[ t ]
+[ \ baz "declared-effect" word-prop terminated?>> ]
+unit-test
 
-    [ t ] [
-        "effect-parsing-test" "parser.tests" lookup
-        \ effect-parsing-test eq?
-    ] unit-test
+[ ] [ "IN: parser.tests USE: math : effect-parsing-test ( a b -- d ) - ;" eval( -- ) ] unit-test
 
-    [ T{ effect f { "a" "b" } { "c" } f } ]
-    [ \ effect-parsing-test "declared-effect" word-prop ] unit-test
+[ t ] [
+    "effect-parsing-test" "parser.tests" lookup
+    \ effect-parsing-test eq?
+] unit-test
 
-    : baz ( a b -- * ) 2array throw ;
+[ T{ effect f { "a" "b" } { "d" } f } ]
+[ \ effect-parsing-test "declared-effect" word-prop ] unit-test
 
-    [ t ]
-    [ \ baz "declared-effect" word-prop terminated?>> ]
-    unit-test
+[ "IN: parser.tests : missing-- ( a b ) ;" eval( -- ) ] must-fail
 
-    [ ] [ "IN: parser.tests USE: math : effect-parsing-test ( a b -- d ) - ;" eval( -- ) ] unit-test
+! Funny bug
+[ 2 ] [ "IN: parser.tests : \0. ( -- x ) 2 ; \0." eval( -- n ) ] unit-test
 
-    [ t ] [
-        "effect-parsing-test" "parser.tests" lookup
-        \ effect-parsing-test eq?
-    ] unit-test
+! These should throw errors
+[ "HEX: zzz" eval( -- obj ) ] must-fail
+[ "OCT: 999" eval( -- obj ) ] must-fail
+[ "BIN: --0" eval( -- obj ) ] must-fail
 
-    [ T{ effect f { "a" "b" } { "d" } f } ]
-    [ \ effect-parsing-test "declared-effect" word-prop ] unit-test
+DEFER: foo
 
-    ! Funny bug
-    [ 2 ] [ "IN: parser.tests : \0. ( -- x ) 2 ; \0." eval( -- n ) ] unit-test
+"IN: parser.tests USING: math prettyprint ; SYNTAX: foo 2 2 + . ;" eval( -- )
 
-    [ "IN: parser.tests : missing-- ( a b ) ;" eval( -- ) ] must-fail
+[ ] [ "USE: parser.tests foo" eval( -- ) ] unit-test
 
-    ! These should throw errors
-    [ "HEX: zzz" eval( -- obj ) ] must-fail
-    [ "OCT: 999" eval( -- obj ) ] must-fail
-    [ "BIN: --0" eval( -- obj ) ] must-fail
+"IN: parser.tests USING: math prettyprint ; : foo ( -- ) 2 2 + . ;" eval( -- )
 
-    DEFER: foo
+[ t ] [
+    "USE: parser.tests \\ foo" eval( -- word )
+    "foo" "parser.tests" lookup eq?
+] unit-test
 
-    "IN: parser.tests USING: math prettyprint ; SYNTAX: foo 2 2 + . ;" eval( -- )
+! parse-tokens should do the right thing on EOF
+[ "USING: kernel" eval( -- ) ]
+[ error>> T{ unexpected { want ";" } } = ] must-fail-with
 
-    [ ] [ "USE: parser.tests foo" eval( -- ) ] unit-test
+! Test smudging
 
-    "IN: parser.tests USING: math prettyprint ; : foo ( -- ) 2 2 + . ;" eval( -- )
+[ 1 ] [
+    "IN: parser.tests : smudge-me ( -- ) ;" <string-reader> "foo"
+    parse-stream drop
 
-    [ t ] [
-        "USE: parser.tests \\ foo" eval( -- word )
-        "foo" "parser.tests" lookup eq?
-    ] unit-test
+    "foo" source-file definitions>> first assoc-size
+] unit-test
 
-    ! Test smudging
+[ t ] [ "smudge-me" "parser.tests" lookup >boolean ] unit-test
 
-    [ 1 ] [
-        "IN: parser.tests : smudge-me ( -- ) ;" <string-reader> "foo"
-        parse-stream drop
+[ ] [
+    "IN: parser.tests : smudge-me-more ( -- ) ;" <string-reader> "foo"
+    parse-stream drop
+] unit-test
 
-        "foo" source-file definitions>> first assoc-size
-    ] unit-test
+[ t ] [ "smudge-me-more" "parser.tests" lookup >boolean ] unit-test
+[ f ] [ "smudge-me" "parser.tests" lookup >boolean ] unit-test
 
-    [ t ] [ "smudge-me" "parser.tests" lookup >boolean ] unit-test
+[ 3 ] [
+    "IN: parser.tests USING: math strings ; GENERIC: smudge-me ( a -- b ) M: integer smudge-me ; M: string smudge-me ;" <string-reader> "foo"
+    parse-stream drop
 
-    [ ] [
-        "IN: parser.tests : smudge-me-more ( -- ) ;" <string-reader> "foo"
-        parse-stream drop
-    ] unit-test
+    "foo" source-file definitions>> first assoc-size
+] unit-test
 
-    [ t ] [ "smudge-me-more" "parser.tests" lookup >boolean ] unit-test
-    [ f ] [ "smudge-me" "parser.tests" lookup >boolean ] unit-test
+[ 1 ] [
+    "IN: parser.tests USING: arrays ; M: array smudge-me ;" <string-reader> "bar"
+    parse-stream drop
 
-    [ 3 ] [
-        "IN: parser.tests USING: math strings ; GENERIC: smudge-me ( a -- b ) M: integer smudge-me ; M: string smudge-me ;" <string-reader> "foo"
-        parse-stream drop
+    "bar" source-file definitions>> first assoc-size
+] unit-test
 
-        "foo" source-file definitions>> first assoc-size
-    ] unit-test
+[ 2 ] [
+    "IN: parser.tests USING: math strings ; GENERIC: smudge-me ( a -- b ) M: integer smudge-me ;" <string-reader> "foo"
+    parse-stream drop
 
-    [ 1 ] [
-        "IN: parser.tests USING: arrays ; M: array smudge-me ;" <string-reader> "bar"
-        parse-stream drop
+    "foo" source-file definitions>> first assoc-size
+] unit-test
 
-        "bar" source-file definitions>> first assoc-size
-    ] unit-test
+[ t ] [
+    array "smudge-me" "parser.tests" lookup order member-eq?
+] unit-test
 
-    [ 2 ] [
-        "IN: parser.tests USING: math strings ; GENERIC: smudge-me ( a -- b ) M: integer smudge-me ;" <string-reader> "foo"
-        parse-stream drop
+[ t ] [
+    integer "smudge-me" "parser.tests" lookup order member-eq?
+] unit-test
 
-        "foo" source-file definitions>> first assoc-size
-    ] unit-test
-    
-    [ t ] [
-        array "smudge-me" "parser.tests" lookup order member-eq?
-    ] unit-test
-    
-    [ t ] [
-        integer "smudge-me" "parser.tests" lookup order member-eq?
-    ] unit-test
-    
-    [ f ] [
-        string "smudge-me" "parser.tests" lookup order member-eq?
-    ] unit-test
+[ f ] [
+    string "smudge-me" "parser.tests" lookup order member-eq?
+] unit-test
 
-    [ ] [
-        "IN: parser.tests USE: math 2 2 +" <string-reader> "a"
-        parse-stream drop
-    ] unit-test
-    
-    [ t ] [
-        "a" <pathname> \ + usage member?
-    ] unit-test
+[ ] [
+    "IN: parser.tests USE: math 2 2 +" <string-reader> "a"
+    parse-stream drop
+] unit-test
 
-    [ ] [
-        "IN: parser.tests USE: math 2 2 -" <string-reader> "a"
-        parse-stream drop
-    ] unit-test
-    
-    [ f ] [
-        "a" <pathname> \ + usage member?
-    ] unit-test
-    
-    [ ] [
-        "a" source-files get delete-at
-        2 [
-            "IN: parser.tests DEFER: x : y ( -- ) x ; : x ( -- ) y ;"
-            <string-reader> "a" parse-stream drop
-        ] times
-    ] unit-test
-    
-    "a" source-files get delete-at
+[ t ] [
+    "a" <pathname> \ + usage member?
+] unit-test
 
-    [
-        "IN: parser.tests : x ( -- ) ; : y ( -- * ) 3 throw ; this is an error"
-        <string-reader> "a" parse-stream
-    ] [ source-file-error? ] must-fail-with
+[ ] [
+    "IN: parser.tests USE: math 2 2 -" <string-reader> "a"
+    parse-stream drop
+] unit-test
 
-    [ t ] [
-        "y" "parser.tests" lookup >boolean
-    ] unit-test
+[ f ] [
+    "a" <pathname> \ + usage member?
+] unit-test
 
-    [ f ] [
-        "IN: parser.tests : x ( -- ) ;"
+[ ] [
+    "a" source-files get delete-at
+    2 [
+        "IN: parser.tests DEFER: x : y ( -- ) x ; : x ( -- ) y ;"
         <string-reader> "a" parse-stream drop
-        
-        "y" "parser.tests" lookup
-    ] unit-test
+    ] times
+] unit-test
 
-    ! Test new forward definition logic
-    [ ] [
-        "IN: axx : axx ( -- ) ;"
-        <string-reader> "axx" parse-stream drop
-    ] unit-test
+"a" source-files get delete-at
 
-    [ ] [
-        "USE: axx IN: bxx : bxx ( -- ) ; : cxx ( -- ) axx bxx ;"
-        <string-reader> "bxx" parse-stream drop
-    ] unit-test
-
-    ! So we move the bxx word to axx...
-    [ ] [
-        "IN: axx : axx ( -- ) ; : bxx ( -- ) ;"
-        <string-reader> "axx" parse-stream drop
-    ] unit-test
+[
+    "IN: parser.tests : x ( -- ) ; : y ( -- * ) 3 throw ; this is an error"
+    <string-reader> "a" parse-stream
+] [ source-file-error? ] must-fail-with
 
-    [ t ] [ "bxx" "axx" lookup >boolean ] unit-test
+[ t ] [
+    "y" "parser.tests" lookup >boolean
+] unit-test
 
-    ! And reload the file that uses it...
-    [ ] [
-        "USE: axx IN: bxx ( -- ) : cxx ( -- ) axx bxx ;"
-        <string-reader> "bxx" parse-stream drop
-    ] unit-test
+[ f ] [
+    "IN: parser.tests : x ( -- ) ;"
+    <string-reader> "a" parse-stream drop
     
-    ! And hope not to get a forward-error!
+    "y" "parser.tests" lookup
+] unit-test
 
-    ! Turning a generic into a non-generic could cause all
-    ! kinds of funnyness
-    [ ] [
-        "IN: ayy USE: kernel GENERIC: ayy ( a -- b ) M: object ayy ;"
-        <string-reader> "ayy" parse-stream drop
-    ] unit-test
+! Test new forward definition logic
+[ ] [
+    "IN: axx : axx ( -- ) ;"
+    <string-reader> "axx" parse-stream drop
+] unit-test
 
-    [ ] [
-        "IN: ayy USE: kernel : ayy ( -- ) ;"
-        <string-reader> "ayy" parse-stream drop
-    ] unit-test
+[ ] [
+    "USE: axx IN: bxx : bxx ( -- ) ; : cxx ( -- ) axx bxx ;"
+    <string-reader> "bxx" parse-stream drop
+] unit-test
 
-    [ ] [
-        "IN: azz TUPLE: my-class ; GENERIC: a-generic ( a -- b )"
-        <string-reader> "azz" parse-stream drop
-    ] unit-test
+! So we move the bxx word to axx...
+[ ] [
+    "IN: axx : axx ( -- ) ; : bxx ( -- ) ;"
+    <string-reader> "axx" parse-stream drop
+] unit-test
 
-    [ ] [
-        "USE: azz M: my-class a-generic ;"
-        <string-reader> "azz-2" parse-stream drop
-    ] unit-test
+[ t ] [ "bxx" "axx" lookup >boolean ] unit-test
 
-    [ ] [
-        "IN: azz GENERIC: a-generic ( a -- b )"
-        <string-reader> "azz" parse-stream drop
-    ] unit-test
+! And reload the file that uses it...
+[ ] [
+    "USE: axx IN: bxx ( -- ) : cxx ( -- ) axx bxx ;"
+    <string-reader> "bxx" parse-stream drop
+] unit-test
 
-    [ ] [
-        "USE: azz USE: math M: integer a-generic ;"
-        <string-reader> "azz-2" parse-stream drop
-    ] unit-test
+! And hope not to get a forward-error!
 
-    [ ] [
-        "IN: parser.tests : <bogus-error> ( -- ) ; : bogus ( -- error ) <bogus-error> ;"
-        <string-reader> "bogus-error" parse-stream drop
-    ] unit-test
+! Turning a generic into a non-generic could cause all
+! kinds of funnyness
+[ ] [
+    "IN: ayy USE: kernel GENERIC: ayy ( a -- b ) M: object ayy ;"
+    <string-reader> "ayy" parse-stream drop
+] unit-test
 
-    [ ] [
-        "IN: parser.tests TUPLE: bogus-error ; C: <bogus-error> bogus-error : bogus ( -- error ) <bogus-error> ;"
-        <string-reader> "bogus-error" parse-stream drop
-    ] unit-test
+[ ] [
+    "IN: ayy USE: kernel : ayy ( -- ) ;"
+    <string-reader> "ayy" parse-stream drop
+] unit-test
 
-    ! Problems with class predicates -vs- ordinary words
-    [ ] [
-        "IN: parser.tests TUPLE: killer ;"
-        <string-reader> "removing-the-predicate" parse-stream drop
-    ] unit-test
+[ ] [
+    "IN: azz TUPLE: my-class ; GENERIC: a-generic ( a -- b )"
+    <string-reader> "azz" parse-stream drop
+] unit-test
 
-    [ ] [
-        "IN: parser.tests GENERIC: killer? ( a -- b )"
-        <string-reader> "removing-the-predicate" parse-stream drop
-    ] unit-test
-    
-    [ t ] [
-        "killer?" "parser.tests" lookup >boolean
-    ] unit-test
+[ ] [
+    "USE: azz M: my-class a-generic ;"
+    <string-reader> "azz-2" parse-stream drop
+] unit-test
 
-    [
-        "IN: parser.tests TUPLE: another-pred-test ; GENERIC: another-pred-test? ( a -- b )"
-        <string-reader> "removing-the-predicate" parse-stream
-    ] [ error>> error>> error>> redefine-error? ] must-fail-with
+[ ] [
+    "IN: azz GENERIC: a-generic ( a -- b )"
+    <string-reader> "azz" parse-stream drop
+] unit-test
 
-    [
-        "IN: parser.tests TUPLE: class-redef-test ; TUPLE: class-redef-test ;"
-        <string-reader> "redefining-a-class-1" parse-stream
-    ] [ error>> error>> error>> redefine-error? ] must-fail-with
+[ ] [
+    "USE: azz USE: math M: integer a-generic ;"
+    <string-reader> "azz-2" parse-stream drop
+] unit-test
 
-    [ ] [
-        "IN: parser.tests TUPLE: class-redef-test ; SYMBOL: class-redef-test"
-        <string-reader> "redefining-a-class-2" parse-stream drop
-    ] unit-test
+[ ] [
+    "IN: parser.tests : <bogus-error> ( -- ) ; : bogus ( -- error ) <bogus-error> ;"
+    <string-reader> "bogus-error" parse-stream drop
+] unit-test
 
-    [
-        "IN: parser.tests TUPLE: class-redef-test ; SYMBOL: class-redef-test : class-redef-test ( -- ) ;"
-        <string-reader> "redefining-a-class-3" parse-stream drop
-    ] [ error>> error>> error>> redefine-error? ] must-fail-with
+[ ] [
+    "IN: parser.tests TUPLE: bogus-error ; C: <bogus-error> bogus-error : bogus ( -- error ) <bogus-error> ;"
+    <string-reader> "bogus-error" parse-stream drop
+] unit-test
 
-    [ ] [
-        "IN: parser.tests TUPLE: class-fwd-test ;"
-        <string-reader> "redefining-a-class-3" parse-stream drop
-    ] unit-test
+! Problems with class predicates -vs- ordinary words
+[ ] [
+    "IN: parser.tests TUPLE: killer ;"
+    <string-reader> "removing-the-predicate" parse-stream drop
+] unit-test
 
-    [
-        "IN: parser.tests \\ class-fwd-test"
-        <string-reader> "redefining-a-class-3" parse-stream drop
-    ] [ error>> error>> error>> no-word-error? ] must-fail-with
+[ ] [
+    "IN: parser.tests GENERIC: killer? ( a -- b )"
+    <string-reader> "removing-the-predicate" parse-stream drop
+] unit-test
 
-    [ ] [
-        "IN: parser.tests TUPLE: class-fwd-test ; SYMBOL: class-fwd-test"
-        <string-reader> "redefining-a-class-3" parse-stream drop
-    ] unit-test
+[ t ] [
+    "killer?" "parser.tests" lookup >boolean
+] unit-test
 
-    [
-        "IN: parser.tests \\ class-fwd-test"
-        <string-reader> "redefining-a-class-3" parse-stream drop
-    ] [ error>> error>> error>> no-word-error? ] must-fail-with
+[
+    "IN: parser.tests TUPLE: another-pred-test ; GENERIC: another-pred-test? ( a -- b )"
+    <string-reader> "removing-the-predicate" parse-stream
+] [ error>> error>> error>> redefine-error? ] must-fail-with
 
-    [
-        "IN: parser.tests : foo ( -- ) ; TUPLE: foo ;"
-        <string-reader> "redefining-a-class-4" parse-stream drop
-    ] [ error>> 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
+] [ error>> error>> error>> redefine-error? ] must-fail-with
 
-    [ ] [
-        "IN: parser.tests : foo ( x y -- z ) 1 2 ; : bar ( a -- b ) ;" eval( -- )
-    ] unit-test
+[ ] [
+    "IN: parser.tests TUPLE: class-redef-test ; SYMBOL: class-redef-test"
+    <string-reader> "redefining-a-class-2" parse-stream drop
+] unit-test
 
-    [
-        "IN: parser.tests : foo ( x y -- z) 1 2 ; : bar ( a -- b ) ;" eval( -- )
-    ] must-fail
-] with-file-vocabs
+[
+    "IN: parser.tests TUPLE: class-redef-test ; SYMBOL: class-redef-test : class-redef-test ( -- ) ;"
+    <string-reader> "redefining-a-class-3" parse-stream drop
+] [ error>> error>> error>> redefine-error? ] must-fail-with
+
+[ ] [
+    "IN: parser.tests TUPLE: class-fwd-test ;"
+    <string-reader> "redefining-a-class-3" parse-stream drop
+] unit-test
+
+[
+    "IN: parser.tests \\ class-fwd-test"
+    <string-reader> "redefining-a-class-3" parse-stream drop
+] [ error>> error>> error>> no-word-error? ] must-fail-with
+
+[ ] [
+    "IN: parser.tests TUPLE: class-fwd-test ; SYMBOL: class-fwd-test"
+    <string-reader> "redefining-a-class-3" parse-stream drop
+] unit-test
+
+[
+    "IN: parser.tests \\ class-fwd-test"
+    <string-reader> "redefining-a-class-3" parse-stream drop
+] [ error>> error>> error>> no-word-error? ] must-fail-with
+
+[
+    "IN: parser.tests : foo ( -- ) ; TUPLE: foo ;"
+    <string-reader> "redefining-a-class-4" parse-stream drop
+] [ error>> error>> error>> redefine-error? ] must-fail-with
+
+[ ] [
+    "IN: parser.tests : foo ( x y -- z ) 1 2 ; : bar ( a -- b ) ;" eval( -- )
+] unit-test
+
+[
+    "IN: parser.tests : foo ( x y -- z) 1 2 ; : bar ( a -- b ) ;" eval( -- )
+] must-fail
 
 [ ] [
     "IN: parser.tests USE: kernel PREDICATE: foo < object ( x -- y ) ;" eval( -- )
index 75df4069dc61252bbcd031ec0eb17f46709acaee..5bde8a1febce4e5a09f3e661ba22fce2f3e0b217 100644 (file)
@@ -61,9 +61,9 @@ ARTICLE: "set-implementations" "Set implementations"
 ARTICLE: "sequence-sets" "Sequences as sets"
 "Any sequence can be used as a set. The members of this set are the elements of the sequence. Calling the word " { $link members } " on a sequence returns a copy of the sequence with only one listing of each member. Destructive operations " { $link adjoin } " and " { $link delete } " only work properly on growable sequences like " { $link vector } "s."
 $nl
-"Care must be taken in writing efficient code using sequence sets. Testing for membership with " { $link in? } ", as well as the destructive set operations, take time proportional to the size of the sequence. Another representation, like " { $link "hash-sets" } ", would take constant time for membership tests. But binary operations like " { $link union } "are asymptotically optimal, taking time proportional to the sum of the size of the inputs."
+"Care must be taken in writing efficient code using sequence sets. Testing for membership with " { $link in? } ", as well as the destructive set operations, take time proportional to the size of the sequence. Another representation, like " { $link "hash-sets" } ", would take constant time for membership tests. But binary operations like " { $link union } " are asymptotically optimal, taking time proportional to the sum of the size of the inputs."
 $nl
-"As one particlar example, " { $link POSTPONE: f } " is a representation of the empty set, as it represents the empty sequence." ;
+"As one particular example, " { $link POSTPONE: f } " is a representation of the empty set, since it is an empty sequence." ;
 
 HELP: set
 { $class-description "The class of all sets. Custom implementations of the set protocol should be declared as instances of this mixin for all set implementation to work correctly." } ;
index 84a753fb1b58f4846a787d7c19b17547412fd040..bd70b0be62235d1ab443a04d92c79851c381d81e 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2004, 2009 Slava Pestov.
+! Copyright (C) 2004, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors alien arrays byte-arrays byte-vectors definitions generic
 hashtables kernel math namespaces parser lexer sequences strings
@@ -125,7 +125,7 @@ IN: bootstrap.syntax
     ] define-core-syntax
 
     "SYMBOLS:" [
-        ";" [ create-in dup reset-generic define-symbol ] each-token
+        ";" [ create-in [ reset-generic ] [ define-symbol ] bi ] each-token
     ] define-core-syntax
 
     "SINGLETONS:" [
index 765861c62f3790e8f0632164f5b72f749624cfa8..ecd5047fba66d9edd6c0c0cc03c41ad377504950 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2007, 2009 Slava Pestov.
+! Copyright (C) 2007, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel kernel.private sequences math namespaces
 init splitting assocs system.private layouts words ;
@@ -57,4 +57,4 @@ PRIVATE>
 
 : embedded? ( -- ? ) 15 special-object ;
 
-: exit ( n -- ) do-shutdown-hooks (exit) ;
+: exit ( n -- ) do-shutdown-hooks (exit) ;
index 08ab729b6daecd36a806459738b82c10ed8c1fac..d5a6be53359b0867660beca3966508fb226d763b 100755 (executable)
@@ -50,7 +50,9 @@ $nl
 { $subsections "vocabs.metadata" "vocabs.icons" }
 "Vocabularies can also be loaded at run time, without altering the vocabulary search path. This is done by calling a word which loads a vocabulary if it is not in the image, doing nothing if it is:"
 { $subsections require }
-"The above word will only ever load a vocabulary once in a given session. There is another word which unconditionally loads vocabulary from disk, regardless of whether or not is has already been loaded:"
+"The above word will only ever load a vocabulary once in a given session. Sometimes, two vocabularies require special code to interact. The following word is used to load one vocabulary when another is present:"
+{ $subsections require-when }
+"There is another word which unconditionally loads vocabulary from disk, regardless of whether or not is has already been loaded:"
 { $subsections reload }
 "For interactive development in the listener, calling " { $link reload } " directly is usually not necessary, since a better facility exists for " { $link "vocabs.refresh" } "."
 $nl
@@ -111,6 +113,12 @@ HELP: require
 { $description "Loads a vocabulary if it has not already been loaded." }
 { $notes "To unconditionally reload a vocabulary, use " { $link reload } ". To reload changed source files only, use the words in " { $link "vocabs.refresh" } "." } ;
 
+HELP: require-when
+{ $values { "if" "a vocabulary specifier" } { "then" "a vocabulary specifier" } }
+{ $description "Loads the " { $snippet "then" } " vocabulary if it is not loaded and the " { $snippet "if" } " vocabulary is. If the " { $snippet "if" } " vocabulary is not loaded now, but it is later, then the " { $snippet "then" } " vocabulary will be loaded along with it at that time." }
+{ $notes "This is used to express a joint dependency of vocabularies. If vocabularies " { $snippet "a" } " and " { $snippet "b" } " use code in vocabulary " { $snippet "c" } " to interact, then the following line can be placed in " { $snippet "a" } " in order express the dependency."
+{ $code "\"b\" \"c\" require-when" } } ;
+
 HELP: run
 { $values { "vocab" "a vocabulary specifier" } }
 { $description "Runs a vocabulary's main entry point. The main entry point is set with the " { $link POSTPONE: MAIN: } " parsing word." } ;
index 09f28541e0ba92c844a24b84e346d837b3b86f7d..89afb50af7b15bd83ef9e567e2783b3318752520 100644 (file)
@@ -170,3 +170,21 @@ forget-junk
 ] with-compilation-unit
 
 [ ] [ [ "vocabs.loader.test.j" require ] [ drop :1 ] recover ] unit-test
+
+[ ] [ "vocabs.loader.test.m" require ] unit-test
+[ f ] [ "vocabs.loader.test.n" vocab ] unit-test
+[ ] [ "vocabs.loader.test.o" require ] unit-test
+[ t ] [ "vocabs.loader.test.n" vocab >boolean ] unit-test
+
+[
+    "mno" [ "vocabs.loader.test." swap suffix forget-vocab ] each
+] with-compilation-unit
+
+[ ] [ "vocabs.loader.test.o" require ] unit-test
+[ f ] [ "vocabs.loader.test.n" vocab ] unit-test
+[ ] [ "vocabs.loader.test.m" require ] unit-test
+[ t ] [ "vocabs.loader.test.n" vocab >boolean ] unit-test
+
+[
+    "mno" [ "vocabs.loader.test." swap suffix forget-vocab ] each
+] with-compilation-unit
index c8cf77b795612145bc2a0acbe6fda1d21ff1d6d0..59fe06e6fd2b1a6bd27cd6082350f1cd8f12ef74 100644 (file)
@@ -62,8 +62,15 @@ SYMBOL: check-vocab-hook
 
 check-vocab-hook [ [ drop ] ] initialize
 
+DEFER: require
+
 <PRIVATE
 
+: load-conditional-requires ( vocab-name -- )
+    conditional-requires get
+    [ at [ require ] each ] 
+    [ delete-at ] 2bi ;
+
 : load-source ( vocab -- )
     dup check-vocab-hook get call( vocab -- )
     [
@@ -71,7 +78,8 @@ check-vocab-hook [ [ drop ] ] initialize
         dup vocab-source-path [ parse-file ] [ [ ] ] if*
         [ +parsing+ >>source-loaded? ] dip
         [ % ] [ call( -- ) ] if-bootstrapping
-        +done+ >>source-loaded? drop
+        +done+ >>source-loaded?
+        vocab-name load-conditional-requires
     ] [ ] [ f >>source-loaded? ] cleanup ;
 
 : load-docs ( vocab -- )
@@ -88,6 +96,12 @@ PRIVATE>
 : require ( vocab -- )
     load-vocab drop ;
 
+: require-when ( if then -- )
+    over vocab
+    [ nip require ]
+    [ swap conditional-requires get [ swap suffix ] change-at ]
+    if ;
+
 : reload ( name -- )
     dup vocab
     [ [ load-source ] [ load-docs ] bi ]
diff --git a/core/vocabs/loader/test/m/m.factor b/core/vocabs/loader/test/m/m.factor
new file mode 100644 (file)
index 0000000..d6d3bd8
--- /dev/null
@@ -0,0 +1,4 @@
+USE: vocabs.loader
+IN: vocabs.loader.test.m
+
+"vocabs.loader.test.o" "vocabs.loader.test.n" require-when
diff --git a/core/vocabs/loader/test/m/tags.txt b/core/vocabs/loader/test/m/tags.txt
new file mode 100644 (file)
index 0000000..5d77766
--- /dev/null
@@ -0,0 +1 @@
+untested
diff --git a/core/vocabs/loader/test/n/n.factor b/core/vocabs/loader/test/n/n.factor
new file mode 100644 (file)
index 0000000..b3cedb3
--- /dev/null
@@ -0,0 +1 @@
+IN: vocabs.loader.test.n
diff --git a/core/vocabs/loader/test/n/tags.txt b/core/vocabs/loader/test/n/tags.txt
new file mode 100644 (file)
index 0000000..5d77766
--- /dev/null
@@ -0,0 +1 @@
+untested
diff --git a/core/vocabs/loader/test/o/o.factor b/core/vocabs/loader/test/o/o.factor
new file mode 100644 (file)
index 0000000..cc8051a
--- /dev/null
@@ -0,0 +1 @@
+IN: vocabs.loader.test.o
diff --git a/core/vocabs/loader/test/o/tags.txt b/core/vocabs/loader/test/o/tags.txt
new file mode 100644 (file)
index 0000000..5d77766
--- /dev/null
@@ -0,0 +1 @@
+untested
index 239b88a2e80b6030285b0390602445a292072f7c..e48d6c3031317965d7c24f9dd80acd5d0c680604 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2007, 2009 Eduardo Cavazos, Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors assocs strings kernel sorting namespaces
-sequences definitions ;
+sequences definitions sets ;
 IN: vocabs
 
 SYMBOL: dictionary
@@ -83,6 +83,9 @@ ERROR: bad-vocab-name name ;
 : check-vocab-name ( name -- name )
     dup string? [ bad-vocab-name ] unless ;
 
+SYMBOL: conditional-requires
+conditional-requires [ H{ } clone ] initialize
+
 : create-vocab ( name -- vocab )
     check-vocab-name
     dictionary get [ <vocab> ] cache
@@ -118,8 +121,8 @@ M: vocab-spec >vocab-link ;
 M: string >vocab-link dup vocab [ ] [ <vocab-link> ] ?if ;
 
 : forget-vocab ( vocab -- )
-    dup words forget-all
-    vocab-name dictionary get delete-at
+    [ words forget-all ]
+    [ vocab-name dictionary get delete-at ] bi
     notify-vocab-observers ;
 
 M: vocab-spec forget* forget-vocab ;
diff --git a/extra/astar/astar-docs.factor b/extra/astar/astar-docs.factor
deleted file mode 100644 (file)
index d19166c..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-! Copyright (C) 2010 Samuel Tardieu.
-! See http://factorcode.org/license.txt for BSD license.
-USING: help.markup help.syntax ;
-IN: astar
-
-HELP: astar
-{ $description "This tuple must be subclassed and its method " { $link cost } ", "
-  { $link heuristic } ", and " { $link neighbours } " must be implemented. "
-  "Alternatively, the " { $link <astar> } " word can be used to build a non-specialized version." } ;
-
-HELP: cost
-{ $values
-  { "from" "a node" }
-  { "to" "a node" }
-  { "astar" "an instance of a subclassed " { $link astar } " tuple" }
-  { "n" "a number" }
-}
-{ $description "Return the cost to go from " { $snippet "from" } " to " { $snippet "to" } ". "
-  { $snippet "to" } " is necessarily a neighbour of " { $snippet "from" } "."
-} ;
-
-HELP: heuristic
-{ $values
-  { "from" "a node" }
-  { "to" "a node" }
-  { "astar" "an instance of a subclassed " { $link astar } " tuple" }
-  { "n" "a number" }
-}
-{ $description "Return the estimated (undervalued) cost to go from " { $snippet "from" } " to " { $snippet "to" } ". "
-  { $snippet "from" } " and " { $snippet "to" } " are not necessarily neighbours."
-} ;
-
-HELP: neighbours
-{ $values
-  { "node" "a node" }
-  { "astar" "an instance of a subclassed " { $link astar } " tuple" }
-  { "seq" "a sequence of nodes" }
-}
-{ $description "Return the list of nodes reachable from " { $snippet "node" } "." } ;
-
-HELP: <astar>
-{ $values
-  { "neighbours" "a quotation with stack effect ( node -- seq )" }
-  { "cost" "a quotation with stack effect ( from to -- cost )" }
-  { "heuristic" "a quotation with stack effect ( pos target -- cost )" }
-  { "astar" "a astar tuple" }
-}
-{ $description "Build an astar object from the given quotations. The "
-  { $snippet "neighbours" } " one builds the list of neighbours. The "
-  { $snippet "cost" } " and " { $snippet "heuristic" } " ones represent "
-  "respectively the cost for transitioning from a node to one of its neighbour, "
-  "and the underestimated cost for going from a node to the target. This solution "
-  "may not be as efficient as subclassing the " { $link astar } " tuple."
-} ;
-
-HELP: find-path
-{ $values
-  { "start" "a node" }
-  { "target" "a node" }
-  { "astar" "a astar tuple" }
-  { "path/f" "an optimal path from " { $snippet "start" } " to " { $snippet "target" }
-    ", or f if no such path exists" }
-}
-{ $description "Find a path between " { $snippet "start" } " and " { $snippet "target" }
-  " using the A* algorithm. The " { $snippet "astar" } " tuple must have been previously "
-  " built using " { $link <astar> } "."
-} ;
-
-HELP: considered
-{ $values
-  { "astar" "a astar tuple" }
-  { "considered" "a sequence" }
-}
-{ $description "When called after a call to " { $link find-path } ", return a list of nodes "
-  "which have been examined during the A* exploration."
-} ;
-
-ARTICLE: "astar" "A* algorithm"
-"The " { $vocab-link "astar" } " vocabulary implements a graph search algorithm for finding the least-cost path from one node to another." $nl
-"Make an A* object:"
-{ $subsections <astar> }
-"Find a path between nodes:"
-{ $subsections find-path } ;
-
-ABOUT: "astar"
diff --git a/extra/astar/astar-tests.factor b/extra/astar/astar-tests.factor
deleted file mode 100644 (file)
index 6e2e2f4..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-! Copyright (C) 2010 Samuel Tardieu.
-! See http://factorcode.org/license.txt for BSD license.
-USING: arrays assocs astar combinators hashtables kernel literals math math.functions
-math.vectors sequences sorting splitting strings tools.test ;
-IN: astar.tests
-
-! Use a 10x9 maze (see below) to try to go from s to e, f or g.
-! X means that a position is unreachable.
-! The costs model is:
-!   - going up costs 5 points
-!   - going down costs 1 point
-!   - going left or right costs 2 points
-
-<<
-
-TUPLE: maze < astar ;
-
-: reachable? ( pos -- ? )
-    first2 [ 2 * 5 + ] [ 2 + ] bi* $[
-"    0 1 2 3 4 5 6 7 8 9
-
-  0  X X X X X X X X X X
-  1  X s           f X X
-  2  X X X X   X X X X X
-  3  X X X X   X X X X X
-  4  X X X X   X       X
-  5  X X       X   X   X
-  6  X X X X   X   X e X
-  7  X g   X           X
-  8  X X X X X X X X X X"
-        "\n" split ] nth nth CHAR: X = not ;
-
-M: maze neighbours
-    drop
-    first2
-    { [ 1 + 2array ] [ 1 - 2array ] [ [ 1 + ] dip 2array ] [ [ 1 - ] dip 2array ] } 2cleave
-    4array
-    [ reachable? ] filter ;
-
-M: maze heuristic
-    drop v- [ abs ] [ + ] map-reduce ;
-
-M: maze cost
-    drop 2dup [ first ] bi@ = [ [ second ] bi@ > 1 5 ? ] [ 2drop 2 ] if ;
-
-: test1 ( to -- path considered )
-    { 1 1 } swap maze new [ find-path ] [ considered ] bi ;
->>
-
-! Existing path from s to f
-[
-    {
-        { 1 1 }
-        { 2 1 }
-        { 3 1 }
-        { 4 1 }
-        { 4 2 }
-        { 4 3 }
-        { 4 4 }
-        { 4 5 }
-        { 4 6 }
-        { 4 7 }
-        { 5 7 }
-        { 6 7 }
-        { 7 7 }
-        { 8 7 }
-        { 8 6 }
-    }
-] [
-    { 8 6 } test1 drop
-] unit-test
-
-! Check that only the right positions have been considered in the s to f path
-[ 7 ] [ { 7 1 } test1 nip length ] unit-test
-
-! Non-existing path from s to g -- all positions must have been considered
-[ f 26 ] [ { 1 7 } test1 length ] unit-test
-
-! Look for a path between A and C. The best path is A --> D --> C. C will be placed
-! in the open set early because B will be examined first. This checks that the evaluation
-! of C is correctly replaced in the open set.
-!
-! We use no heuristic here and always return 0.
-!
-!       (5)
-!     B ---> C <--------
-!                        \ (2)
-!     ^      ^            |
-!     |      |            |
-! (1) |      | (2)        |
-!     |      |            |
-!
-!     A ---> D ---------> E ---> F
-!       (2)       (1)       (1)
-
-<<
-
-! In this version, we will use the quotations-aware version through <astar>.
-
-: n ( pos -- neighbours )
-    $[ { "ABD" "BC" "C" "DCE" "ECF" } [ unclip swap 2array ] map >hashtable ] at ;
-
-: c ( from to -- cost )
-    "" 2sequence H{ { "AB" 1 } { "AD" 2 } { "BC" 5 } { "DC" 2 } { "DE" 1 } { "EC" 2 } { "EF" 1 } } at ;
-
-: test2 ( fromto -- path considered )
-    first2 [ n ] [ c ] [ 2drop 0 ] <astar> [ find-path ] [ considered natural-sort >string ] bi ;
->>
-
-! Check path from A to C -- all nodes but F must have been examined
-[ "ADC" "ABCDE" ] [ "AC" test2 [ >string ] dip ] unit-test
-
-! No path from D to B -- all nodes reachable from D must have been examined
-[ f "CDEF" ] [ "DB" test2 ] unit-test
diff --git a/extra/astar/astar.factor b/extra/astar/astar.factor
deleted file mode 100644 (file)
index 45f8aaa..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-! Copyright (C) 2010 Samuel Tardieu.
-! See http://factorcode.org/license.txt for BSD license.
-USING: accessors assocs heaps kernel math sequences sets shuffle ;
-IN: astar
-
-! This implements the A* algorithm. See http://en.wikipedia.org/wiki/A*
-
-TUPLE: astar g in-closed-set ;
-GENERIC: cost ( from to astar -- n )
-GENERIC: heuristic ( from to astar -- n )
-GENERIC: neighbours ( node astar -- seq )
-
-<PRIVATE
-
-TUPLE: (astar) astar goal origin in-open-set open-set ;
-
-: (add-to-open-set) ( h node astar -- )
-    2dup in-open-set>> at* [ over open-set>> heap-delete ] [ drop ] if
-    [ swapd open-set>> heap-push* ] [ in-open-set>> set-at ] 2bi ;
-
-: add-to-open-set ( node astar -- )
-    [ astar>> g>> at ] 2keep
-    [ [ goal>> ] [ astar>> heuristic ] bi + ] 2keep
-    (add-to-open-set) ;
-
-: ?add-to-open-set ( node astar -- )
-    2dup astar>> in-closed-set>> key? [ 2drop ] [ add-to-open-set ] if ;
-
-: move-to-closed-set ( node astar -- )
-    [ astar>> in-closed-set>> conjoin ] [ in-open-set>> delete-at ] 2bi ;
-
-: get-first ( astar -- node )
-    [ open-set>> heap-pop drop dup ] [ move-to-closed-set ] bi ;
-
-: set-g ( origin g node astar -- )
-    [ [ origin>> set-at ] [ astar>> g>> set-at ] bi-curry bi-curry bi* ] [ ?add-to-open-set ] 2bi ;
-
-: cost-through ( origin node astar -- cost )
-    [ astar>> cost ] [ nip astar>> g>> at ] 3bi + ;
-
-: ?set-g ( origin node astar -- )
-    [ cost-through ] 3keep [ swap ] 2dip
-    3dup astar>> g>> at [ 1/0. ] unless* > [ 4drop ] [ set-g ] if ;
-
-: build-path ( target astar -- path )
-    [ over ] [ over [ [ origin>> at ] keep ] dip ] produce 2nip reverse ;
-
-: handle ( node astar -- )
-    dupd [ astar>> neighbours ] keep [ ?set-g ] curry with each ;
-
-: (find-path) ( astar -- path/f )
-    dup open-set>> heap-empty? [
-        drop f
-    ] [
-        [ get-first ] keep 2dup goal>> = [ build-path ] [ [ handle ] [ (find-path) ] bi ] if
-    ] if ;
-
-: (init) ( from to astar -- )
-    swap >>goal
-    H{ } clone over astar>> (>>g)
-    H{ } clone over astar>> (>>in-closed-set)
-    H{ } clone >>origin
-    H{ } clone >>in-open-set
-    <min-heap> >>open-set
-    [ 0 ] 2dip [ (add-to-open-set) ] [ astar>> g>> set-at ] 3bi ;
-
-TUPLE: astar-simple < astar cost heuristic neighbours ;
-M: astar-simple cost cost>> call( n1 n2 -- c ) ;
-M: astar-simple heuristic heuristic>> call( n1 n2 -- c ) ;
-M: astar-simple neighbours neighbours>> call( n -- neighbours ) ;
-
-PRIVATE>
-
-: find-path ( start target astar -- path/f )
-    (astar) new [ (>>astar) ] keep [ (init) ] [ (find-path) ] bi ;
-
-: <astar> ( neighbours cost heuristic -- astar )
-    astar-simple new swap >>heuristic swap >>cost swap >>neighbours ;
-
-: considered ( astar -- considered )
-    in-closed-set>> keys ;
diff --git a/extra/astar/authors.txt b/extra/astar/authors.txt
deleted file mode 100644 (file)
index f3b0233..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Samuel Tardieu
diff --git a/extra/astar/summary.txt b/extra/astar/summary.txt
deleted file mode 100644 (file)
index ff3167a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-A* path-finding algorithm
index b4bd0e7b35e6a8f0d41992b7e7faba52bb7d25da..f13c9c1e77f7b880a3377fd0ad6283a5d9c7b616 100644 (file)
@@ -1 +1 @@
-Doug Coleman
\ No newline at end of file
+Joe Groff
index 8821d4570cf7f21e68b6f6c233c809f279637553..d71999ab871c1d6c36f63891c6be0e763be72a53 100644 (file)
@@ -1,44 +1,72 @@
-! Copyright (C) 2009 Doug Coleman.
-! See http://factorcode.org/license.txt for BSD license.
-USING: cursors math tools.test make ;
+! (c)2010 Joe Groff bsd license
+USING: accessors cursors make math sequences sorting tools.test ;
+FROM: cursors => each map assoc-each assoc>map ;
 IN: cursors.tests
 
-[ 2 t ] [ { 2 3 } [ even? ] find ] unit-test
-[ 3 t ] [ { 2 3 } [ odd? ] find ] unit-test
-[ f f ] [ { 2 4 } [ odd? ] find ] unit-test
+[ { 1 2 3 4 } ] [
+    [ T{ linear-cursor f 1 1 } T{ linear-cursor f 5 1 } [ value>> , ] -each ]
+    { } make
+] unit-test
 
-[ { 2 3 } ] [ { 1 2 } [ 1 + ] map ] unit-test
-[ { 2 3 } ] [ { 1 2 } [ [ 1 + , ] each ] { 2 3 } make ] unit-test
+[ T{ linear-cursor f 3 1 } ] [
+    T{ linear-cursor f 1 1 } T{ linear-cursor f 5 1 } [ value>> 3 mod zero? ] -find
+] unit-test
 
-[ t ] [ { } [ odd? ] all? ] unit-test
-[ t ] [ { 1 3 5 } [ odd? ] all? ] unit-test
-[ f ] [ { 1 3 5 6 } [ odd? ] all? ] unit-test
+[ { 1 3 } ] [
+    [ T{ linear-cursor f 1 2 } T{ linear-cursor f 5 2 } [ value>> , ] -each ]
+    { } make
+] unit-test
 
-[ t ] [ { } [ odd? ] all? ] unit-test
-[ t ] [ { 1 3 5 } [ odd? ] any? ] unit-test
-[ f ] [ { 2 4 6 } [ odd? ] any? ] unit-test
+[ B{ 1 2 3 4 5 } ] [ [ { 1 2 3 4 5 } [ , ] each ] B{ } make ] unit-test
+[ B{ } ] [ [ { } [ , ] each ] B{ } make ] unit-test
+[ { 2 4 6 8 10 } ] [ { 1 2 3 4 5 } [ 2 * ] map ] unit-test
 
-[ { 1 3 5 } ] [ { 1 2 3 4 5 6 } [ odd? ] filter ] unit-test
+[ { "roses: lutefisk" "tulips: lox" } ]
+[
+    [
+        { { "roses" "lutefisk" } { "tulips" "lox" } }
+        [ ": " glue , ] assoc-each
+    ] { } make
+] unit-test
 
-[ { } ]
-[ { 1 2 } { } [ + ] 2map ] unit-test
+[ { "roses: lutefisk" "tulips: lox" } ]
+[
+    { { "roses" "lutefisk" } { "tulips" "lox" } }
+    [ ": " glue ] { } assoc>map
+] unit-test
 
-[ { 11 } ]
-[ { 1 2 } { 10 } [ + ] 2map ] unit-test
+[ { "roses: lutefisk" "tulips: lox" } ]
+[
+    [
+        H{ { "roses" "lutefisk" } { "tulips" "lox" } }
+        [ ": " glue , ] assoc-each
+    ] { } make natural-sort
+] unit-test
 
-[ { 11 22 } ]
-[ { 1 2 } { 10 20 } [ + ] 2map ] unit-test
+[ { "roses: lutefisk" "tulips: lox" } ]
+[
+    H{ { "roses" "lutefisk" } { "tulips" "lox" } }
+    [ ": " glue ] { } assoc>map natural-sort
+] unit-test
 
-[ { } ]
-[ { 1 2 } { } { } [ + + ] 3map ] unit-test
+: compile-test-each ( xs -- )
+    [ , ] each ;
 
-[ { 111 } ]
-[ { 1 2 } { 10 } { 100 200 } [ + + ] 3map ] unit-test
+: compile-test-map ( xs -- ys )
+    [ 2 * ] map ;
 
-[ { 111 222 } ]
-[ { 1 2 } { 10 20 } { 100 200 } [ + + ] 3map ] unit-test
+: compile-test-assoc-each ( xs -- )
+    [ ": " glue , ] assoc-each ;
 
-: test-3map ( -- seq )
-     { 1 2 } { 10 20 } { 100 200 } [ + + ] 3map ;
+: compile-test-assoc>map ( xs -- ys )
+    [ ": " glue ] { } assoc>map ;
+
+[ B{ 1 2 3 4 5 } ] [ [ { 1 2 3 4 5 } compile-test-each ] B{ } make ] unit-test
+[ { 2 4 6 8 10 } ] [ { 1 2 3 4 5 } compile-test-map ] unit-test
+
+[ { "roses: lutefisk" "tulips: lox" } ]
+[ [ { { "roses" "lutefisk" } { "tulips" "lox" } } compile-test-assoc-each ] { } make ] unit-test
+
+[ { "roses: lutefisk" "tulips: lox" } ]
+[ { { "roses" "lutefisk" } { "tulips" "lox" } } compile-test-assoc>map ] unit-test
 
-[ { 111 222 } ] [ test-3map ] unit-test
index 77defb081d952a977e2a11f73ed1e183ed7ebb1f..d7fe5fb893b4ec0412fd5ace29c2a6cece411070 100644 (file)
-! Copyright (C) 2009 Slava Pestov, Doug Coleman.
-! See http://factorcode.org/license.txt for BSD license.
-USING: accessors arrays generalizations kernel math sequences
-sequences.private fry ;
+! (c)2010 Joe Groff bsd license
+USING: accessors arrays assocs combinators.short-circuit fry
+hashtables kernel locals macros math math.functions math.order
+generalizations sequences ;
+FROM: sequences.private => nth-unsafe set-nth-unsafe ;
+FROM: hashtables.private => tombstone? ;
 IN: cursors
 
-GENERIC: cursor-done? ( cursor -- ? )
-GENERIC: cursor-get-unsafe ( cursor -- obj )
-GENERIC: cursor-advance ( cursor -- )
+!
+! basic cursor protocol
+!
+
+MIXIN: cursor
+
+GENERIC: cursor-compatible? ( cursor cursor -- ? )
 GENERIC: cursor-valid? ( cursor -- ? )
-GENERIC: cursor-write ( obj cursor -- )
+GENERIC: cursor= ( cursor cursor -- ? )
+GENERIC: cursor<= ( cursor cursor -- ? )
+GENERIC: cursor>= ( cursor cursor -- ? )
+GENERIC: cursor-distance-hint ( cursor cursor -- n )
+
+M: cursor cursor<= cursor= ; inline
+M: cursor cursor>= cursor= ; inline
+M: cursor cursor-distance-hint 2drop 0 ; inline
+
+!
+! cursor iteration
+!
+
+MIXIN: forward-cursor
+INSTANCE: forward-cursor cursor
+
+GENERIC: inc-cursor ( cursor -- cursor' )
+
+MIXIN: bidirectional-cursor
+INSTANCE: bidirectional-cursor forward-cursor
+
+GENERIC: dec-cursor ( cursor -- cursor' )
+
+MIXIN: random-access-cursor
+INSTANCE: random-access-cursor bidirectional-cursor
+
+GENERIC# cursor+ 1 ( cursor n -- cursor' )
+GENERIC# cursor- 1 ( cursor n -- cursor' )
+GENERIC: cursor-distance ( cursor cursor -- n )
+GENERIC: cursor<  ( cursor cursor -- ? )
+GENERIC: cursor>  ( cursor cursor -- ? )
+
+M: random-access-cursor inc-cursor  1 cursor+ ; inline
+M: random-access-cursor dec-cursor -1 cursor+ ; inline
+M: random-access-cursor cursor- neg cursor+ ; inline
+M: random-access-cursor cursor<= { [ cursor= ] [ cursor< ] } 2|| ; inline
+M: random-access-cursor cursor>= { [ cursor= ] [ cursor> ] } 2|| ; inline
+M: random-access-cursor cursor-distance-hint cursor-distance ; inline
+
+!
+! input cursors
+!
+
+ERROR: invalid-cursor cursor ;
+
+MIXIN: input-cursor
+
+GENERIC: cursor-value ( cursor -- value )
+<PRIVATE
+GENERIC: cursor-value-unsafe ( cursor -- value )
+PRIVATE>
+M: input-cursor cursor-value-unsafe cursor-value ; inline
+M: input-cursor cursor-value
+    dup cursor-valid? [ cursor-value-unsafe ] [ invalid-cursor ] if ; inline
+
+!
+! output cursors
+!
+
+MIXIN: output-cursor
+
+GENERIC: set-cursor-value ( value cursor -- )
+<PRIVATE
+GENERIC: set-cursor-value-unsafe ( value cursor -- )
+PRIVATE>
+M: output-cursor set-cursor-value-unsafe set-cursor-value ; inline
+M: output-cursor set-cursor-value
+    dup cursor-valid? [ set-cursor-value-unsafe ] [ invalid-cursor ] if ; inline
+
+!
+! stream cursors
+!
+
+MIXIN: stream-cursor
+INSTANCE: stream-cursor forward-cursor
+
+M: stream-cursor cursor-compatible? 2drop f ; inline
+M: stream-cursor cursor-valid? drop t ; inline
+M: stream-cursor cursor= 2drop f ; inline
+
+MIXIN: infinite-stream-cursor
+INSTANCE: infinite-stream-cursor stream-cursor
+
+M: infinite-stream-cursor inc-cursor ; inline
+
+MIXIN: finite-stream-cursor
+INSTANCE: finite-stream-cursor stream-cursor
+
+SINGLETON: end-of-stream
+
+GENERIC: cursor-stream-ended? ( cursor -- ? )
+
+M: finite-stream-cursor inc-cursor
+    dup cursor-stream-ended? [ drop end-of-stream ] when ; inline
+
+INSTANCE: end-of-stream finite-stream-cursor
+
+M: end-of-stream cursor-compatible? drop finite-stream-cursor? ; inline
+M: end-of-stream cursor-valid? drop f ; inline
+M: end-of-stream cursor= eq? ; inline
+M: end-of-stream inc-cursor ; inline
+M: end-of-stream cursor-stream-ended? drop t ; inline
+
+!
+! basic iterators
+!
+
+: -each ( ... begin end quot: ( ... cursor -- ... ) -- ... )
+    [ '[ dup _ cursor>= ] ]
+    [ '[ _ keep inc-cursor ] ] bi* until drop ; inline
+
+: -find ( ... begin end quot: ( ... cursor -- ... ? ) -- ... cursor )
+    '[ dup _ cursor>= [ t ] [ dup @ ] if ] [ inc-cursor ] until ; inline
+
+: -in- ( quot -- quot' )
+    '[ cursor-value-unsafe @ ] ; inline
+
+: -out- ( quot -- quot' )
+    '[ _ keep set-cursor-value-unsafe ] ; inline
+
+: -out ( ... begin end quot: ( ... cursor -- ... value ) -- ... )
+    -out- -each ; inline
+
+!
+! numeric cursors
+!
+
+TUPLE: numeric-cursor
+    { value read-only } ;
+
+M: numeric-cursor cursor-valid? drop t ; inline
+
+M: numeric-cursor cursor=  [ value>> ] bi@ =  ; inline
+
+M: numeric-cursor cursor<= [ value>> ] bi@ <= ; inline
+M: numeric-cursor cursor<  [ value>> ] bi@ <  ; inline
+M: numeric-cursor cursor>  [ value>> ] bi@ >  ; inline
+M: numeric-cursor cursor>= [ value>> ] bi@ >= ; inline
+
+INSTANCE: numeric-cursor input-cursor
+
+M: numeric-cursor cursor-value value>> ; inline
+
+!
+! linear cursor
+!
+
+TUPLE: linear-cursor < numeric-cursor
+    { delta read-only } ;
+C: <linear-cursor> linear-cursor
+
+INSTANCE: linear-cursor random-access-cursor
+
+M: linear-cursor cursor-compatible?
+    [ linear-cursor? ] both? ; inline
+
+M: linear-cursor inc-cursor
+    [ value>> ] [ delta>> ] bi [ + ] keep <linear-cursor> ; inline
+M: linear-cursor dec-cursor
+    [ value>> ] [ delta>> ] bi [ - ] keep <linear-cursor> ; inline
+M: linear-cursor cursor+
+    [ [ value>> ] [ delta>> ] bi ] dip [ * + ] keep <linear-cursor> ; inline
+M: linear-cursor cursor-
+    [ [ value>> ] [ delta>> ] bi ] dip [ * - ] keep <linear-cursor> ; inline
+
+GENERIC: up/i ( distance delta -- distance' )
+M: integer up/i [ 1 - + ] keep /i ; inline
+M: real up/i / ceiling >integer ; inline
+
+M: linear-cursor cursor-distance
+    [ [ value>> ] bi@ - ] [ nip delta>> ] 2bi up/i ; inline
+
+!
+! quadratic cursor
+!
+
+TUPLE: quadratic-cursor < numeric-cursor
+    { delta read-only }
+    { delta2 read-only } ;
+
+C: <quadratic-cursor> quadratic-cursor
+
+INSTANCE: quadratic-cursor bidirectional-cursor
+
+M: quadratic-cursor cursor-compatible?
+    [ linear-cursor? ] both? ; inline
+
+M: quadratic-cursor inc-cursor
+    [ value>> ] [ delta>> [ + ] keep ] [ delta2>> [ + ] keep ] tri <quadratic-cursor> ; inline
+
+M: quadratic-cursor dec-cursor
+    [ value>> ] [ delta>> ] [ delta2>> ] tri [ - [ - ] keep ] keep <quadratic-cursor> ; inline
+
+!
+! collections
+!
+
+MIXIN: collection
+
+GENERIC: begin-cursor ( collection -- cursor )
+GENERIC: end-cursor ( collection -- cursor )
+
+: all ( collection -- begin end )
+    [ begin-cursor ] [ end-cursor ] bi ; inline
+
+: all- ( collection quot -- begin end quot )
+    [ all ] dip ; inline
+
+!
+! containers
+!
+
+MIXIN: container
+INSTANCE: container collection
+
+: in- ( container quot -- begin end quot' )
+    all- -in- ; inline
+
+: each ( ... container quot: ( ... x -- ... ) -- ... ) in- -each ; inline
+
+INSTANCE: finite-stream-cursor container
+
+M: finite-stream-cursor begin-cursor ; inline
+M: finite-stream-cursor end-cursor drop end-of-stream ; inline
+
+!
+! sequence cursor
+!
+
+TUPLE: sequence-cursor
+    { seq read-only }
+    { n fixnum read-only } ;
+C: <sequence-cursor> sequence-cursor
+    
+INSTANCE: sequence container
+
+M: sequence begin-cursor 0 <sequence-cursor> ; inline
+M: sequence end-cursor dup length <sequence-cursor> ; inline
+
+INSTANCE: sequence-cursor random-access-cursor
+
+M: sequence-cursor cursor-compatible?
+    {
+        [ [ sequence-cursor? ] both? ]
+        [ [ seq>> ] bi@ eq? ]
+    } 2&& ; inline
+
+M: sequence-cursor cursor-valid?
+    [ n>> ] [ seq>> ] bi bounds-check? ; inline
+
+M: sequence-cursor cursor=  [ n>> ] bi@ =  ; inline
+M: sequence-cursor cursor<= [ n>> ] bi@ <= ; inline
+M: sequence-cursor cursor>= [ n>> ] bi@ >= ; inline
+M: sequence-cursor cursor<  [ n>> ] bi@ <  ; inline
+M: sequence-cursor cursor>  [ n>> ] bi@ >  ; inline
+M: sequence-cursor inc-cursor [ seq>> ] [ n>> ] bi 1 + <sequence-cursor> ; inline
+M: sequence-cursor dec-cursor [ seq>> ] [ n>> ] bi 1 - <sequence-cursor> ; inline
+M: sequence-cursor cursor+ [ [ seq>> ] [ n>> ] bi ] dip + <sequence-cursor> ; inline
+M: sequence-cursor cursor- [ [ seq>> ] [ n>> ] bi ] dip - <sequence-cursor> ; inline
+M: sequence-cursor cursor-distance ( cursor cursor -- n )
+    [ n>> ] bi@ - ; inline
+
+INSTANCE: sequence-cursor input-cursor
+
+M: sequence-cursor cursor-value-unsafe [ n>> ] [ seq>> ] bi nth-unsafe ; inline
+M: sequence-cursor cursor-value [ n>> ] [ seq>> ] bi nth ; inline
+
+INSTANCE: sequence-cursor output-cursor
+
+M: sequence-cursor set-cursor-value-unsafe [ n>> ] [ seq>> ] bi set-nth-unsafe ; inline
+M: sequence-cursor set-cursor-value [ n>> ] [ seq>> ] bi set-nth ; inline
+
+!
+! map cursor
+!
+
+TUPLE: map-cursor
+    { from read-only }
+    { to read-only } ;
+C: <map-cursor> map-cursor
+
+INSTANCE: map-cursor forward-cursor
+
+M: map-cursor cursor-compatible? [ from>> ] bi@ cursor-compatible? ; inline
+M: map-cursor cursor-valid? [ from>> ] [ to>> ] bi [ cursor-valid? ] both? ; inline
+M: map-cursor cursor= [ from>> ] bi@ cursor= ; inline
+M: map-cursor inc-cursor [ from>> inc-cursor ] [ to>> inc-cursor ] bi <map-cursor> ; inline
+
+INSTANCE: map-cursor output-cursor
+
+M: map-cursor set-cursor-value-unsafe to>> set-cursor-value-unsafe ; inline
+M: map-cursor set-cursor-value        to>> set-cursor-value        ; inline
+
+: -map- ( begin end quot to -- begin' end' quot' )
+    swap [ '[ _ <map-cursor> ] bi@ ] dip '[ from>> @ ] -out- ; inline
+
+: -map ( begin end quot to -- begin' end' quot' )
+    -map- -each ; inline
+
+!
+! pusher cursor
+!
+
+TUPLE: pusher-cursor
+    { growable read-only } ;
+C: <pusher-cursor> pusher-cursor
+
+INSTANCE: pusher-cursor infinite-stream-cursor
+INSTANCE: pusher-cursor output-cursor
+
+M: pusher-cursor set-cursor-value growable>> push ; inline
+
+!
+! Create cursors into new sequences
+!
+
+: new-growable-cursor ( begin end exemplar -- cursor result )
+    [ swap cursor-distance-hint ] dip new-resizable [ <pusher-cursor> ] keep ; inline
+
+GENERIC# new-sequence-cursor 1 ( begin end exemplar -- cursor result )
+
+M: random-access-cursor new-sequence-cursor
+    [ swap cursor-distance ] dip new-sequence [ begin-cursor ] keep ; inline
+M: forward-cursor new-sequence-cursor
+    new-growable-cursor ; inline
+
+: -into-sequence- ( begin end quot exemplar -- begin' end' quot' cursor result )
+    [ 2over ] dip new-sequence-cursor ; inline
+
+: -into-growable- ( begin end quot exemplar -- begin' end' quot' cursor result )
+    [ 2over ] dip new-growable-cursor ; inline
+
+!
+! map combinators
+!
+
+! XXX generalize exemplar
+: -map-as ( ... begin end quot: ( ... cursor -- ... value ) exemplar -- ... newseq )
+    [ -into-sequence- [ -map ] dip ] keep like ; inline
+
+: map! ( ... container quot: ( ... x -- ... newx ) -- ... container )
+    [ in- -out ] keep ; inline
+: map-as ( ... container quot: ( ... x -- ... newx ) exemplar -- ... newseq )
+    [ in- ] dip -map-as ; inline
+: map ( ... container quot: ( ... x -- ... newx ) -- ... newcontainer )
+    over map-as ; inline
+
+!
+! assoc cursors
+!
+
+MIXIN: assoc-cursor
+
+GENERIC: cursor-key-value ( cursor -- key value )
+
+: -assoc- ( quot -- quot' )
+    '[ cursor-key-value @ ] ; inline
+
+: assoc- ( assoc quot -- begin end quot' )
+    all- -assoc- ; inline
+
+: assoc-each ( ... assoc quot: ( ... k v -- ... ) -- ... )
+    assoc- -each ; inline
+: assoc>map ( ... assoc quot: ( ... k v -- ... newx ) exemplar -- ... newcontainer )
+    [ assoc- ] dip -map-as ; inline
+
+INSTANCE: input-cursor assoc-cursor
+
+M: input-cursor cursor-key-value
+    cursor-value-unsafe first2 ; inline
+
+!
+! hashtable cursor
+!
 
-ERROR: cursor-ended cursor ;
+TUPLE: hashtable-cursor
+    { hashtable hashtable read-only }
+    { n fixnum read-only } ;
+<PRIVATE
+C: <hashtable-cursor> hashtable-cursor
+PRIVATE>
 
-: cursor-get ( cursor -- obj )
-    dup cursor-done?
-    [ cursor-ended ] [ cursor-get-unsafe ] if ; inline
+INSTANCE: hashtable-cursor forward-cursor
 
-: find-done? ( cursor quot -- ? )
-    over cursor-done?
-    [ 2drop t ] [ [ cursor-get-unsafe ] dip call ] if ; inline
+M: hashtable-cursor cursor-compatible?
+    {
+        [ [ hashtable-cursor? ] both? ]
+        [ [ hashtable>> ] bi@ eq? ]
+    } 2&& ; inline
 
-: cursor-until ( cursor quot -- )
-    [ find-done? not ]
-    [ drop cursor-advance ] bi-curry bi-curry while ; inline
-: cursor-each ( cursor quot -- )
-    [ f ] compose cursor-until ; inline
+M: hashtable-cursor cursor-valid? ( cursor -- ? )
+    [ n>> ] [ hashtable>> array>> ] bi bounds-check? ; inline
 
-: cursor-find ( cursor quot -- obj ? )
-    [ cursor-until ] [ drop ] 2bi
-    dup cursor-done? [ drop f f ] [ cursor-get t ] if ; inline
+M: hashtable-cursor cursor= ( cursor cursor -- ? )
+    [ n>> ] bi@ = ; inline
+M: hashtable-cursor cursor-distance-hint ( cursor cursor -- n )
+    nip hashtable>> assoc-size ; inline
 
-: cursor-any? ( cursor quot -- ? )
-    cursor-find nip ; inline
+<PRIVATE
+: (inc-hashtable-cursor) ( array n -- n' )
+    [ 2dup swap { [ length < ] [ nth-unsafe tombstone? ] } 2&& ] [ 2 + ] while nip ; inline
+PRIVATE>
 
-: cursor-all? ( cursor quot -- ? )
-    [ not ] compose cursor-any? not ; inline
+M: hashtable-cursor inc-cursor ( cursor -- cursor' )
+    [ hashtable>> dup array>> ] [ n>> 2 + ] bi
+    (inc-hashtable-cursor) <hashtable-cursor> ; inline
 
-: cursor-map-quot ( quot to -- quot' )
-    [ [ call ] dip cursor-write ] 2curry ; inline
+INSTANCE: hashtable-cursor assoc-cursor
+    
+M: hashtable-cursor cursor-key-value
+    [ n>> ] [ hashtable>> array>> ] bi
+    [ nth-unsafe ] [ [ 1 + ] dip nth-unsafe ] 2bi ; inline
 
-: cursor-map ( from to quot -- )
-    swap cursor-map-quot cursor-each ; inline
+INSTANCE: hashtable-cursor input-cursor
 
-: cursor-write-if ( obj quot to -- )
-    [ over [ call ] dip ] dip
-    [ cursor-write ] 2curry when ; inline
+M: hashtable-cursor cursor-value-unsafe
+    cursor-key-value 2array ; inline
 
-: cursor-filter-quot ( quot to -- quot' )
-    [ cursor-write-if ] 2curry ; inline
+INSTANCE: hashtable container
 
-: cursor-filter ( from to quot -- )
-    swap cursor-filter-quot cursor-each ; inline
+M: hashtable begin-cursor
+    dup array>> 0 (inc-hashtable-cursor) <hashtable-cursor> ; inline
+M: hashtable end-cursor
+    dup array>> length <hashtable-cursor> ; inline
 
-TUPLE: from-sequence { seq sequence } { n integer } ;
+!
+! zip cursor
+!
 
-: >from-sequence< ( from-sequence -- n seq )
-    [ n>> ] [ seq>> ] bi ; inline
+TUPLE: zip-cursor
+    { keys   read-only }
+    { values read-only } ;
+C: <zip-cursor> zip-cursor
 
-M: from-sequence cursor-done? ( cursor -- ? )
-    >from-sequence< length >= ;
+INSTANCE: zip-cursor forward-cursor
 
-M: from-sequence cursor-valid?
-    >from-sequence< bounds-check? not ;
+M: zip-cursor cursor-compatible? ( cursor cursor -- ? )
+    {
+        [ [ zip-cursor? ] both? ]
+        [ [ keys>> ] bi@ cursor-compatible? ]
+        [ [ values>> ] bi@ cursor-compatible? ]
+    } 2&& ; inline
 
-M: from-sequence cursor-get-unsafe
-    >from-sequence< nth-unsafe ;
+M: zip-cursor cursor-valid? ( cursor -- ? )
+    [ keys>> ] [ values>> ] bi [ cursor-valid? ] both? ; inline
+M: zip-cursor cursor= ( cursor cursor -- ? )
+    {
+        [ [ keys>> ] bi@ cursor= ]
+        [ [ values>> ] bi@ cursor= ]
+    } 2|| ; inline
 
-M: from-sequence cursor-advance
-    [ 1 + ] change-n drop ;
+M: zip-cursor cursor-distance-hint ( cursor cursor -- n )
+    [ [ keys>> ] bi@ cursor-distance-hint ]
+    [ [ values>> ] bi@ cursor-distance-hint ] 2bi max ; inline
 
-: >input ( seq -- cursor )
-    0 from-sequence boa ; inline
+M: zip-cursor inc-cursor ( cursor -- cursor' )
+    [ keys>> inc-cursor ] [ values>> inc-cursor ] bi <zip-cursor> ; inline
+    
+INSTANCE: zip-cursor assoc-cursor
 
-: iterate ( seq quot iterator -- )
-    [ >input ] 2dip call ; inline
+M: zip-cursor cursor-key-value
+    [ keys>> cursor-value-unsafe ] [ values>> cursor-value-unsafe ] bi ; inline
 
-: each ( seq quot -- ) [ cursor-each ] iterate ; inline
-: find ( seq quot -- ? ) [ cursor-find ] iterate ; inline
-: any? ( seq quot -- ? ) [ cursor-any? ] iterate ; inline
-: all? ( seq quot -- ? ) [ cursor-all? ] iterate ; inline
+: zip-cursors ( a-begin a-end b-begin b-end -- begin end )
+    [ <zip-cursor> ] bi-curry@ bi* ; inline
 
-TUPLE: to-sequence { seq sequence } { exemplar sequence } ;
+: 2all ( a b -- begin end )
+    [ all ] bi@ zip-cursors ; inline
 
-M: to-sequence cursor-write
-    seq>> push ;
+: 2all- ( a b quot -- begin end quot )
+    [ 2all ] dip ; inline
 
-: freeze ( cursor -- seq )
-    [ seq>> ] [ exemplar>> ] bi like ; inline
+ALIAS: -2in- -assoc-
 
-: >output ( seq -- cursor )
-    [ [ length ] keep new-resizable ] keep
-    to-sequence boa ; inline
+: 2in- ( a b quot -- begin end quot' )
+    2all- -2in- ; inline
 
-: transform ( seq quot transformer -- newseq )
-    [ [ >input ] [ >output ] bi ] 2dip
-    [ call ]
-    [ 2drop freeze ] 3bi ; inline
+: 2each ( ... a b quot: ( ... x y -- ... ) -- ... )
+    2in- -each ; inline
 
-: map ( seq quot -- ) [ cursor-map ] transform ; inline
-: filter ( seq quot -- newseq ) [ cursor-filter ] transform ; inline
+: 2map-as ( ... a b quot: ( ... x y -- ... z ) exemplar -- ... c )
+    [ 2in- ] dip -map-as ; inline
 
-: find-done2? ( cursor cursor quot -- ? )
-    2over [ cursor-done? ] either?
-    [ 3drop t ] [ [ [ cursor-get-unsafe ] bi@ ] dip call ] if ; inline
+: 2map ( ... a b quot: ( ... x y -- ... z ) -- ... c )
+    pick 2map-as ; inline 
 
-: cursor-until2 ( cursor cursor quot -- )
-    [ find-done2? not ]
-    [ drop [ cursor-advance ] bi@ ] bi-curry bi-curry bi-curry while ; inline
+!
+! generalized zips
+!
 
-: cursor-each2 ( cursor cursor quot -- )
-    [ f ] compose cursor-until2 ; inline
+: -unzip- ( quot -- quot' )
+    '[ [ keys>> cursor-value-unsafe ] [ values>> ] bi @ ] ; inline
 
-: cursor-map2 ( from to quot -- )
-    swap cursor-map-quot cursor-each2 ; inline
+MACRO: nzip-cursors ( n -- ) 1 - [ zip-cursors ] n*quot ;
 
-: iterate2 ( seq1 seq2 quot iterator -- )
-    [ [ >input ] bi@ ] 2dip call ; inline
+: nall ( seqs... n -- begin end ) [ [ all ] swap napply ] [ nzip-cursors ] bi ; inline
 
-: transform2 ( seq1 seq2 quot transformer -- newseq )
-    [ over >output [ [ >input ] [ >input ] bi* ] dip ] 2dip
-    [ call ]
-    [ 2drop nip freeze ] 4 nbi ; inline
+: nall- ( seqs... quot n -- begin end quot ) swap [ nall ] dip ; inline
 
-: 2each ( seq1 seq2 quot -- ) [ cursor-each2 ] iterate2 ; inline
-: 2map ( seq1 seq2 quot -- ) [ cursor-map2 ] transform2 ; inline
+MACRO: -nin- ( n -- )
+    1 - [ -unzip- ] n*quot [ -in- ] prepend ;
 
-: find-done3? ( cursor1 cursor2 cursor3 quot -- ? )
-    [ 3 ndrop t ] swap '[ [ cursor-get-unsafe ] tri@ @ ]
-    [ 3 ndup 3 narray [ cursor-done? ] any? ] 2dip if ; inline
+: nin- ( seqs... quot n -- begin end quot ) [ nall- ] [ -nin- ] bi ; inline
 
-: cursor-until3 ( cursor cursor quot -- )
-    [ find-done3? not ]
-    [ drop [ cursor-advance ] tri@ ]
-    bi-curry bi-curry bi-curry bi-curry while ; inline
+: neach ( seqs... quot n -- ) nin- -each ; inline
+: nmap-as ( seqs... quot exemplar n -- newseq )
+    swap [ nin- ] dip -map-as ; inline
+: nmap ( seqs... quot n -- newseq )
+    dup [ npick ] curry [ dip swap ] curry dip nmap-as ; inline
 
-: cursor-each3 ( cursor cursor quot -- )
-    [ f ] compose cursor-until3 ; inline
+!
+! utilities
+!
 
-: cursor-map3 ( from to quot -- )
-    swap cursor-map-quot cursor-each3 ; inline
+: -with- ( invariant begin end quot -- begin end quot' )
+    [ rot ] dip '[ [ _ ] dip @ ] ; inline
 
-: iterate3 ( seq1 seq2 seq3 quot iterator -- )
-    [ [ >input ] tri@ ] 2dip call ; inline
+: -2with- ( invariant invariant begin end quot -- begin end quot' )
+    -with- -with- ; inline
 
-: transform3 ( seq1 seq2 seq3 quot transformer -- newseq )
-    [ pick >output [ [ >input ] [ >input ] [ >input ] tri* ] dip ] 2dip
-    [ call ]
-    [ 2drop 2nip freeze ] 5 nbi ; inline
+MACRO: -nwith- ( n -- )
+    [ -with- ] n*quot ;
 
-: 3each ( seq1 seq2 seq3 quot -- ) [ cursor-each3 ] iterate3 ; inline
-: 3map ( seq1 seq2 seq3 quot -- ) [ cursor-map3 ] transform3 ; inline
diff --git a/extra/elf/authors.txt b/extra/elf/authors.txt
new file mode 100644 (file)
index 0000000..6f03a12
--- /dev/null
@@ -0,0 +1 @@
+Erik Charlebois
diff --git a/extra/elf/elf.factor b/extra/elf/elf.factor
new file mode 100644 (file)
index 0000000..2ad82bc
--- /dev/null
@@ -0,0 +1,458 @@
+! Copyright (C) 2010 Erik Charlebois.
+! See http://factorcode.org/license.txt for BSD license.
+USING: alien.c-types alien.syntax classes.struct ;
+IN: elf
+
+CONSTANT: EI_NIDENT 16
+CONSTANT: EI_MAG0       0
+CONSTANT: EI_MAG1       1
+CONSTANT: EI_MAG2       2
+CONSTANT: EI_MAG3       3
+CONSTANT: EI_CLASS      4
+CONSTANT: EI_DATA       5
+CONSTANT: EI_VERSION    6
+CONSTANT: EI_OSABI      7
+CONSTANT: EI_ABIVERSION 8
+CONSTANT: EI_PAD        9
+
+CONSTANT: ELFMAG0       HEX: 7f
+CONSTANT: ELFMAG1       HEX: 45
+CONSTANT: ELFMAG2       HEX: 4c
+CONSTANT: ELFMAG3       HEX: 46
+
+CONSTANT: ELFCLASS32 1
+CONSTANT: ELFCLASS64 2
+
+CONSTANT: ELFDATA2LSB 1
+CONSTANT: ELFDATA2MSB 2
+
+CONSTANT: ELFOSABI_SYSV       0
+CONSTANT: ELFOSABI_HPUX       1
+CONSTANT: ELFOSABI_NETBSD     2
+CONSTANT: ELFOSABI_LINUX      3
+CONSTANT: ELFOSABI_SOLARIS    6
+CONSTANT: ELFOSABI_AIX        7
+CONSTANT: ELFOSABI_IRIX       8
+CONSTANT: ELFOSABI_FREEBSD    9
+CONSTANT: ELFOSABI_TRU64      10
+CONSTANT: ELFOSABI_MODESTO    11
+CONSTANT: ELFOSABI_OPENBSD    12
+CONSTANT: ELFOSABI_OPENVMS    13
+CONSTANT: ELFOSABI_NSK        14
+CONSTANT: ELFOSABI_AROS       15
+CONSTANT: ELFOSABI_ARM_AEABI  64
+CONSTANT: ELFOSABI_ARM        97
+CONSTANT: ELFOSABI_STANDALONE 255
+
+CONSTANT: ET_NONE   0
+CONSTANT: ET_REL    1
+CONSTANT: ET_EXEC   2
+CONSTANT: ET_DYN    3
+CONSTANT: ET_CORE   4
+CONSTANT: ET_LOOS   HEX: FE00
+CONSTANT: ET_HIOS   HEX: FEFF
+CONSTANT: ET_LOPROC HEX: FF00
+CONSTANT: ET_HIPROC HEX: FFFF
+
+CONSTANT: EM_NONE         0
+CONSTANT: EM_M32          1
+CONSTANT: EM_SPARC        2
+CONSTANT: EM_386          3
+CONSTANT: EM_68K          4
+CONSTANT: EM_88K          5
+CONSTANT: EM_486          6
+CONSTANT: EM_860          7
+CONSTANT: EM_MIPS         8
+CONSTANT: EM_S370         9
+CONSTANT: EM_MIPS_RS3_LE  10
+CONSTANT: EM_SPARC64      11
+CONSTANT: EM_PARISC       15
+CONSTANT: EM_VPP500       17
+CONSTANT: EM_SPARC32PLUS  18
+CONSTANT: EM_960          19
+CONSTANT: EM_PPC          20
+CONSTANT: EM_PPC64        21
+CONSTANT: EM_S390         22
+CONSTANT: EM_SPU          23
+CONSTANT: EM_V800         36
+CONSTANT: EM_FR20         37
+CONSTANT: EM_RH32         38
+CONSTANT: EM_RCE          39
+CONSTANT: EM_ARM          40
+CONSTANT: EM_ALPHA        41
+CONSTANT: EM_SH           42
+CONSTANT: EM_SPARCV9      43
+CONSTANT: EM_TRICORE      44
+CONSTANT: EM_ARC          45
+CONSTANT: EM_H8_300       46
+CONSTANT: EM_H8_300H      47
+CONSTANT: EM_H8S          48
+CONSTANT: EM_H8_500       49
+CONSTANT: EM_IA_64        50
+CONSTANT: EM_MIPS_X       51
+CONSTANT: EM_COLDFIRE     52
+CONSTANT: EM_68HC12       53
+CONSTANT: EM_MMA          54
+CONSTANT: EM_PCP          55
+CONSTANT: EM_NCPU         56
+CONSTANT: EM_NDR1         57
+CONSTANT: EM_STARCORE     58
+CONSTANT: EM_ME16         59
+CONSTANT: EM_ST100        60
+CONSTANT: EM_TINYJ        61
+CONSTANT: EM_X86_64       62
+CONSTANT: EM_PDSP         63
+CONSTANT: EM_FX66         66
+CONSTANT: EM_ST9PLUS      67
+CONSTANT: EM_ST7          68
+CONSTANT: EM_68HC16       69
+CONSTANT: EM_68HC11       70
+CONSTANT: EM_68HC08       71
+CONSTANT: EM_68HC05       72
+CONSTANT: EM_SVX          73
+CONSTANT: EM_ST19         74
+CONSTANT: EM_VAX          75
+CONSTANT: EM_CRIS         76
+CONSTANT: EM_JAVELIN      77
+CONSTANT: EM_FIREPATH     78
+CONSTANT: EM_ZSP          79
+CONSTANT: EM_MMIX         80
+CONSTANT: EM_HUANY        81
+CONSTANT: EM_PRISM        82
+CONSTANT: EM_AVR          83
+CONSTANT: EM_FR30         84
+CONSTANT: EM_D10V         85
+CONSTANT: EM_D30V         86
+CONSTANT: EM_V850         87
+CONSTANT: EM_M32R         88
+CONSTANT: EM_MN10300      89
+CONSTANT: EM_MN10200      90
+CONSTANT: EM_PJ           91
+CONSTANT: EM_OPENRISC     92
+CONSTANT: EM_ARC_A5       93
+CONSTANT: EM_XTENSA       94
+CONSTANT: EM_VIDEOCORE    95
+CONSTANT: EM_TMM_GPP      96
+CONSTANT: EM_NS32K        97
+CONSTANT: EM_TPC          98
+CONSTANT: EM_SNP1K        99
+CONSTANT: EM_ST200        100
+CONSTANT: EM_IP2K         101
+CONSTANT: EM_MAX          102
+CONSTANT: EM_CR           103
+CONSTANT: EM_F2MC16       104
+CONSTANT: EM_MSP430       105
+CONSTANT: EM_BLACKFIN     106
+CONSTANT: EM_SE_C33       107
+CONSTANT: EM_SEP          108
+CONSTANT: EM_ARCA         109
+CONSTANT: EM_UNICORE      110
+
+CONSTANT: EV_NONE    0
+CONSTANT: EV_CURRENT 1
+
+CONSTANT: EF_ARM_EABIMASK HEX: ff000000
+CONSTANT: EF_ARM_BE8      HEX: 00800000
+
+CONSTANT: SHN_UNDEF  HEX: 0000
+CONSTANT: SHN_LOPROC HEX: FF00
+CONSTANT: SHN_HIPROC HEX: FF1F
+CONSTANT: SHN_LOOS   HEX: FF20
+CONSTANT: SHN_HIOS   HEX: FF3F
+CONSTANT: SHN_ABS    HEX: FFF1
+CONSTANT: SHN_COMMON HEX: FFF2
+
+CONSTANT: SHT_NULL               0
+CONSTANT: SHT_PROGBITS           1
+CONSTANT: SHT_SYMTAB             2
+CONSTANT: SHT_STRTAB             3
+CONSTANT: SHT_RELA               4
+CONSTANT: SHT_HASH               5
+CONSTANT: SHT_DYNAMIC            6
+CONSTANT: SHT_NOTE               7
+CONSTANT: SHT_NOBITS             8
+CONSTANT: SHT_REL                9
+CONSTANT: SHT_SHLIB              10
+CONSTANT: SHT_DYNSYM             11
+CONSTANT: SHT_LOOS               HEX: 60000000
+CONSTANT: SHT_GNU_LIBLIST        HEX: 6ffffff7
+CONSTANT: SHT_CHECKSUM           HEX: 6ffffff8
+CONSTANT: SHT_LOSUNW             HEX: 6ffffffa
+CONSTANT: SHT_SUNW_move          HEX: 6ffffffa
+CONSTANT: SHT_SUNW_COMDAT        HEX: 6ffffffb
+CONSTANT: SHT_SUNW_syminfo       HEX: 6ffffffc
+CONSTANT: SHT_GNU_verdef         HEX: 6ffffffd
+CONSTANT: SHT_GNU_verneed        HEX: 6ffffffe
+CONSTANT: SHT_GNU_versym         HEX: 6fffffff
+CONSTANT: SHT_HISUNW             HEX: 6fffffff
+CONSTANT: SHT_HIOS               HEX: 6fffffff
+CONSTANT: SHT_LOPROC             HEX: 70000000
+CONSTANT: SHT_ARM_EXIDX          HEX: 70000001
+CONSTANT: SHT_ARM_PREEMPTMAP     HEX: 70000002
+CONSTANT: SHT_ARM_ATTRIBUTES     HEX: 70000003
+CONSTANT: SHT_ARM_DEBUGOVERLAY   HEX: 70000004
+CONSTANT: SHT_ARM_OVERLAYSECTION HEX: 70000005
+CONSTANT: SHT_HIPROC             HEX: 7fffffff
+CONSTANT: SHT_LOUSER             HEX: 80000000
+CONSTANT: SHT_HIUSER             HEX: 8fffffff
+
+CONSTANT: SHF_WRITE            1
+CONSTANT: SHF_ALLOC            2
+CONSTANT: SHF_EXECINSTR        4
+CONSTANT: SHF_MERGE            16
+CONSTANT: SHF_STRINGS          32
+CONSTANT: SHF_INFO_LINK        64
+CONSTANT: SHF_LINK_ORDER       128
+CONSTANT: SHF_OS_NONCONFORMING 256
+CONSTANT: SHF_GROUP            512
+CONSTANT: SHF_TLS              1024
+CONSTANT: SHF_MASKOS           HEX: 0f000000
+CONSTANT: SHF_MASKPROC         HEX: f0000000
+
+CONSTANT: STB_LOCAL  0
+CONSTANT: STB_GLOBAL 1
+CONSTANT: STB_WEAK   2
+CONSTANT: STB_LOOS   10
+CONSTANT: STB_HIOS   12
+CONSTANT: STB_LOPROC 13
+CONSTANT: STB_HIPROC 15
+
+CONSTANT: STT_NOTYPE   0
+CONSTANT: STT_OBJECT   1
+CONSTANT: STT_FUNC     2
+CONSTANT: STT_SECTION  3
+CONSTANT: STT_FILE     4
+CONSTANT: STT_COMMON   5
+CONSTANT: STT_TLS      6
+CONSTANT: STT_LOOS    10
+CONSTANT: STT_HIOS    12
+CONSTANT: STT_LOPROC  13
+CONSTANT: STT_HIPROC  15
+
+CONSTANT: STN_UNDEF 0
+
+CONSTANT: STV_DEFAULT   0
+CONSTANT: STV_INTERNAL  1
+CONSTANT: STV_HIDDEN    2
+CONSTANT: STV_PROTECTED 3
+
+CONSTANT: PT_NULL        0
+CONSTANT: PT_LOAD        1
+CONSTANT: PT_DYNAMIC     2
+CONSTANT: PT_INTERP      3
+CONSTANT: PT_NOTE        4
+CONSTANT: PT_SHLIB       5
+CONSTANT: PT_PHDR        6
+CONSTANT: PT_TLS         7
+CONSTANT: PT_LOOS        HEX: 60000000
+CONSTANT: PT_HIOS        HEX: 6fffffff
+CONSTANT: PT_LOPROC      HEX: 70000000
+CONSTANT: PT_ARM_ARCHEXT HEX: 70000000
+CONSTANT: PT_ARM_EXIDX   HEX: 70000001
+CONSTANT: PT_ARM_UNWIND  HEX: 70000001
+CONSTANT: PT_HIPROC      HEX: 7fffffff
+
+CONSTANT: PT_ARM_ARCHEXT_FMTMSK       HEX: ff000000
+CONSTANT: PT_ARM_ARCHEXT_PROFMSK      HEX: 00ff0000
+CONSTANT: PT_ARM_ARCHEXT_ARCHMSK      HEX: 000000ff
+CONSTANT: PT_ARM_ARCHEXT_FMT_OS       HEX: 00000000
+CONSTANT: PT_ARM_ARCHEXT_FMT_ABI      HEX: 01000000
+CONSTANT: PT_ARM_ARCHEXT_PROF_NONE    HEX: 00000000
+CONSTANT: PT_ARM_ARCHEXT_PROF_ARM     HEX: 00410000
+CONSTANT: PT_ARM_ARCHEXT_PROF_RT      HEX: 00520000
+CONSTANT: PT_ARM_ARCHEXT_PROF_MC      HEX: 004d0000
+CONSTANT: PT_ARM_ARCHEXT_PROF_CLASSIC HEX: 00530000
+
+CONSTANT: PT_ARM_ARCHEXT_ARCH_UNKN      HEX: 00
+CONSTANT: PT_ARM_ARCHEXT_ARCH_ARCHv4    HEX: 01
+CONSTANT: PT_ARM_ARCHEXT_ARCH_ARCHv4T   HEX: 02
+CONSTANT: PT_ARM_ARCHEXT_ARCH_ARCHv5T   HEX: 03
+CONSTANT: PT_ARM_ARCHEXT_ARCH_ARCHv5TE  HEX: 04
+CONSTANT: PT_ARM_ARCHEXT_ARCH_ARCHv5TEJ HEX: 05
+CONSTANT: PT_ARM_ARCHEXT_ARCH_ARCHv6    HEX: 06
+CONSTANT: PT_ARM_ARCHEXT_ARCH_ARCHv6KZ  HEX: 07
+CONSTANT: PT_ARM_ARCHEXT_ARCH_ARCHv6T2  HEX: 08
+CONSTANT: PT_ARM_ARCHEXT_ARCH_ARCHv6K   HEX: 09
+CONSTANT: PT_ARM_ARCHEXT_ARCH_ARCHv7    HEX: 0A
+CONSTANT: PT_ARM_ARCHEXT_ARCH_ARCHv6M   HEX: 0B
+CONSTANT: PT_ARM_ARCHEXT_ARCH_ARCHv6SM  HEX: 0C
+CONSTANT: PT_ARM_ARCHEXT_ARCH_ARCHv7EM  HEX: 0D
+
+CONSTANT: PF_X        1
+CONSTANT: PF_W        2
+CONSTANT: PF_R        4
+CONSTANT: PF_MASKOS   HEX: 00ff0000
+CONSTANT: PF_MASKPROC HEX: ff000000
+
+CONSTANT: DT_NULL            0
+CONSTANT: DT_NEEDED          1
+CONSTANT: DT_PLTRELSZ        2
+CONSTANT: DT_PLTGOT          3
+CONSTANT: DT_HASH            4
+CONSTANT: DT_STRTAB          5
+CONSTANT: DT_SYMTAB          6
+CONSTANT: DT_RELA            7
+CONSTANT: DT_RELASZ          8
+CONSTANT: DT_RELAENT         9
+CONSTANT: DT_STRSZ           10
+CONSTANT: DT_SYMENT          11
+CONSTANT: DT_INIT            12
+CONSTANT: DT_FINI            13
+CONSTANT: DT_SONAME          14
+CONSTANT: DT_RPATH           15
+CONSTANT: DT_SYMBOLIC        16
+CONSTANT: DT_REL             17
+CONSTANT: DT_RELSZ           18
+CONSTANT: DT_RELENT          19
+CONSTANT: DT_PLTREL          20
+CONSTANT: DT_DEBUG           21
+CONSTANT: DT_TEXTREL         22
+CONSTANT: DT_JMPREL          23
+CONSTANT: DT_BIND_NOW        24
+CONSTANT: DT_INIT_ARRAY      25
+CONSTANT: DT_FINI_ARRAY      26
+CONSTANT: DT_INIT_ARRAYSZ    27
+CONSTANT: DT_FINI_ARRAYSZ    28
+CONSTANT: DT_RUNPATH         29
+CONSTANT: DT_FLAGS           30
+CONSTANT: DT_ENCODING        32
+CONSTANT: DT_PREINIT_ARRAY   32
+CONSTANT: DT_PREINIT_ARRAYSZ 33
+CONSTANT: DT_LOOS            HEX: 60000000
+CONSTANT: DT_HIOS            HEX: 6fffffff
+CONSTANT: DT_LOPROC          HEX: 70000000
+CONSTANT: DT_ARM_RESERVED1   HEX: 70000000
+CONSTANT: DT_ARM_SYMTABSZ    HEX: 70000001
+CONSTANT: DT_ARM_PREEMPTYMAP HEX: 70000002
+CONSTANT: DT_ARM_RESERVED2   HEX: 70000003
+CONSTANT: DT_HIPROC          HEX: 7fffffff
+
+TYPEDEF: ushort    Elf32_Half
+TYPEDEF: uint      Elf32_Word
+TYPEDEF: int       Elf32_Sword
+TYPEDEF: uint      Elf32_Off
+TYPEDEF: uint      Elf32_Addr
+TYPEDEF: ushort    Elf64_Half
+TYPEDEF: uint      Elf64_Word
+TYPEDEF: ulonglong Elf64_Xword
+TYPEDEF: longlong  Elf64_Sxword
+TYPEDEF: ulonglong Elf64_Off
+TYPEDEF: ulonglong Elf64_Addr
+
+STRUCT: Elf32_Ehdr
+    { e_ident     uchar[16]  }
+    { e_type      Elf32_Half }
+    { e_machine   Elf32_Half }
+    { e_version   Elf32_Word }
+    { e_entry     Elf32_Addr }
+    { e_phoff     Elf32_Off  }
+    { e_shoff     Elf32_Off  }
+    { e_flags     Elf32_Word }
+    { e_ehsize    Elf32_Half }
+    { e_phentsize Elf32_Half }
+    { e_phnum     Elf32_Half }
+    { e_shentsize Elf32_Half }
+    { e_shnum     Elf32_Half }
+    { e_shstrndx  Elf32_Half } ;
+
+STRUCT: Elf64_Ehdr
+    { e_ident     uchar[16]  }
+    { e_type      Elf64_Half }
+    { e_machine   Elf64_Half }
+    { e_version   Elf64_Word }
+    { e_entry     Elf64_Addr }
+    { e_phoff     Elf64_Off  }
+    { e_shoff     Elf64_Off  }
+    { e_flags     Elf64_Word }
+    { e_ehsize    Elf64_Half }
+    { e_phentsize Elf64_Half }
+    { e_phnum     Elf64_Half }
+    { e_shentsize Elf64_Half }
+    { e_shnum     Elf64_Half }
+    { e_shstrndx  Elf64_Half } ;
+
+STRUCT: Elf32_Shdr
+    { sh_name      Elf32_Word  }
+    { sh_type      Elf32_Word  }
+    { sh_flags     Elf32_Word  }
+    { sh_addr      Elf32_Addr  }
+    { sh_offset    Elf32_Off   }
+    { sh_size      Elf32_Word  }
+    { sh_link      Elf32_Word  }
+    { sh_info      Elf32_Word  }
+    { sh_addralign Elf32_Word  }
+    { sh_entsize   Elf32_Word  } ;
+
+STRUCT: Elf64_Shdr
+    { sh_name      Elf64_Word  }
+    { sh_type      Elf64_Word  }
+    { sh_flags     Elf64_Xword }
+    { sh_addr      Elf64_Addr  }
+    { sh_offset    Elf64_Off   }
+    { sh_size      Elf64_Xword }
+    { sh_link      Elf64_Word  }
+    { sh_info      Elf64_Word  }
+    { sh_addralign Elf64_Xword }
+    { sh_entsize   Elf64_Xword } ;
+
+STRUCT: Elf32_Sym
+    { st_name  Elf32_Word }
+    { st_value Elf32_Addr }
+    { st_size  Elf32_Word }
+    { st_info  uchar      }
+    { st_other uchar      }
+    { st_shndx Elf32_Half } ;
+
+STRUCT: Elf64_Sym
+    { st_name  Elf64_Word  }
+    { st_info  uchar       }
+    { st_other uchar       }
+    { st_shndx Elf64_Half  }
+    { st_value Elf64_Addr  }
+    { st_size  Elf64_Xword } ;
+
+STRUCT: Elf32_Rel
+    { r_offset Elf32_Addr }
+    { r_info   Elf32_Word } ;
+
+STRUCT: Elf32_Rela
+    { r_offset Elf32_Addr  }
+    { r_info   Elf32_Word  }
+    { r_addend Elf32_Sword } ;
+
+STRUCT: Elf64_Rel
+    { r_offset Elf64_Addr  }
+    { r_info   Elf64_Xword } ;
+
+STRUCT: Elf64_Rela
+    { r_offset Elf64_Addr   }
+    { r_info   Elf64_Xword  }
+    { r_addend Elf64_Sxword } ;
+
+STRUCT: Elf32_Phdr
+    { p_type   Elf32_Word  }
+    { p_offset Elf32_Off   }
+    { p_vaddr  Elf32_Addr  }
+    { p_paddr  Elf32_Addr  }
+    { p_filesz Elf32_Word  }
+    { p_memsz  Elf32_Word  }
+    { p_flags  Elf32_Word  }
+    { p_align  Elf32_Word  } ;
+
+STRUCT: Elf64_Phdr
+    { p_type   Elf64_Word  }
+    { p_flags  Elf64_Word  }
+    { p_offset Elf64_Off   }
+    { p_vaddr  Elf64_Addr  }
+    { p_paddr  Elf64_Addr  }
+    { p_filesz Elf64_Xword }
+    { p_memsz  Elf64_Xword }
+    { p_align  Elf64_Xword } ;
+
+STRUCT: Elf32_Dyn
+    { d_tag Elf32_Sword }
+    { d_val Elf32_Word  } ;
+
+STRUCT: Elf64_Dyn
+    { d_tag Elf64_Sxword }
+    { d_val Elf64_Xword  } ;
diff --git a/extra/elf/summary.txt b/extra/elf/summary.txt
new file mode 100644 (file)
index 0000000..5cb6b84
--- /dev/null
@@ -0,0 +1 @@
+Constants and structs related to the ELF object format.
index a233d6f4f545dfd416e743985c766db888948b2c..458ef3d51e2de1df1ae41dd20543cdec247cde24 100755 (executable)
@@ -16,7 +16,7 @@ IN: fullscreen
 :: (monitor-info>devmodes) ( monitor-info n -- )
     DEVMODE <struct>
         DEVMODE heap-size >>dmSize
-        { DM_BITSPERPEL DM_PELSWIDTH DM_PELSHEIGHT } flags >>dmFields
+        flags{ DM_BITSPERPEL DM_PELSWIDTH DM_PELSHEIGHT } >>dmFields
     :> devmode
 
     monitor-info szDevice>>
@@ -73,11 +73,11 @@ ERROR: display-change-error n ;
 
 : set-fullscreen-styles ( hwnd -- )
     [ GWL_STYLE [ WS_OVERLAPPEDWINDOW unmask ] change-style ]
-    [ GWL_EXSTYLE [ { WS_EX_APPWINDOW WS_EX_TOPMOST } flags bitor ] change-style ] bi ;
+    [ GWL_EXSTYLE [ flags{ WS_EX_APPWINDOW WS_EX_TOPMOST } bitor ] change-style ] bi ;
 
 : set-non-fullscreen-styles ( hwnd -- )
     [ GWL_STYLE [ WS_OVERLAPPEDWINDOW bitor ] change-style ]
-    [ GWL_EXSTYLE [ { WS_EX_APPWINDOW WS_EX_TOPMOST } flags unmask ] change-style ] bi ;
+    [ GWL_EXSTYLE [ flags{ WS_EX_APPWINDOW WS_EX_TOPMOST } unmask ] change-style ] bi ;
 
 ERROR: unsupported-resolution triple ;
 
@@ -92,10 +92,10 @@ ERROR: unsupported-resolution triple ;
     hwnd f
     desktop-monitor-info rcMonitor>> slots{ left top } first2
     triple first2
-    {
+    flags{
         SWP_NOACTIVATE SWP_NOCOPYBITS SWP_NOOWNERZORDER
         SWP_NOREPOSITION SWP_NOZORDER
-    } flags
+    }
     SetWindowPos win32-error=0/f ;
 
 :: enable-fullscreen ( triple hwnd -- rect )
diff --git a/extra/game/debug/authors.txt b/extra/game/debug/authors.txt
new file mode 100644 (file)
index 0000000..6f03a12
--- /dev/null
@@ -0,0 +1 @@
+Erik Charlebois
diff --git a/extra/game/debug/debug.factor b/extra/game/debug/debug.factor
new file mode 100644 (file)
index 0000000..a4f4895
--- /dev/null
@@ -0,0 +1,212 @@
+! Copyright (C) 2010 Erik Charlebois
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors alien.c-types arrays circular colors colors.constants
+columns destructors fonts gpu.buffers gpu.render gpu.shaders gpu.state
+gpu.textures images kernel literals locals make math math.constants
+math.functions math.vectors sequences specialized-arrays typed ui.text fry ;
+FROM: alien.c-types => float ;
+SPECIALIZED-ARRAYS: float uint ;
+IN: game.debug
+
+<PRIVATE
+! Vertex shader for debug shapes
+GLSL-SHADER: debug-shapes-vertex-shader vertex-shader
+uniform   mat4 u_mvp_matrix;
+attribute vec3 a_position;
+attribute vec3 a_color;
+varying   vec3 v_color;
+void main()
+{
+    gl_Position = u_mvp_matrix * vec4(a_position, 1.0);
+    gl_PointSize = 5.0;
+    v_color = a_color;
+}
+;
+
+GLSL-SHADER: debug-shapes-fragment-shader fragment-shader
+varying vec3 v_color;
+void main()
+{
+    gl_FragColor = vec4(v_color, 1.0);
+}
+;
+
+VERTEX-FORMAT: debug-shapes-vertex-format
+    { "a_position" float-components 3 f }
+    { "a_color"    float-components 3 f } ;
+
+UNIFORM-TUPLE: debug-shapes-uniforms
+    { "u_mvp_matrix" mat4-uniform f } ;
+
+GLSL-PROGRAM: debug-shapes-program debug-shapes-vertex-shader
+debug-shapes-fragment-shader debug-shapes-vertex-format ;
+
+! Vertex shader for debug text
+GLSL-SHADER: debug-text-vertex-shader vertex-shader
+attribute vec2 a_position;
+attribute vec2 a_texcoord;
+varying   vec2 v_texcoord;
+void main()
+{
+    gl_Position = vec4(a_position, 0.0, 1.0);
+    v_texcoord  = a_texcoord;
+}
+;
+
+GLSL-SHADER: debug-text-fragment-shader fragment-shader
+uniform sampler2D u_text_map;
+uniform vec3 u_background_color;
+varying vec2 v_texcoord;
+void main()
+{
+    vec4 c = texture2D(u_text_map, v_texcoord);
+    if (c.xyz == u_background_color)
+        discard;
+    else
+        gl_FragColor = c;
+}
+;
+
+VERTEX-FORMAT: debug-text-vertex-format
+    { "a_position" float-components 2 f }
+    { "a_texcoord" float-components 2 f } ;
+
+UNIFORM-TUPLE: debug-text-uniforms
+    { "u_text_map"         texture-uniform f }
+    { "u_background_color" vec3-uniform    f } ;
+
+GLSL-PROGRAM: debug-text-program debug-text-vertex-shader
+debug-text-fragment-shader debug-text-vertex-format ;
+
+CONSTANT: debug-text-font
+    T{ font 
+       { name       "monospace"  }
+       { size       16           }
+       { bold?      f            }
+       { italic?    f            }
+       { foreground COLOR: white }
+       { background COLOR: black } }
+       
+CONSTANT: debug-text-texture-parameters       
+    T{ texture-parameters
+       { wrap              repeat-texcoord }
+       { min-filter        filter-linear   }
+       { min-mipmap-filter f               } }
+       
+: text>image ( string color -- image )      
+    debug-text-font clone swap >>foreground swap string>image drop ;
+
+:: image>texture ( image -- texture )
+    image [ component-order>> ] [ component-type>> ] bi
+    debug-text-texture-parameters <texture-2d> &dispose
+    [ 0 image allocate-texture-image ] keep ;
+
+:: screen-quad ( image pt dim -- float-array )
+    pt dim v/ 2.0 v*n 1.0 v-n
+    dup image dim>> dim v/ 2.0 v*n v+
+    [ first2 ] bi@ :> ( x0 y0 x1 y1 )
+    image upside-down?>>
+    [ { x0 y0 0 0 x1 y0 1 0 x1 y1 1 1 x0 y1 0 1 } ]
+    [ { x0 y0 0 1 x1 y0 1 1 x1 y1 1 0 x0 y1 0 0 } ]
+    if >float-array ;
+
+: debug-text-uniform-variables ( string color -- image uniforms )
+    text>image dup image>texture
+    float-array{ 0.0 0.0 0.0 }
+    debug-text-uniforms boa swap ;
+
+: debug-text-vertex-array ( image pt dim -- vertex-array )
+    screen-quad stream-upload draw-usage vertex-buffer byte-array>buffer &dispose
+    debug-text-program <program-instance> <vertex-array> &dispose ;
+: debug-text-index-buffer ( -- index-buffer )
+    uint-array{ 0 1 2 2 3 0 } stream-upload draw-usage index-buffer
+    byte-array>buffer &dispose 0 <buffer-ptr> 6 uint-indexes <index-elements> ;
+
+: debug-text-render ( uniforms vertex-array index-buffer -- )
+    [
+        {
+            { "primitive-mode" [ 3drop triangles-mode ] }
+            { "uniforms"       [ 2drop ] }
+            { "vertex-array"   [ drop nip ] }
+            { "indexes"        [ 2nip ] }
+        } 3<render-set> render
+    ] with-destructors ;
+
+: debug-shapes-vertex-array ( sequence -- vertex-array )
+    stream-upload draw-usage vertex-buffer byte-array>buffer &dispose
+    debug-shapes-program <program-instance> &dispose <vertex-array> &dispose ;
+
+: draw-debug-primitives ( mode primitives mvp-matrix -- )
+    f origin-upper-left 1.0 <point-state> set-gpu-state
+    {
+        { "primitive-mode"     [ 2drop ] }
+        { "uniforms"           [ 2nip debug-shapes-uniforms boa ] }
+        { "vertex-array"       [ drop nip debug-shapes-vertex-array ] }
+        { "indexes"            [ drop nip length 0 swap <index-range> ] }
+    } 3<render-set> render ;
+
+CONSTANT: box-vertices
+    { { {  1  1  1 } {  1  1 -1 } }
+      { {  1  1  1 } {  1 -1  1 } }
+      { {  1  1  1 } { -1  1  1 } }
+      { { -1 -1 -1 } { -1 -1  1 } }
+      { { -1 -1 -1 } { -1  1 -1 } }
+      { { -1 -1 -1 } {  1 -1 -1 } }
+      { { -1 -1  1 } { -1  1  1 } }
+      { { -1 -1  1 } {  1 -1  1 } }
+      { { -1  1 -1 } { -1  1  1 } }
+      { { -1  1 -1 } {  1  1 -1 } }
+      { {  1 -1 -1 } {  1 -1  1 } }
+      { {  1 -1 -1 } {  1  1 -1 } } }
+      
+CONSTANT: cylinder-vertices
+    $[ 12 iota [ 2pi 12 / * [ cos ] [ drop 0.0 ] [ sin ] tri 3array ] map ]
+    
+:: scale-cylinder-vertices ( radius half-height verts -- bot-verts top-verts )
+    verts
+    [ [ radius v*n { 0 half-height 0 } v- ] map ]
+    [ [ radius v*n { 0 half-height 0 } v+ ] map ] bi ;
+PRIVATE>
+
+: debug-point ( pt color -- )
+    [ first3 [ , ] tri@ ]
+    [ [ red>> , ] [ green>> , ] [ blue>> , ] tri ]
+    bi* ; inline
+
+: debug-line ( from to color -- )
+    dup swapd [ debug-point ] 2bi@ ; inline
+
+: debug-axes ( pt mat -- )
+    [ 0 <column> normalize over v+ COLOR: red debug-line ]
+    [ 1 <column> normalize over v+ COLOR: green debug-line ]
+    [ 2 <column> normalize over v+ COLOR: blue debug-line ]
+    2tri ; inline
+        
+:: debug-box ( pt half-widths color -- )
+    box-vertices [
+        first2 [ half-widths v* pt v+ ] bi@ color debug-line
+    ] each ; inline
+
+:: debug-circle ( points color -- )
+    points dup <circular> [ 1 swap change-circular-start ] keep
+    [ color debug-line ] 2each ; inline
+
+:: debug-cylinder ( pt half-height radius color -- )
+    radius half-height cylinder-vertices scale-cylinder-vertices
+    [ [ color debug-circle ] bi@ ]
+    [ color '[ _ debug-line ] 2each ] 2bi ; inline
+
+TYPED: draw-debug-lines ( lines: float-array mvp-matrix -- )
+    [ lines-mode -rot draw-debug-primitives ] with-destructors ; inline
+
+TYPED: draw-debug-points ( points: float-array mvp-matrix -- )
+    [ points-mode -rot draw-debug-primitives ] with-destructors ; inline
+        
+TYPED: draw-text ( string color: rgba pt dim -- )
+    [
+        [ debug-text-uniform-variables ] 2dip
+        debug-text-vertex-array
+        debug-text-index-buffer
+        debug-text-render
+    ] with-destructors ; inline
diff --git a/extra/game/debug/summary.txt b/extra/game/debug/summary.txt
new file mode 100644 (file)
index 0000000..1f772ef
--- /dev/null
@@ -0,0 +1 @@
+Simple shape rendering for visual debugging.
diff --git a/extra/game/debug/tags.txt b/extra/game/debug/tags.txt
new file mode 100644 (file)
index 0000000..84d4140
--- /dev/null
@@ -0,0 +1 @@
+games
diff --git a/extra/game/debug/tests/tests.factor b/extra/game/debug/tests/tests.factor
new file mode 100644 (file)
index 0000000..049aa2b
--- /dev/null
@@ -0,0 +1,68 @@
+! Copyright (C) 2010 Erik Charlebois
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors colors.constants game.loop game.worlds gpu
+gpu.framebuffers gpu.util.wasd game.debug kernel literals locals
+make math math.constants math.matrices math.parser sequences
+alien.c-types specialized-arrays ui.gadgets.worlds ui.pixel-formats ;
+FROM: alien.c-types => float ;
+SPECIALIZED-ARRAY: float
+IN: game.debug.tests
+
+:: clear-screen ( color -- )
+    system-framebuffer {
+        { default-attachment color }
+    } clear-framebuffer ;
+
+: deg>rad ( d -- r )
+    180 / pi * ;
+
+:: draw-debug-tests ( world -- )
+    world [ wasd-p-matrix ] [ wasd-mv-matrix ] bi m. :> mvp-matrix
+    { 0 0 0 } clear-screen
+    
+    [
+        { 0 0 0 } { 1 0 0 } COLOR: red   debug-line
+        { 0 0 0 } { 0 1 0 } COLOR: green debug-line
+        { 0 0 0 } { 0 0 1 } COLOR: blue  debug-line
+        { -1.2 0 0 } { 0 1 0 } 0 deg>rad rotation-matrix3 debug-axes
+        { 3 5 -2 } { 3 2 1 } COLOR: white debug-box
+        { 0 9 0 } 8 2 COLOR: blue debug-cylinder
+    ] float-array{ } make
+    mvp-matrix draw-debug-lines
+
+    [
+        { 0 4.0 0 } COLOR: red debug-point
+        { 0 4.1 0 } COLOR: green debug-point
+        { 0 4.2 0 } COLOR: blue debug-point
+    ] float-array{ } make
+    mvp-matrix draw-debug-points
+
+    "Frame: " world frame-number>> number>string append
+    COLOR: purple { 5 5 } world dim>> draw-text
+    world [ 1 + ] change-frame-number drop ;
+
+TUPLE: tests-world < wasd-world frame-number ;
+M: tests-world draw-world* draw-debug-tests ;
+M: tests-world wasd-movement-speed drop 1/16. ;
+M: tests-world wasd-near-plane drop 1/32. ;
+M: tests-world wasd-far-plane drop 1024.0 ;
+M: tests-world begin-game-world
+    init-gpu
+    0 >>frame-number
+    { 0.0 0.0 2.0 } 0 0 set-wasd-view drop ;
+
+GAME: run-tests {
+        { world-class tests-world }
+        { title "game.debug.tests" }
+        { pixel-format-attributes {
+            windowed
+            double-buffered
+            T{ depth-bits { value 24 } }
+        } }
+        { grab-input? t }
+        { use-game-input? t }
+        { pref-dim { 1024 768 } }
+        { tick-interval-micros $[ 60 fps ] }
+    } ;
+
+MAIN: run-tests
index 00fe14c3cdb5e3c9a4b1c8acd2032163738da22a..ffe5acd879cf600c2430001f822f29a2d0ae840c 100644 (file)
@@ -114,4 +114,4 @@ M: game-loop dispose
 
 USING: vocabs vocabs.loader ;
 
-"prettyprint" vocab [ "game.loop.prettyprint" require ] when
+"prettyprint" "game.loop.prettyprint" require-when
index b01a64ccbc48a1509d24d088993356dfb3198228..2fec4f861f3f5410a5d6ea8cca65c826c7045aaa 100644 (file)
@@ -3,6 +3,7 @@ H{
     { deploy-name "Raytrace" }
     { deploy-ui? t }
     { deploy-c-types? f }
+    { deploy-console? f }
     { deploy-unicode? f }
     { "stop-after-last-window?" t }
     { deploy-io 2 }
index 2b7d75a3aea6a2aae344b2d52f21e5973995bf1f..6e66832a2fbc4a0624cdda71278e75d3289fc65c 100755 (executable)
@@ -104,9 +104,13 @@ VARIANT: primitive-mode
     points-mode
     lines-mode
     line-strip-mode
+    lines-with-adjacency-mode
+    line-strip-with-adjacency-mode
     line-loop-mode
     triangles-mode
     triangle-strip-mode
+    triangles-with-adjacency-mode
+    triangle-strip-with-adjacency-mode
     triangle-fan-mode ;
 
 TUPLE: uniform-tuple ;
@@ -131,6 +135,10 @@ ERROR: invalid-uniform-type uniform ;
         { triangles-mode      [ GL_TRIANGLES      ] }
         { triangle-strip-mode [ GL_TRIANGLE_STRIP ] }
         { triangle-fan-mode   [ GL_TRIANGLE_FAN   ] }
+        { lines-with-adjacency-mode          [ GL_LINES_ADJACENCY          ] }
+        { line-strip-with-adjacency-mode     [ GL_LINE_STRIP_ADJACENCY     ] }
+        { triangles-with-adjacency-mode      [ GL_TRIANGLES_ADJACENCY      ] }
+        { triangle-strip-with-adjacency-mode [ GL_TRIANGLE_STRIP_ADJACENCY ] }
     } case ; inline
 
 GENERIC: render-vertex-indexes ( primitive-mode vertex-indexes -- )
index 025acba896f12fa06b8df35da26a9dd373c949b8..69f6ba2253187025155c88339d75d2b2cf143307 100755 (executable)
@@ -15,7 +15,18 @@ SPECIALIZED-ARRAY: void*
 IN: gpu.shaders
 
 VARIANT: shader-kind
-    vertex-shader fragment-shader ;
+    vertex-shader fragment-shader geometry-shader ;
+
+VARIANT: geometry-shader-input
+    points-input
+    lines-input
+    lines-with-adjacency-input
+    triangles-input
+    triangles-with-adjacency-input ;
+VARIANT: geometry-shader-output
+    points-output
+    line-strips-output
+    triangle-strips-output ;
 
 UNION: ?string string POSTPONE: f ;
 
@@ -47,6 +58,7 @@ TUPLE: program
     { shaders array read-only }
     { vertex-formats array read-only }
     { feedback-format ?vertex-format read-only }
+    { geometry-shader-parameters array read-only }
     { instances hashtable read-only } ;
 
 TUPLE: shader-instance < gpu-object
@@ -197,6 +209,31 @@ TR: hyphens>underscores "-" "_" ;
     vertex-attributes [ [verify-feedback-attribute] ] map-index :> verify-cleave
     { drop verify-cleave cleave } >quotation ;
 
+: gl-geometry-shader-input ( input -- input )
+    {
+        { points-input [ GL_POINTS ] }
+        { lines-input  [ GL_LINES ] }
+        { lines-with-adjacency-input [ GL_LINES_ADJACENCY ] }
+        { triangles-input [ GL_TRIANGLES ] }
+        { triangles-with-adjacency-input [ GL_TRIANGLES_ADJACENCY ] }
+    } case ; inline
+
+: gl-geometry-shader-output ( output -- output )
+    {
+        { points-output [ GL_POINTS ] }
+        { line-strips-output  [ GL_LINE_STRIP ] }
+        { triangle-strips-output [ GL_TRIANGLE_STRIP ] }
+    } case ; inline
+
+TUPLE: geometry-shader-vertices-out
+    { count integer read-only } ;
+
+UNION: geometry-shader-parameter
+    geometry-shader-input
+    geometry-shader-output
+    geometry-shader-vertices-out ;
+
+
 GENERIC: bind-vertex-format ( program-instance buffer-ptr format -- )
 
 GENERIC: link-feedback-format ( program-handle format -- )
@@ -208,6 +245,18 @@ M: f link-feedback-format
     [ vertex-format-attributes [ name>> ] map sift ] map concat
     swap '[ [ _ ] 2dip swap glBindAttribLocation ] each-index ; 
 
+GENERIC: link-geometry-shader-parameter ( program-handle parameter -- )
+
+M: geometry-shader-input link-geometry-shader-parameter
+    [ GL_GEOMETRY_INPUT_TYPE ] dip gl-geometry-shader-input glProgramParameteriARB ;
+M: geometry-shader-output link-geometry-shader-parameter
+    [ GL_GEOMETRY_OUTPUT_TYPE ] dip gl-geometry-shader-output glProgramParameteriARB ;
+M: geometry-shader-vertices-out link-geometry-shader-parameter
+    [ GL_GEOMETRY_VERTICES_OUT ] dip count>> glProgramParameteriARB ;
+
+: link-geometry-shader-parameters ( program-handle parameters -- )
+    [ link-geometry-shader-parameter ] with each ;
+
 GENERIC: (verify-feedback-format) ( program-instance format -- )
 
 M: f (verify-feedback-format)
@@ -293,7 +342,8 @@ padding-no [ 0 ] initialize
     {
         { vertex-shader [ GL_VERTEX_SHADER ] }
         { fragment-shader [ GL_FRAGMENT_SHADER ] }
-    } case ;
+        { geometry-shader [ GL_GEOMETRY_SHADER ] }
+    } case ; inline
 
 PRIVATE>
 
@@ -433,8 +483,12 @@ DEFER: <shader-instance>
 : (link-program) ( program shader-instances -- program-instance )
     '[ _ [ handle>> ] map ]
     [
-        [ vertex-formats>> ] [ feedback-format>> ] bi
-        '[ [ _ link-vertex-formats ] [ _ link-feedback-format ] bi ]
+        [ vertex-formats>> ] [ feedback-format>> ] [ geometry-shader-parameters>> ] tri
+        '[
+            [ _ link-vertex-formats ]
+            [ _ link-feedback-format ]
+            [ _ link-geometry-shader-parameters ] tri
+        ]
     ] bi (gl-program)
     dup gl-program-ok?  [
         [ swap world get \ program-instance boa |dispose dup verify-feedback-format ]
@@ -485,15 +539,20 @@ TUPLE: feedback-format
 : ?shader ( object -- shader/f )
     dup word? [ def>> first dup shader? [ drop f ] unless ] [ drop f ] if ;
 
-: shaders-and-formats ( words -- shaders vertex-formats feedback-format )
-    [ [ ?shader ] map sift ]
-    [ [ vertex-format-attributes ] filter ]
-    [ [ feedback-format? ] filter validate-feedback-format ] tri ;
+: shaders-and-formats ( words -- shaders vertex-formats feedback-format geom-parameters )
+    {
+        [ [ ?shader ] map sift ]
+        [ [ vertex-format-attributes ] filter ]
+        [ [ feedback-format? ] filter validate-feedback-format ]
+        [ [ geometry-shader-parameter? ] filter ]
+    } cleave ;
 
 PRIVATE>
 
 SYNTAX: feedback-format:
     scan-object feedback-format boa suffix! ;
+SYNTAX: geometry-shader-vertices-out:
+    scan-object geometry-shader-vertices-out boa suffix! ;
 
 TYPED:: refresh-program ( program: program -- )
     program shaders>> [ refresh-shader-source ] each
@@ -575,4 +634,4 @@ M: program-instance dispose
     [ world>> ] [ program>> instances>> ] [ ] tri ?delete-at
     reset-memos ;
 
-"prettyprint" vocab [ "gpu.shaders.prettyprint" require ] when
+"prettyprint" "gpu.shaders.prettyprint" require-when
index dbb013aca04ff7a8d3ed859d3738384286093cb0..14d4f515ae94f18d37cecf526f8f6e23e2ab825e 100644 (file)
@@ -1,6 +1,7 @@
 ! Copyright (C) 2008 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien.syntax kernel math.bitwise sequences system io.serial ;
+USING: alien.syntax kernel math.bitwise sequences system io.serial
+literals ;
 IN: io.serial.unix
 
 M: bsd lookup-baud ( m -- n )
@@ -60,7 +61,7 @@ CONSTANT: HUPCL       HEX: 00004000
 CONSTANT: CLOCAL      HEX: 00008000
 CONSTANT: CCTS_OFLOW  HEX: 00010000
 CONSTANT: CRTS_IFLOW  HEX: 00020000
-: CRTSCTS ( -- n )  { CCTS_OFLOW CRTS_IFLOW } flags ; inline
+CONSTANT: CRTSCTS flags{ CCTS_OFLOW CRTS_IFLOW }
 CONSTANT: CDTR_IFLOW  HEX: 00040000
 CONSTANT: CDSR_OFLOW  HEX: 00080000
 CONSTANT: CCAR_OFLOW  HEX: 00100000
index f4c0c6b45a4cbc91ce9862867c11dc20291c4b2b..422844ab82f1e91222cc785c88b91c0874bd1591 100644 (file)
@@ -1,6 +1,7 @@
 ! Copyright (C) 2008 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors kernel math.bitwise io.serial io.serial.unix ;
+USING: accessors kernel math.bitwise io.serial io.serial.unix
+literals ;
 IN: io.serial.unix
 
 : serial-obj ( -- obj )
@@ -10,10 +11,10 @@ IN: io.serial.unix
     ! "/dev/ttyd0" >>path ! freebsd
     ! "/dev/ttyU0" >>path ! openbsd
     19200 >>baud
-    { IGNPAR ICRNL } flags >>iflag
-    { } flags >>oflag
-    { CS8 CLOCAL CREAD } flags >>cflag
-    { ICANON } flags >>lflag ;
+    flags{ IGNPAR ICRNL } >>iflag
+    flags{ } >>oflag
+    flags{ CS8 CLOCAL CREAD } >>cflag
+    flags{ ICANON } >>lflag ;
 
 : serial-test ( -- serial )
     serial-obj
index 6c0de55ec84628b3983e3206f54bce23fdc504d3..fc613da4238164f6451c39c6488dfc7333459a0b 100644 (file)
@@ -3,7 +3,8 @@
 USING: accessors alien.c-types alien.syntax alien.data 
 classes.struct combinators io.ports io.streams.duplex
 system kernel math math.bitwise vocabs.loader io.serial
-io.serial.unix.termios io.backend.unix unix unix.ffi ;
+io.serial.unix.termios io.backend.unix unix unix.ffi
+literals ;
 IN: io.serial.unix
 
 << {
@@ -33,7 +34,7 @@ FUNCTION: int cfsetspeed ( termios* t, speed_t s ) ;
 
 M: unix open-serial ( serial -- serial' )
     dup
-    path>> { O_RDWR O_NOCTTY O_NDELAY } flags file-mode open-file
+    path>> flags{ O_RDWR O_NOCTTY O_NDELAY } file-mode open-file
     fd>duplex-stream >>stream ;
 
 : serial-fd ( serial -- fd )
index 0963765482275ba61681a2b3411f9df6a4000579..950b34a8d79d80782b3cc7d3a1946f6f5901f14d 100644 (file)
@@ -1,13 +1,13 @@
-! Copyright (C) 2008 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: fry irc.client irc.client.chats kernel namespaces
 sequences threads io.launcher io splitting
 make mason.common mason.updates calendar math alarms
-io.encodings.8-bit.latin1 ;
+io.encodings.8-bit.latin1 debugger ;
 IN: irc.gitbot
 
 : bot-profile ( -- obj )
-    "irc.freenode.org" 6667 "jackass" f <irc-profile> ;
+    "irc.freenode.org" 6667 "stackoid" f <irc-profile> ;
 
 : bot-channel ( -- seq ) "#concatenative" ;
 
@@ -46,8 +46,10 @@ M: object handle-message drop ;
     '[ _ speak ] interleave ;
 
 : check-for-updates ( chat -- )
-    [ git-id git-pull-cmd short-running-process git-id ] dip
-    report-updates ;
+    '[
+        git-id git-pull-cmd short-running-process git-id
+        _ report-updates
+    ] try ;
 
 : bot ( -- )
     start-bot
index 6fedac87bd0a154a3a2c62ab20fd759c7d62154d..f8046ac8e567b8ac7a2815c93453af42dec1d09d 100644 (file)
@@ -33,7 +33,7 @@ USING: mason.child mason.config tools.test namespaces io kernel sequences ;
     ] with-scope
 ] unit-test
 
-[ { "./factor.com" "-i=boot.x86.32.image" "-no-user-init" } ] [
+[ { "./factor.com" "-i=boot.winnt-x86.32.image" "-no-user-init" } ] [
     [
         "winnt" target-os set
         "x86.32" target-cpu set
index 912cd48c79387c945dbe03b32df5c51f65ed2bc9..db68a558e094e68031866cb76e5a4532fd445e66 100644 (file)
@@ -17,8 +17,8 @@ SYMBOL: current-git-id
 
 : short-running-process ( command -- )
     #! Give network operations and shell commands at most
-    #! 15 minutes to complete, to catch hangs.
-    >process 15 minutes >>timeout try-output-process ;
+    #! 30 minutes to complete, to catch hangs.
+    >process 30 minutes >>timeout try-output-process ;
 
 HOOK: really-delete-tree os ( path -- )
 
index 061ce07d1e515d5f5a482f40c08d4d2097234e8f..f1b184f2201423d6adb77cad6b7a09c7f481f83f 100644 (file)
@@ -11,7 +11,7 @@ ui.gadgets.worlds ui.pixel-formats specialized-arrays
 specialized-vectors literals fry
 sequences.deep destructors math.bitwise opengl.gl
 game.models game.models.obj game.models.loader game.models.collada
-prettyprint images.tga ;
+prettyprint images.tga literals ;
 FROM: alien.c-types => float ;
 SPECIALIZED-ARRAY: float
 SPECIALIZED-VECTOR: uint
@@ -164,9 +164,9 @@ TUPLE: vbo
     0 0 0 0 glClearColor 
     1 glClearDepth
     HEX: ffffffff glClearStencil
-    { GL_COLOR_BUFFER_BIT
+    flags{ GL_COLOR_BUFFER_BIT
       GL_DEPTH_BUFFER_BIT
-      GL_STENCIL_BUFFER_BIT } flags glClear ;
+      GL_STENCIL_BUFFER_BIT } glClear ;
     
 : draw-model ( world -- )
     clear-screen
diff --git a/extra/path-finding/authors.txt b/extra/path-finding/authors.txt
new file mode 100644 (file)
index 0000000..f3b0233
--- /dev/null
@@ -0,0 +1 @@
+Samuel Tardieu
diff --git a/extra/path-finding/path-finding-docs.factor b/extra/path-finding/path-finding-docs.factor
new file mode 100644 (file)
index 0000000..46f1048
--- /dev/null
@@ -0,0 +1,97 @@
+! Copyright (C) 2010 Samuel Tardieu.
+! See http://factorcode.org/license.txt for BSD license.
+USING: help.markup help.syntax ;
+IN: path-finding
+
+{ <astar> <bfs> } related-words
+
+HELP: astar
+{ $description "This tuple must be subclassed and its method " { $link cost } ", "
+  { $link heuristic } ", and " { $link neighbours } " must be implemented. "
+  "Alternatively, the " { $link <astar> } " word can be used to build a non-specialized version." } ;
+
+HELP: cost
+{ $values
+  { "from" "a node" }
+  { "to" "a node" }
+  { "astar" "an instance of a subclassed " { $link astar } " tuple" }
+  { "n" "a number" }
+}
+{ $description "Return the cost to go from " { $snippet "from" } " to " { $snippet "to" } ". "
+  { $snippet "to" } " is necessarily a neighbour of " { $snippet "from" } "."
+} ;
+
+HELP: heuristic
+{ $values
+  { "from" "a node" }
+  { "to" "a node" }
+  { "astar" "an instance of a subclassed " { $link astar } " tuple" }
+  { "n" "a number" }
+}
+{ $description "Return the estimated (undervalued) cost to go from " { $snippet "from" } " to " { $snippet "to" } ". "
+  { $snippet "from" } " and " { $snippet "to" } " are not necessarily neighbours."
+} ;
+
+HELP: neighbours
+{ $values
+  { "node" "a node" }
+  { "astar" "an instance of a subclassed " { $link astar } " tuple" }
+  { "seq" "a sequence of nodes" }
+}
+{ $description "Return the list of nodes reachable from " { $snippet "node" } "." } ;
+
+HELP: <astar>
+{ $values
+  { "neighbours" "a quotation with stack effect ( node -- seq )" }
+  { "cost" "a quotation with stack effect ( from to -- cost )" }
+  { "heuristic" "a quotation with stack effect ( pos target -- cost )" }
+  { "astar" "a astar tuple" }
+}
+{ $description "Build an astar object from the given quotations. The "
+  { $snippet "neighbours" } " one builds the list of neighbours. The "
+  { $snippet "cost" } " and " { $snippet "heuristic" } " ones represent "
+  "respectively the cost for transitioning from a node to one of its neighbour, "
+  "and the underestimated cost for going from a node to the target. This solution "
+  "may not be as efficient as subclassing the " { $link astar } " tuple."
+} ;
+
+HELP: <bfs>
+{ $values
+  { "neighbours" "an assoc" }
+  { "astar" "a astar tuple" }
+}
+{ $description "Build an astar object from the " { $snippet "neighbours" } " assoc. "
+  "When used with " { $link find-path } ", this astar tuple will use the breadth-first search (BFS) "
+  "path finding algorithm which is a particular case of the general A* algorithm."
+} ;
+
+HELP: find-path
+{ $values
+  { "start" "a node" }
+  { "target" "a node" }
+  { "astar" "a astar tuple" }
+  { "path/f" "an optimal path from " { $snippet "start" } " to " { $snippet "target" }
+    ", or f if no such path exists" }
+}
+{ $description "Find a path between " { $snippet "start" } " and " { $snippet "target" }
+  " using the A* algorithm."
+} ;
+
+HELP: considered
+{ $values
+  { "astar" "a astar tuple" }
+  { "considered" "a sequence" }
+}
+{ $description "When called after a call to " { $link find-path } ", return a list of nodes "
+  "which have been examined during the A* exploration."
+} ;
+
+ARTICLE: "path-finding" "Path finding using the A* algorithm"
+"The " { $vocab-link "path-finding" } " vocabulary implements a graph search algorithm for finding the least-cost path from one node to another using the A* algorithm." $nl
+"The " { $link astar } " tuple may be derived from and its " { $link cost } ", " { $link heuristic } ", and " { $link neighbours } " methods overwritten, or the " { $link <astar> } " or " { $link <bfs> } " words can be used to build a new tuple." $nl
+"Make an A* object:"
+{ $subsections <astar> <bfs> }
+"Find a path between nodes:"
+{ $subsections find-path } ;
+
+ABOUT: "path-finding"
diff --git a/extra/path-finding/path-finding-tests.factor b/extra/path-finding/path-finding-tests.factor
new file mode 100644 (file)
index 0000000..11a047c
--- /dev/null
@@ -0,0 +1,122 @@
+! Copyright (C) 2010 Samuel Tardieu.
+! See http://factorcode.org/license.txt for BSD license.
+USING: arrays assocs combinators hashtables kernel literals math math.functions
+math.vectors memoize path-finding sequences sorting splitting strings tools.test ;
+IN: path-finding.tests
+
+! Use a 10x9 maze (see below) to try to go from s to e, f or g.
+! X means that a position is unreachable.
+! The costs model is:
+!   - going up costs 5 points
+!   - going down costs 1 point
+!   - going left or right costs 2 points
+
+<<
+
+TUPLE: maze < astar ;
+
+: reachable? ( pos -- ? )
+    first2 [ 2 * 5 + ] [ 2 + ] bi* $[
+"    0 1 2 3 4 5 6 7 8 9
+
+  0  X X X X X X X X X X
+  1  X s           f X X
+  2  X X X X   X X X X X
+  3  X X X X   X X X X X
+  4  X X X X   X       X
+  5  X X       X   X   X
+  6  X X X X   X   X e X
+  7  X g   X           X
+  8  X X X X X X X X X X"
+        "\n" split ] nth nth CHAR: X = not ;
+
+M: maze neighbours
+    drop
+    first2
+    { [ 1 + 2array ] [ 1 - 2array ] [ [ 1 + ] dip 2array ] [ [ 1 - ] dip 2array ] } 2cleave
+    4array
+    [ reachable? ] filter ;
+
+M: maze heuristic
+    drop v- [ abs ] [ + ] map-reduce ;
+
+M: maze cost
+    drop 2dup [ first ] bi@ = [ [ second ] bi@ > 1 5 ? ] [ 2drop 2 ] if ;
+
+: test1 ( to -- path considered )
+    { 1 1 } swap maze new [ find-path ] [ considered ] bi ;
+>>
+
+! Existing path from s to f
+[
+    {
+        { 1 1 }
+        { 2 1 }
+        { 3 1 }
+        { 4 1 }
+        { 4 2 }
+        { 4 3 }
+        { 4 4 }
+        { 4 5 }
+        { 4 6 }
+        { 4 7 }
+        { 5 7 }
+        { 6 7 }
+        { 7 7 }
+        { 8 7 }
+        { 8 6 }
+    }
+] [
+    { 8 6 } test1 drop
+] unit-test
+
+! Check that only the right positions have been considered in the s to f path
+[ 7 ] [ { 7 1 } test1 nip length ] unit-test
+
+! Non-existing path from s to g -- all positions must have been considered
+[ f 26 ] [ { 1 7 } test1 length ] unit-test
+
+! Look for a path between A and C. The best path is A --> D --> C. C will be placed
+! in the open set early because B will be examined first. This checks that the evaluation
+! of C is correctly replaced in the open set.
+!
+! We use no heuristic here and always return 0.
+!
+!       (5)
+!     B ---> C <--------
+!                        \ (2)
+!     ^      ^            |
+!     |      |            |
+! (1) |      | (2)        |
+!     |      |            |
+!
+!     A ---> D ---------> E ---> F
+!       (2)       (1)       (1)
+
+<<
+
+! In this version, we will use the quotations-aware version through <astar>.
+
+MEMO: routes ( -- hash ) $[ { "ABD" "BC" "C" "DCE" "ECF" } [ unclip swap 2array ] map >hashtable ] ;
+
+: n ( pos -- neighbours )
+    routes at ;
+
+: c ( from to -- cost )
+    "" 2sequence H{ { "AB" 1 } { "AD" 2 } { "BC" 5 } { "DC" 2 } { "DE" 1 } { "EC" 2 } { "EF" 1 } } at ;
+
+: test2 ( fromto -- path considered )
+    first2 [ n ] [ c ] [ 2drop 0 ] <astar> [ find-path ] [ considered natural-sort >string ] bi ;
+>>
+
+! Check path from A to C -- all nodes but F must have been examined
+[ "ADC" "ABCDE" ] [ "AC" test2 [ >string ] dip ] unit-test
+
+! No path from D to B -- all nodes reachable from D must have been examined
+[ f "CDEF" ] [ "DB" test2 ] unit-test
+
+! Find a path using BFS. There are no path from F to A, and the path from D to
+! C does not include any other node.
+
+[ f ] [ "FA" first2 routes <bfs> find-path ] unit-test
+[ "DC" ] [ "DC" first2 routes <bfs> find-path >string ] unit-test
diff --git a/extra/path-finding/path-finding.factor b/extra/path-finding/path-finding.factor
new file mode 100644 (file)
index 0000000..3188013
--- /dev/null
@@ -0,0 +1,89 @@
+! Copyright (C) 2010 Samuel Tardieu.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors assocs hash-sets heaps kernel math sequences sets shuffle ;
+IN: path-finding
+
+! This implements the A* algorithm. See http://en.wikipedia.org/wiki/A*
+
+TUPLE: astar g in-closed-set ;
+GENERIC: cost ( from to astar -- n )
+GENERIC: heuristic ( from to astar -- n )
+GENERIC: neighbours ( node astar -- seq )
+
+<PRIVATE
+
+TUPLE: (astar) astar goal origin in-open-set open-set ;
+
+: (add-to-open-set) ( h node astar -- )
+    2dup in-open-set>> at* [ over open-set>> heap-delete ] [ drop ] if
+    [ swapd open-set>> heap-push* ] [ in-open-set>> set-at ] 2bi ;
+
+: add-to-open-set ( node astar -- )
+    [ astar>> g>> at ] 2keep
+    [ [ goal>> ] [ astar>> heuristic ] bi + ] 2keep
+    (add-to-open-set) ;
+
+: ?add-to-open-set ( node astar -- )
+    2dup astar>> in-closed-set>> in? [ 2drop ] [ add-to-open-set ] if ;
+
+: move-to-closed-set ( node astar -- )
+    [ astar>> in-closed-set>> adjoin ] [ in-open-set>> delete-at ] 2bi ;
+
+: get-first ( astar -- node )
+    [ open-set>> heap-pop drop dup ] [ move-to-closed-set ] bi ;
+
+: set-g ( origin g node astar -- )
+    [ [ origin>> set-at ] [ astar>> g>> set-at ] bi-curry bi-curry bi* ] [ ?add-to-open-set ] 2bi ;
+
+: cost-through ( origin node astar -- cost )
+    [ astar>> cost ] [ nip astar>> g>> at ] 3bi + ;
+
+: ?set-g ( origin node astar -- )
+    [ cost-through ] 3keep [ swap ] 2dip
+    3dup astar>> g>> at [ 1/0. ] unless* > [ 4drop ] [ set-g ] if ;
+
+: build-path ( target astar -- path )
+    [ over ] [ over [ [ origin>> at ] keep ] dip ] produce 2nip reverse ;
+
+: handle ( node astar -- )
+    dupd [ astar>> neighbours ] keep [ ?set-g ] curry with each ;
+
+: (find-path) ( astar -- path/f )
+    dup open-set>> heap-empty? [
+        drop f
+    ] [
+        [ get-first ] keep 2dup goal>> = [ build-path ] [ [ handle ] [ (find-path) ] bi ] if
+    ] if ;
+
+: (init) ( from to astar -- )
+    swap >>goal
+    H{ } clone over astar>> (>>g)
+    { } <hash-set> over astar>> (>>in-closed-set)
+    H{ } clone >>origin
+    H{ } clone >>in-open-set
+    <min-heap> >>open-set
+    [ 0 ] 2dip [ (add-to-open-set) ] [ astar>> g>> set-at ] 3bi ;
+
+TUPLE: astar-simple < astar cost heuristic neighbours ;
+M: astar-simple cost cost>> call( n1 n2 -- c ) ;
+M: astar-simple heuristic heuristic>> call( n1 n2 -- c ) ;
+M: astar-simple neighbours neighbours>> call( n -- neighbours ) ;
+
+TUPLE: bfs < astar neighbours ;
+M: bfs cost 3drop 1 ;
+M: bfs heuristic 3drop 0 ;
+M: bfs neighbours neighbours>> at ;
+
+PRIVATE>
+
+: find-path ( start target astar -- path/f )
+    (astar) new [ (>>astar) ] keep [ (init) ] [ (find-path) ] bi ;
+
+: <astar> ( neighbours cost heuristic -- astar )
+    astar-simple new swap >>heuristic swap >>cost swap >>neighbours ;
+
+: considered ( astar -- considered )
+    in-closed-set>> members ;
+
+: <bfs> ( neighbours -- astar )
+    [ bfs new ] dip >>neighbours ;
diff --git a/extra/path-finding/summary.txt b/extra/path-finding/summary.txt
new file mode 100644 (file)
index 0000000..ff3167a
--- /dev/null
@@ -0,0 +1 @@
+A* path-finding algorithm
diff --git a/extra/spelling/authors.txt b/extra/spelling/authors.txt
new file mode 100644 (file)
index 0000000..e091bb8
--- /dev/null
@@ -0,0 +1 @@
+John Benediktsson
diff --git a/extra/spelling/spelling-tests.factor b/extra/spelling/spelling-tests.factor
new file mode 100644 (file)
index 0000000..f323638
--- /dev/null
@@ -0,0 +1,14 @@
+USING: spelling tools.test memoize ;
+IN: spelling.tests
+
+MEMO: test-dictionary ( -- assoc )
+    "vocab:spelling/test.txt" load-dictionary ;
+
+: test-correct ( word -- word/f )
+    test-dictionary (correct) ;
+
+[ "government" ] [ "goverment" test-correct ] unit-test
+[ "government" ] [ "govxernment" test-correct ] unit-test
+[ "government" ] [ "govermnent" test-correct ] unit-test
+[ "government" ] [ "govxermnent" test-correct ] unit-test
+[ "government" ] [ "govyrmnent" test-correct ] unit-test
diff --git a/extra/spelling/spelling.factor b/extra/spelling/spelling.factor
new file mode 100644 (file)
index 0000000..b8a90bd
--- /dev/null
@@ -0,0 +1,78 @@
+USING: arrays ascii assocs combinators combinators.smart fry
+http.client io.encodings.ascii io.files io.files.temp kernel
+locals math math.statistics memoize sequences sorting splitting
+strings urls ;
+IN: spelling
+
+! http://norvig.com/spell-correct.html
+
+CONSTANT: ALPHABET "abcdefghijklmnopqrstuvwxyz"
+
+: splits ( word -- sequence )
+    dup length iota [ cut 2array ] with map ;
+
+: deletes ( sequence -- sequence' )
+    [ second length 0 > ] filter [ first2 rest append ] map ;
+
+: transposes ( sequence -- sequence' )
+    [ second length 1 > ] filter [
+        [
+            {
+                [ first ]
+                [ second second 1string ]
+                [ second first 1string ]
+                [ second 2 tail ]
+            } cleave
+        ] "" append-outputs-as
+    ] map ;
+
+: replaces ( sequence -- sequence' )
+    [ second length 0 > ] filter [
+        [ ALPHABET ] dip first2
+        '[ 1string _ _ rest surround ] { } map-as
+    ] map concat ;
+
+: inserts ( sequence -- sequence' )
+    [
+        ALPHABET
+        [ [ first2 ] dip 1string glue ] with { } map-as
+    ] map concat ;
+
+: edits1 ( word -- edits )
+    [
+        splits {
+            [ deletes ]
+            [ transposes ]
+            [ replaces ]
+            [ inserts ]
+        } cleave
+    ] append-outputs ;
+
+: edits2 ( word -- edits )
+    edits1 [ edits1 ] map concat ;
+
+: filter-known ( words dictionary -- words' )
+    '[ _ key? ] filter ;
+
+:: corrections ( word dictionary -- words )
+    word 1array dictionary filter-known
+    [ word edits1 dictionary filter-known ] when-empty
+    [ word edits2 dictionary filter-known ] when-empty
+    [ dictionary at 1 or ] sort-with ;
+
+: words ( string -- words )
+    >lower [ letter? not ] split-when harvest ;
+
+: load-dictionary ( file -- assoc )
+    ascii file-contents words histogram ;
+
+MEMO: default-dictionary ( -- counts )
+    "big.txt" temp-file dup exists?
+    [ URL" http://norvig.com/big.txt" over download-to ] unless
+    load-dictionary ;
+
+: (correct) ( word dictionary -- word/f )
+    corrections [ f ] [ first ] if-empty ;
+
+: correct ( word -- word/f )
+    default-dictionary (correct) ;
diff --git a/extra/spelling/summary.txt b/extra/spelling/summary.txt
new file mode 100644 (file)
index 0000000..7fa9068
--- /dev/null
@@ -0,0 +1 @@
+Peter Norvig's spelling corrector
diff --git a/extra/spelling/tags.txt b/extra/spelling/tags.txt
new file mode 100644 (file)
index 0000000..1e107f5
--- /dev/null
@@ -0,0 +1 @@
+examples
diff --git a/extra/spelling/test.txt b/extra/spelling/test.txt
new file mode 100644 (file)
index 0000000..5b9de09
--- /dev/null
@@ -0,0 +1,246 @@
+AMERICAN FOREIGN RELATIONS (1865-98)
+
+=French Intrigues in Mexico Blocked.=--Between the war for the union and
+the war with Spain, the Department of State had many an occasion to
+present the rights of America among the powers of the world. Only a
+little while after the civil conflict came to a close, it was called
+upon to deal with a dangerous situation created in Mexico by the
+ambitions of Napoleon III. During the administration of Buchanan, Mexico
+had fallen into disorder through the strife of the Liberal and the
+Clerical parties; the President asked for authority to use American
+troops to bring to a peaceful haven "a wreck upon the ocean, drifting
+about as she is impelled by different factions." Our own domestic crisis
+then intervened.
+
+Observing the United States heavily involved in its own problems, the
+great powers, England, France, and Spain, decided in the autumn of 1861
+to take a hand themselves in restoring order in Mexico. They entered
+into an agreement to enforce the claims of their citizens against Mexico
+and to protect their subjects residing in that republic. They invited
+the United States to join them, and, on meeting a polite refusal, they
+prepared for a combined military and naval demonstration on their own
+account. In the midst of this action England and Spain, discovering the
+sinister purposes of Napoleon, withdrew their troops and left the field
+to him.
+
+The French Emperor, it was well known, looked with jealousy upon the
+growth of the United States and dreamed of establishing in the Western
+hemisphere an imperial power to offset the American republic.
+Intervention to collect debts was only a cloak for his deeper designs.
+Throwing off that guise in due time, he made the Archduke Maximilian, a
+brother of the ruler of Austria, emperor in Mexico, and surrounded his
+throne by French soldiers, in spite of all protests.
+
+This insolent attack upon the Mexican republic, deeply resented in the
+United States, was allowed to drift in its course until 1865. At that
+juncture General Sheridan was dispatched to the Mexican border with a
+large armed force; General Grant urged the use of the American army to
+expel the French from this continent. The Secretary of State, Seward,
+counseled negotiation first, and, applying the Monroe Doctrine, was able
+to prevail upon Napoleon III to withdraw his troops. Without the support
+of French arms, the sham empire in Mexico collapsed like a house of
+cards and the unhappy Maximilian, the victim of French ambition and
+intrigue, met his death at the hands of a Mexican firing squad.
+
+=Alaska Purchased.=--The Mexican affair had not been brought to a close
+before the Department of State was busy with negotiations which resulted
+in the purchase of Alaska from Russia. The treaty of cession, signed on
+March 30, 1867, added to the United States a domain of nearly six
+hundred thousand square miles, a territory larger than Texas and nearly
+three-fourths the size of the Louisiana purchase. Though it was a
+distant colony separated from our continental domain by a thousand miles
+of water, no question of "imperialism" or "colonization foreign to
+American doctrines" seems to have been raised at the time. The treaty
+was ratified promptly by the Senate. The purchase price, $7,200,000, was
+voted by the House of Representatives after the display of some
+resentment against a system that compelled it to appropriate money to
+fulfill an obligation which it had no part in making. Seward, who
+formulated the treaty, rejoiced, as he afterwards said, that he had kept
+Alaska out of the hands of England.
+
+=American Interest in the Caribbean.=--Having achieved this diplomatic
+triumph, Seward turned to the increase of American power in another
+direction. He negotiated, with Denmark, a treaty providing for the
+purchase of the islands of St. John and St. Thomas in the West Indies,
+strategic points in the Caribbean for sea power. This project, long
+afterward brought to fruition by other men, was defeated on this
+occasion by the refusal of the Senate to ratify the treaty. Evidently it
+was not yet prepared to exercise colonial dominion over other races.
+
+Undaunted by the misadventure in Caribbean policies, President Grant
+warmly advocated the acquisition of Santo Domingo. This little republic
+had long been in a state of general disorder. In 1869 a treaty of
+annexation was concluded with its president. The document Grant
+transmitted to the Senate with his cordial approval, only to have it
+rejected. Not at all changed in his opinion by the outcome of his
+effort, he continued to urge the subject of annexation. Even in his last
+message to Congress he referred to it, saying that time had only proved
+the wisdom of his early course. The addition of Santo Domingo to the
+American sphere of protection was the work of a later generation. The
+State Department, temporarily checked, had to bide its time.
+
+=The _Alabama_ Claims Arbitrated.=--Indeed, it had in hand a far more
+serious matter, a vexing issue that grew out of Civil War diplomacy. The
+British government, as already pointed out in other connections, had
+permitted Confederate cruisers, including the famous _Alabama_, built in
+British ports, to escape and prey upon the commerce of the Northern
+states. This action, denounced at the time by our government as a grave
+breach of neutrality as well as a grievous injury to American citizens,
+led first to remonstrances and finally to repeated claims for damages
+done to American ships and goods. For a long time Great Britain was
+firm. Her foreign secretary denied all obligations in the premises,
+adding somewhat curtly that "he wished to say once for all that Her
+Majesty's government disclaimed any responsibility for the losses and
+hoped that they had made their position perfectly clear." Still
+President Grant was not persuaded that the door of diplomacy, though
+closed, was barred. Hamilton Fish, his Secretary of State, renewed the
+demand. Finally he secured from the British government in 1871 the
+treaty of Washington providing for the arbitration not merely of the
+_Alabama_ and other claims but also all points of serious controversy
+between the two countries.
+
+The tribunal of arbitration thus authorized sat at Geneva in
+Switzerland, and after a long and careful review of the arguments on
+both sides awarded to the United States the lump sum of $15,500,000 to
+be distributed among the American claimants. The damages thus allowed
+were large, unquestionably larger than strict justice required and it is
+not surprising that the decision excited much adverse comment in
+England. Nevertheless, the prompt payment by the British government
+swept away at once a great cloud of ill-feeling in America. Moreover,
+the spectacle of two powerful nations choosing the way of peaceful
+arbitration to settle an angry dispute seemed a happy, if illusory, omen
+of a modern method for avoiding the arbitrament of war.
+
+=Samoa.=--If the Senate had its doubts at first about the wisdom of
+acquiring strategic points for naval power in distant seas, the same
+could not be said of the State Department or naval officers. In 1872
+Commander Meade, of the United States navy, alive to the importance of
+coaling stations even in mid-ocean, made a commercial agreement with the
+chief of Tutuila, one of the Samoan Islands, far below the equator, in
+the southern Pacific, nearer to Australia than to California. This
+agreement, providing among other things for our use of the harbor of
+Pago Pago as a naval base, was six years later changed into a formal
+treaty ratified by the Senate.
+
+Such enterprise could not escape the vigilant eyes of England and
+Germany, both mindful of the course of the sea power in history. The
+German emperor, seizing as a pretext a quarrel between his consul in the
+islands and a native king, laid claim to an interest in the Samoan
+group. England, aware of the dangers arising from German outposts in the
+southern seas so near to Australia, was not content to stand aside. So
+it happened that all three countries sent battleships to the Samoan
+waters, threatening a crisis that was fortunately averted by friendly
+settlement. If, as is alleged, Germany entertained a notion of
+challenging American sea power then and there, the presence of British
+ships must have dispelled that dream.
+
+The result of the affair was a tripartite agreement by which the three
+powers in 1889 undertook a protectorate over the islands. But joint
+control proved unsatisfactory. There was constant friction between the
+Germans and the English. The spheres of authority being vague and open
+to dispute, the plan had to be abandoned at the end of ten years.
+England withdrew altogether, leaving to Germany all the islands except
+Tutuila, which was ceded outright to the United States. Thus one of the
+finest harbors in the Pacific, to the intense delight of the American
+navy, passed permanently under American dominion. Another triumph in
+diplomacy was set down to the credit of the State Department.
+
+=Cleveland and the Venezuela Affair.=--In the relations with South
+America, as well as in those with the distant Pacific, the diplomacy of
+the government at Washington was put to the test. For some time it had
+been watching a dispute between England and Venezuela over the western
+boundary of British Guiana and, on an appeal from Venezuela, it had
+taken a lively interest in the contest. In 1895 President Cleveland saw
+that Great Britain would yield none of her claims. After hearing the
+arguments of Venezuela, his Secretary of State, Richard T. Olney, in a
+note none too conciliatory, asked the British government whether it was
+willing to arbitrate the points in controversy. This inquiry he
+accompanied by a warning to the effect that the United States could not
+permit any European power to contest its mastery in this hemisphere.
+"The United States," said the Secretary, "is practically sovereign on
+this continent and its fiat is law upon the subjects to which it
+confines its interposition.... Its infinite resources, combined with its
+isolated position, render it master of the situation and practically
+invulnerable against any or all other powers."
+
+The reply evoked from the British government by this strong statement
+was firm and clear. The Monroe Doctrine, it said, even if not so widely
+stretched by interpretation, was not binding in international law; the
+dispute with Venezuela was a matter of interest merely to the parties
+involved; and arbitration of the question was impossible. This response
+called forth President Cleveland's startling message of 1895. He asked
+Congress to create a commission authorized to ascertain by researches
+the true boundary between Venezuela and British Guiana. He added that it
+would be the duty of this country "to resist by every means in its
+power, as a willful aggression upon its rights and interests, the
+appropriation by Great Britain of any lands or the exercise of
+governmental jurisdiction over any territory which, after investigation,
+we have determined of right belongs to Venezuela." The serious character
+of this statement he thoroughly understood. He declared that he was
+conscious of his responsibilities, intimating that war, much as it was
+to be deplored, was not comparable to "a supine submission to wrong and
+injustice and the consequent loss of national self-respect and honor."
+
+[Illustration: GROVER CLEVELAND]
+
+The note of defiance which ran through this message, greeted by shrill
+cries of enthusiasm in many circles, was viewed in other quarters as a
+portent of war. Responsible newspapers in both countries spoke of an
+armed settlement of the dispute as inevitable. Congress created the
+commission and appropriated money for the investigation; a body of
+learned men was appointed to determine the merits of the conflicting
+boundary claims. The British government, deaf to the clamor of the
+bellicose section of the London press, deplored the incident,
+courteously replied in the affirmative to a request for assistance in
+the search for evidence, and finally agreed to the proposition that the
+issue be submitted to arbitration. The outcome of this somewhat perilous
+dispute contributed not a little to Cleveland's reputation as "a
+sterling representative of the true American spirit." This was not
+diminished when the tribunal of arbitration found that Great Britain was
+on the whole right in her territorial claims against Venezuela.
+
+=The Annexation of Hawaii.=--While engaged in the dangerous Venezuela
+controversy, President Cleveland was compelled by a strange turn in
+events to consider the annexation of the Hawaiian Islands in the
+mid-Pacific. For more than half a century American missionaries had been
+active in converting the natives to the Christian faith and enterprising
+American business men had been developing the fertile sugar plantations.
+Both the Department of State and the Navy Department were fully
+conscious of the strategic relation of the islands to the growth of sea
+power and watched with anxiety any developments likely to bring them
+under some other Dominion.
+
+The country at large was indifferent, however, until 1893, when a
+revolution, headed by Americans, broke out, ending in the overthrow of
+the native government, the abolition of the primitive monarchy, and the
+retirement of Queen Liliuokalani to private life. This crisis, a
+repetition of the Texas affair in a small theater, was immediately
+followed by a demand from the new Hawaiian government for annexation to
+the United States. President Harrison looked with favor on the proposal,
+negotiated the treaty of annexation, and laid it before the Senate for
+approval. There it still rested when his term of office was brought to a
+close.
+
+Harrison's successor, Cleveland, it was well known, had doubts about the
+propriety of American action in Hawaii. For the purpose of making an
+inquiry into the matter, he sent a special commissioner to the islands.
+On the basis of the report of his agent, Cleveland came to the
+conclusion that "the revolution in the island kingdom had been
+accomplished by the improper use of the armed forces of the United
+States and that the wrong should be righted by a restoration of the
+queen to her throne." Such being his matured conviction, though the
+facts upon which he rested it were warmly controverted, he could do
+nothing but withdraw the treaty from the Senate and close the incident.
+
+To the Republicans this sharp and cavalier disposal of their plans,
+carried out in a way that impugned the motives of a Republican
+President, was nothing less than "a betrayal of American interests." In
+their platform of 1896 they made clear their position: "Our foreign
+policy should be at all times firm, vigorous, and dignified and all our
+interests in the Western hemisphere carefully watched and guarded. The
+Hawaiian Islands should be controlled by the United States and no
+foreign power should be permitted to interfere with them." There was no
+mistaking this view of the issue. As the vote in the election gave
+popular sanction to Republican policies, Congress by a joint resolution,
+passed on July 6, 1898, annexed the islands to the United States and
+later conferred upon them the ordinary territorial form of government.
diff --git a/extra/variables/variables.factor b/extra/variables/variables.factor
new file mode 100644 (file)
index 0000000..705e1f1
--- /dev/null
@@ -0,0 +1,98 @@
+! (c)2010 Joe Groff bsd license
+USING: accessors arrays combinators definitions fry kernel
+locals.types namespaces parser quotations see sequences slots
+words ;
+FROM: kernel.private => declare ;
+FROM: help.markup.private => link-effect? ;
+IN: variables
+
+PREDICATE: variable < word
+    "variable-setter" word-prop ;
+
+GENERIC: variable-setter ( word -- word' )
+
+M: variable variable-setter "variable-setter" word-prop ;
+M: local-reader variable-setter "local-writer" word-prop ;
+
+SYNTAX: set:
+    scan-object variable-setter suffix! ;
+
+: [variable-getter] ( variable -- quot )
+    '[ _ get ] ;
+: [variable-setter] ( variable -- quot )
+    '[ _ set ] ;
+
+: (define-variable) ( word getter setter -- )
+    [ (( -- value )) define-inline ]
+    [
+        [
+            [ name>> "set: " prepend <uninterned-word> ]
+            [ over "variable-setter" set-word-prop ] bi
+        ] dip (( value -- )) define-inline
+    ] bi-curry* bi ;
+
+: define-variable ( word -- )
+    dup [ [variable-getter] ] [ [variable-setter] ] bi (define-variable) ;
+
+SYNTAX: VAR:
+    CREATE-WORD define-variable ;    
+
+M: variable definer drop \ VAR: f ;
+M: variable definition drop f ;
+M: variable link-effect? drop f ;
+M: variable print-stack-effect? drop f ;
+
+PREDICATE: typed-variable < variable
+    "variable-type" word-prop ;
+
+: [typed-getter] ( quot type -- quot )
+    1array '[ @ _ declare ] ;
+: [typed-setter] ( quot type -- quot )
+    instance-check-quot prepose ;
+
+: define-typed-variable ( word type -- )
+    dupd {
+        [ [ [variable-getter] ] dip [typed-getter] ]
+        [ [ [variable-setter] ] dip [typed-setter] ]
+        [ "variable-type" set-word-prop ]
+        [ initial-value swap set-global ]
+    } 2cleave (define-variable) ;
+
+SYNTAX: TYPED-VAR:
+    CREATE-WORD scan-object define-typed-variable ;    
+
+M: typed-variable definer drop \ TYPED-VAR: f ;
+M: typed-variable definition "variable-type" word-prop 1quotation ;
+
+TUPLE: global-box value ;
+
+PREDICATE: global-variable < variable
+    def>> first global-box? ;
+
+: [global-getter] ( box -- quot )
+    '[ _ value>> ] ;
+: [global-setter] ( box -- quot )
+    '[ _ (>>value) ] ;
+
+: define-global ( word -- )
+    global-box new [ [global-getter] ] [ [global-setter] ] bi (define-variable) ;
+
+SYNTAX: GLOBAL:
+    CREATE-WORD define-global ;
+
+M: global-variable definer drop \ GLOBAL: f ;
+
+INTERSECTION: typed-global-variable
+    global-variable typed-variable ;
+
+: define-typed-global ( word type -- )
+    2dup "variable-type" set-word-prop
+    dup initial-value global-box boa swap
+    [ [ [global-getter] ] dip [typed-getter] ]
+    [ [ [global-setter] ] dip [typed-setter] ] 2bi (define-variable) ;
+
+SYNTAX: TYPED-GLOBAL:
+    CREATE-WORD scan-object define-typed-global ;
+
+M: typed-global-variable definer drop \ TYPED-GLOBAL: f ;
+
diff --git a/extra/vars/authors.txt b/extra/vars/authors.txt
deleted file mode 100644 (file)
index 6cfd5da..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Eduardo Cavazos
diff --git a/extra/vars/summary.txt b/extra/vars/summary.txt
deleted file mode 100644 (file)
index 9f5f717..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Shorthand notation for variables
diff --git a/extra/vars/tags.txt b/extra/vars/tags.txt
deleted file mode 100644 (file)
index f427429..0000000
+++ /dev/null
@@ -1 +0,0 @@
-extensions
diff --git a/extra/vars/vars.factor b/extra/vars/vars.factor
deleted file mode 100644 (file)
index 990b030..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-! Copyright (C) 2005, 2006 Eduardo Cavazos
-
-! Thanks to Mackenzie Straight for the idea
-
-USING: accessors kernel parser lexer words words.symbol
-namespaces sequences quotations ;
-
-IN: vars
-
-: define-var-getter ( word -- )
-    [ name>> ">" append create-in ] [ [ get ] curry ] bi
-    (( -- value )) define-declared ;
-
-: define-var-setter ( word -- )
-    [ name>> ">" prepend create-in ] [ [ set ] curry ] bi
-    (( value -- )) define-declared ;
-
-: define-var ( str -- )
-    create-in
-    [ define-symbol ]
-    [ define-var-getter ]
-    [ define-var-setter ] tri ;
-
-SYNTAX: VAR: ! var
-    scan define-var ;
-
-: define-vars ( seq -- )
-    [ define-var ] each ;
-
-SYNTAX: VARS: ! vars ...
-    ";" [ define-var ] each-token ;
index eb51acbe1a698e3dcaf8ce9972f5b4a335437209..a003c8b618b4768f6f3a44da2ef0b2d1427bb860 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2008 Slava Pestov.
+! Copyright (C) 2008, 2010 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel accessors sequences sorting math math.order
 calendar alarms logging concurrency.combinators namespaces
@@ -194,4 +194,7 @@ posting "POSTINGS"
         { planet "planet-common" } >>template ;
 
 : start-update-task ( db -- )
-    '[ _ [ update-cached-postings ] with-db ] 10 minutes every drop ;
+    '[
+        "webapps.planet"
+        [ _ [ update-cached-postings ] with-db ] with-logging
+    ] 10 minutes every drop ;
index e6178a55c3604589045f2cc24a2415c2599b44ba..8f89b1b4aead2a17742fb565a48a2a674d11e1e9 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: cocoa cocoa.application cocoa.types cocoa.classes cocoa.windows
-core-graphics.types kernel math.bitwise ;
+core-graphics.types kernel math.bitwise literals ;
 IN: webkit-demo
 
 FRAMEWORK: /System/Library/Frameworks/WebKit.framework
@@ -13,13 +13,13 @@ IMPORT: WebView
     WebView -> alloc
     rect f f -> initWithFrame:frameName:groupName: ;
 
-: window-style ( -- n )
-    {
+CONSTANT: window-style
+    flags{
         NSClosableWindowMask
         NSMiniaturizableWindowMask
         NSResizableWindowMask
         NSTitledWindowMask
-    } flags ;
+    }
 
 : <WebWindow> ( -- id )
     <WebView> rect window-style <ViewWindow> ;
index 8115627742ad9f7be7f778d7d66e2cd733e15336..dc0c57b7d5ca6417bce4d7a0432813a70af96fe7 100644 (file)
@@ -9,7 +9,7 @@ body, button {
        border: none;
 }
 
-a, .link {
+a:link, a:visited, .link {
        color: #222;
        border-bottom:1px dotted #666;
        text-decoration:none;
index a0dbe228e530a99041057c188da9c5d536041e85..4dc56cfaedc4d19999722dd8644f45e897d88ccb 100644 (file)
@@ -1,4 +1,4 @@
 include vm/Config.unix
-PLAF_DLL_OBJS += vm/os-genunix.o vm/os-freebsd.o
+PLAF_DLL_OBJS += vm/os-genunix.o vm/os-freebsd.o vm/mvm-unix.o
 CFLAGS += -export-dynamic
 LIBS = -L/usr/local/lib/ -lm -lrt $(X11_UI_LIBS)
index 4a859b1216ec1c404a5ee04bd182146669000432..00ff73522a1391610d0a74856b3a4e23e46985d7 100644 (file)
@@ -1,4 +1,4 @@
 include vm/Config.unix
-PLAF_DLL_OBJS += vm/os-genunix.o vm/os-linux.o
+PLAF_DLL_OBJS += vm/os-genunix.o vm/os-linux.o vm/mvm-unix.o
 CFLAGS += -export-dynamic
 LIBS = -ldl -lm -lrt -lpthread $(X11_UI_LIBS)
index 89fe239668bd53f2c1af3b78ff49c05d14cbbcc7..5b9de7f5cf8fb5a45f372df1390b8c5530d9e9fc 100644 (file)
@@ -1,7 +1,7 @@
 include vm/Config.unix
 CFLAGS += -fPIC
 
-PLAF_DLL_OBJS += vm/os-macosx.o vm/mach_signal.o
+PLAF_DLL_OBJS += vm/os-macosx.o vm/mach_signal.o vm/mvm-unix.o
 
 DLL_EXTENSION = .dylib
 SHARED_DLL_EXTENSION = .dylib
index 72a4056c90b4e44c96b9bc66f09a4681f81c7b97..2838f9d4c57d7392341f286485fec48eb7d8cf69 100644 (file)
@@ -1,5 +1,5 @@
 include vm/Config.unix
-PLAF_DLL_OBJS += vm/os-genunix.o vm/os-netbsd.o
+PLAF_DLL_OBJS += vm/os-genunix.o vm/os-netbsd.o vm/mvm-none.o
 CFLAGS += -export-dynamic
 LIBPATH = -L/usr/X11R7/lib -Wl,-rpath,/usr/X11R7/lib -L/usr/pkg/lib -Wl,-rpath,/usr/pkg/lib
 LIBS = -lm -lrt -lssl -lcrypto $(X11_UI_LIBS)
index c7d2672e6b326209ee1e11ab4ab8e275e206e8ae..6983223b747260e62f1e8235ab5a136ffaa8a280 100644 (file)
@@ -1,5 +1,5 @@
 include vm/Config.unix
-PLAF_DLL_OBJS += vm/os-genunix.o vm/os-openbsd.o
+PLAF_DLL_OBJS += vm/os-genunix.o vm/os-openbsd.o vm/mvm-unix.o
 CC = egcc
 CPP = eg++
 CFLAGS += -export-dynamic -fno-inline-functions
index ffaa899fe1e35cd875d0e7a46ef7f88207de8d57..322649dc0663925a536516a9cab569d8725d9737 100644 (file)
@@ -1,7 +1,7 @@
 LIBS = -lm
 EXE_SUFFIX=
 DLL_SUFFIX=
-PLAF_DLL_OBJS += vm/os-windows-nt.o
+PLAF_DLL_OBJS += vm/os-windows-nt.o vm/mvm-windows-nt.o
 PLAF_EXE_OBJS += vm/resources.o
 PLAF_EXE_OBJS += vm/main-windows-nt.o
 CFLAGS += -mwindows
index 44365859e26217f36ad7dcd37cd1a67e1ffa7563..da70fa134ea984ee1a92a53f51684dea436b0467 100755 (executable)
@@ -13,7 +13,7 @@ char *factor_vm::pinned_alien_offset(cell obj)
                {
                        alien *ptr = untag<alien>(obj);
                        if(to_boolean(ptr->expired))
-                               general_error(ERROR_EXPIRED,obj,false_object,NULL);
+                               general_error(ERROR_EXPIRED,obj,false_object);
                        if(to_boolean(ptr->base))
                                type_error(ALIEN_TYPE,obj);
                        else
old mode 100644 (file)
new mode 100755 (executable)
index 416c139..38479a3
@@ -19,7 +19,25 @@ void factor_vm::init_callbacks(cell size)
        callbacks = new callback_heap(size,this);
 }
 
-void callback_heap::store_callback_operand(code_block *stub, cell index, cell value)
+bool callback_heap::setup_seh_p()
+{
+#if defined(WINDOWS) && defined(FACTOR_X86)
+       return true;
+#else
+       return false;
+#endif
+}
+
+bool callback_heap::return_takes_param_p()
+{
+#if defined(FACTOR_X86) || defined(FACTOR_AMD64)
+       return true;
+#else
+       return false;
+#endif
+}
+
+instruction_operand callback_heap::callback_operand(code_block *stub, cell index)
 {
        tagged<array> code_template(parent->special_objects[CALLBACK_STUB]);
 
@@ -33,12 +51,23 @@ void callback_heap::store_callback_operand(code_block *stub, cell index, cell va
                offset);
 
        instruction_operand op(rel,stub,0);
-       op.store_value(value);
+
+       return op;
+}
+
+void callback_heap::store_callback_operand(code_block *stub, cell index)
+{
+       parent->store_external_address(callback_operand(stub,index));
+}
+
+void callback_heap::store_callback_operand(code_block *stub, cell index, cell value)
+{
+       callback_operand(stub,index).store_value(value);
 }
 
 void callback_heap::update(code_block *stub)
 {
-       store_callback_operand(stub,1,(cell)callback_entry_point(stub));
+       store_callback_operand(stub,setup_seh_p() ? 2 : 1,(cell)callback_entry_point(stub));
        stub->flush_icache();
 }
 
@@ -65,11 +94,23 @@ code_block *callback_heap::add(cell owner, cell return_rewind)
        /* Store VM pointer */
        store_callback_operand(stub,0,(cell)parent);
 
+       cell index;
+
+       if(setup_seh_p())
+       {
+               store_callback_operand(stub,1);
+               index = 1;
+       }
+       else
+               index = 0;
+
+       /* Store VM pointer */
+       store_callback_operand(stub,index + 2,(cell)parent);
+
        /* On x86, the RET instruction takes an argument which depends on
        the callback's calling convention */
-#if defined(FACTOR_X86) || defined(FACTOR_AMD64)
-       store_callback_operand(stub,2,return_rewind);
-#endif
+       if(return_takes_param_p())
+               store_callback_operand(stub,index + 3,return_rewind);
 
        update(stub);
 
index 607984ad233c9136c927bdf2c084136c394433e2..a0ab3d6bf965b2ea77527dcdc9781105d89294d3 100644 (file)
@@ -38,6 +38,10 @@ struct callback_heap {
                return w->entry_point;
        }
 
+       bool setup_seh_p();
+       bool return_takes_param_p();
+       instruction_operand callback_operand(code_block *stub, cell index);
+       void store_callback_operand(code_block *stub, cell index);
        void store_callback_operand(code_block *stub, cell index, cell value);
 
        void update(code_block *stub);
index 195b212d8b3899b1b741a39e19c7a20af58ca9ad..ad7528ab84c2b8e2f8c2c5a76498181b026de6cf 100755 (executable)
@@ -13,16 +13,22 @@ void factor_vm::check_frame(stack_frame *frame)
 
 callstack *factor_vm::allot_callstack(cell size)
 {
-       callstack *stack = allot<callstack>(callstack_size(size));
+       callstack *stack = allot<callstack>(callstack_object_size(size));
        stack->length = tag_fixnum(size);
        return stack;
 }
 
-stack_frame *factor_vm::fix_callstack_top(stack_frame *top, stack_frame *bottom)
+/* If 'stack' points into the middle of the frame, find the nearest valid stack
+pointer where we can resume execution and hope to capture the call trace without
+crashing. Also, make sure we have at least 'stack_reserved' bytes available so
+that we don't run out of callstack space while handling the error. */
+stack_frame *factor_vm::fix_callstack_top(stack_frame *stack)
 {
-       stack_frame *frame = bottom - 1;
+       stack_frame *frame = ctx->callstack_bottom - 1;
 
-       while(frame >= top)
+       while(frame >= stack
+               && frame >= ctx->callstack_top
+               && (cell)frame >= ctx->callstack_seg->start + stack_reserved)
                frame = frame_successor(frame);
 
        return frame + 1;
@@ -36,7 +42,7 @@ This means that if 'callstack' is called in tail position, we
 will have popped a necessary frame... however this word is only
 called by continuation implementation, and user code shouldn't
 be calling it at all, so we leave it as it is for now. */
-stack_frame *factor_vm::second_from_top_stack_frame()
+stack_frame *factor_vm::second_from_top_stack_frame(context *ctx)
 {
        stack_frame *frame = ctx->callstack_bottom - 1;
        while(frame >= ctx->callstack_top
@@ -48,16 +54,27 @@ stack_frame *factor_vm::second_from_top_stack_frame()
        return frame + 1;
 }
 
-void factor_vm::primitive_callstack()
+cell factor_vm::capture_callstack(context *ctx)
 {
-       stack_frame *top = second_from_top_stack_frame();
+       stack_frame *top = second_from_top_stack_frame(ctx);
        stack_frame *bottom = ctx->callstack_bottom;
 
        fixnum size = std::max((fixnum)0,(fixnum)bottom - (fixnum)top);
 
        callstack *stack = allot_callstack(size);
        memcpy(stack->top(),top,size);
-       ctx->push(tag<callstack>(stack));
+       return tag<callstack>(stack);
+}
+
+void factor_vm::primitive_callstack()
+{
+       ctx->push(capture_callstack(ctx));
+}
+
+void factor_vm::primitive_callstack_for()
+{
+       context *other_ctx = (context *)pinned_alien_offset(ctx->pop());
+       ctx->push(capture_callstack(other_ctx));
 }
 
 code_block *factor_vm::frame_code(stack_frame *frame)
index 9f8867447cc1686dea09a2331c20017c825eeccc..9f0693eb7648036ee0d9ecf03cb1af650ef293a2 100755 (executable)
@@ -1,7 +1,7 @@
 namespace factor
 {
 
-inline static cell callstack_size(cell size)
+inline static cell callstack_object_size(cell size)
 {
        return sizeof(callstack) + size;
 }
index ac5d140783f45d62691a1bba121607b6a065c90b..deaa41e4b8ef7b282ffdae7b1cabefab41c1fcaa 100644 (file)
@@ -114,7 +114,7 @@ template<typename Visitor>
 void code_block_visitor<Visitor>::visit_context_code_blocks()
 {
        call_frame_code_block_visitor<Visitor> call_frame_visitor(parent,visitor);
-       parent->iterate_active_frames(call_frame_visitor);
+       parent->iterate_active_callstacks(call_frame_visitor);
 }
 
 template<typename Visitor>
index e002b26afcfeee0e40bf1f41128e48dbf30cd9a2..de103cda125506406c48c784cda36481ace4e23e 100755 (executable)
@@ -144,12 +144,12 @@ void factor_vm::update_word_references(code_block *compiled, bool reset_inline_c
 image load */
 void factor_vm::undefined_symbol()
 {
-       general_error(ERROR_UNDEFINED_SYMBOL,false_object,false_object,NULL);
+       general_error(ERROR_UNDEFINED_SYMBOL,false_object,false_object);
 }
 
 void undefined_symbol()
 {
-       return tls_vm()->undefined_symbol();
+       return current_vm()->undefined_symbol();
 }
 
 /* Look up an external library symbol referenced by a compiled code block */
@@ -225,6 +225,11 @@ void factor_vm::store_external_address(instruction_operand op)
        case RT_DECKS_OFFSET:
                op.store_value(decks_offset);
                break;
+#ifdef WINDOWS
+       case RT_EXCEPTION_HANDLER:
+               op.store_value((cell)&factor::exception_handler);
+               break;
+#endif
        default:
                critical_error("Bad rel type",op.rel_type());
                break;
index ece4926c281464e7ae1ad66b368ef9ba2d12b14a..0b8b473e8b3704fd10c5487e1e09c6c551bdfba9 100644 (file)
@@ -1,6 +1,8 @@
 namespace factor
 {
 
+struct must_start_gc_again {};
+
 template<typename TargetGeneration, typename Policy> struct data_workhorse {
        factor_vm *parent;
        TargetGeneration *target;
@@ -27,8 +29,7 @@ template<typename TargetGeneration, typename Policy> struct data_workhorse {
        {
                cell size = untagged->size();
                object *newpointer = target->allot(size);
-               /* XXX not exception-safe */
-               if(!newpointer) longjmp(parent->current_gc->gc_unwind,1);
+               if(!newpointer) throw must_start_gc_again();
 
                memcpy(newpointer,untagged,size);
                untagged->forward_to(newpointer);
index 1079c572d2de756ed15b54de6d9e45ec28b66975..25fe0e5280cc43a82617111119e981303ec6424b 100644 (file)
@@ -3,28 +3,32 @@
 namespace factor
 {
 
-context::context(cell ds_size, cell rs_size) :
+context::context(cell datastack_size, cell retainstack_size, cell callstack_size) :
        callstack_top(NULL),
        callstack_bottom(NULL),
        datastack(0),
        retainstack(0),
-       datastack_region(new segment(ds_size,false)),
-       retainstack_region(new segment(rs_size,false)),
-       next(NULL)
+       callstack_save(0),
+       datastack_seg(new segment(datastack_size,false)),
+       retainstack_seg(new segment(retainstack_size,false)),
+       callstack_seg(new segment(callstack_size,false))
 {
-       reset_datastack();
-       reset_retainstack();
-       reset_context_objects();
+       reset();
 }
 
 void context::reset_datastack()
 {
-       datastack = datastack_region->start - sizeof(cell);
+       datastack = datastack_seg->start - sizeof(cell);
 }
 
 void context::reset_retainstack()
 {
-       retainstack = retainstack_region->start - sizeof(cell);
+       retainstack = retainstack_seg->start - sizeof(cell);
+}
+
+void context::reset_callstack()
+{
+       callstack_top = callstack_bottom = CALLSTACK_BOTTOM(this);
 }
 
 void context::reset_context_objects()
@@ -32,68 +36,133 @@ void context::reset_context_objects()
        memset_cell(context_objects,false_object,context_object_count * sizeof(cell));
 }
 
-context *factor_vm::alloc_context()
+void context::reset()
+{
+       reset_datastack();
+       reset_retainstack();
+       reset_callstack();
+       reset_context_objects();
+}
+
+void context::fix_stacks()
+{
+       if(datastack + sizeof(cell) < datastack_seg->start
+               || datastack + stack_reserved >= datastack_seg->end)
+               reset_datastack();
+
+       if(retainstack + sizeof(cell) < retainstack_seg->start
+               || retainstack + stack_reserved >= retainstack_seg->end)
+               reset_retainstack();
+}
+
+context::~context()
+{
+       delete datastack_seg;
+       delete retainstack_seg;
+       delete callstack_seg;
+}
+
+/* called on startup */
+void factor_vm::init_contexts(cell datastack_size_, cell retainstack_size_, cell callstack_size_)
+{
+       datastack_size = datastack_size_;
+       retainstack_size = retainstack_size_;
+       callstack_size = callstack_size_;
+
+       ctx = NULL;
+       spare_ctx = new_context();
+}
+
+void factor_vm::delete_contexts()
+{
+       assert(!ctx);
+       std::vector<context *>::const_iterator iter = unused_contexts.begin();
+       std::vector<context *>::const_iterator end = unused_contexts.end();
+       while(iter != end)
+       {
+               delete *iter;
+               iter++;
+       }
+}
+
+context *factor_vm::new_context()
 {
        context *new_context;
 
-       if(unused_contexts)
+       if(unused_contexts.empty())
        {
-               new_context = unused_contexts;
-               unused_contexts = unused_contexts->next;
+               new_context = new context(datastack_size,
+                       retainstack_size,
+                       callstack_size);
        }
        else
-               new_context = new context(ds_size,rs_size);
+       {
+               new_context = unused_contexts.back();
+               unused_contexts.pop_back();
+       }
+
+       new_context->reset();
+
+       active_contexts.insert(new_context);
+
+       return new_context;
+}
 
+void factor_vm::init_context(context *ctx)
+{
+       ctx->context_objects[OBJ_CONTEXT] = allot_alien(ctx);
+}
+
+context *new_context(factor_vm *parent)
+{
+       context *new_context = parent->new_context();
+       parent->init_context(new_context);
        return new_context;
 }
 
-void factor_vm::dealloc_context(context *old_context)
+void factor_vm::delete_context(context *old_context)
+{
+       unused_contexts.push_back(old_context);
+       active_contexts.erase(old_context);
+}
+
+VM_C_API void delete_context(factor_vm *parent, context *old_context)
 {
-       old_context->next = unused_contexts;
-       unused_contexts = old_context;
+       parent->delete_context(old_context);
 }
 
-/* called on entry into a compiled callback */
-void factor_vm::nest_stacks()
+cell factor_vm::begin_callback(cell quot_)
 {
-       context *new_ctx = alloc_context();
+       data_root<object> quot(quot_,this);
 
-       new_ctx->callstack_bottom = (stack_frame *)-1;
-       new_ctx->callstack_top = (stack_frame *)-1;
+       ctx->reset();
+       spare_ctx = new_context();
+       callback_ids.push_back(callback_id++);
 
-       new_ctx->reset_datastack();
-       new_ctx->reset_retainstack();
-       new_ctx->reset_context_objects();
+       init_context(ctx);
 
-       new_ctx->next = ctx;
-       ctx = new_ctx;
+       return quot.value();
 }
 
-void nest_stacks(factor_vm *parent)
+cell begin_callback(factor_vm *parent, cell quot)
 {
-       return parent->nest_stacks();
+       return parent->begin_callback(quot);
 }
 
-/* called when leaving a compiled callback */
-void factor_vm::unnest_stacks()
+void factor_vm::end_callback()
 {
-       context *old_ctx = ctx;
-       ctx = old_ctx->next;
-       dealloc_context(old_ctx);
+       callback_ids.pop_back();
+       delete_context(ctx);
 }
 
-void unnest_stacks(factor_vm *parent)
+void end_callback(factor_vm *parent)
 {
-       return parent->unnest_stacks();
+       parent->end_callback();
 }
 
-/* called on startup */
-void factor_vm::init_stacks(cell ds_size_, cell rs_size_)
+void factor_vm::primitive_current_callback()
 {
-       ds_size = ds_size_;
-       rs_size = rs_size_;
-       ctx = NULL;
-       unused_contexts = NULL;
+       ctx->push(tag_fixnum(callback_ids.back()));
 }
 
 void factor_vm::primitive_context_object()
@@ -109,31 +178,71 @@ void factor_vm::primitive_set_context_object()
        ctx->context_objects[n] = value;
 }
 
-bool factor_vm::stack_to_array(cell bottom, cell top)
+void factor_vm::primitive_context_object_for()
+{
+       context *other_ctx = (context *)pinned_alien_offset(ctx->pop());
+       fixnum n = untag_fixnum(ctx->pop());
+       ctx->push(other_ctx->context_objects[n]);
+}
+
+cell factor_vm::stack_to_array(cell bottom, cell top)
 {
        fixnum depth = (fixnum)(top - bottom + sizeof(cell));
 
        if(depth < 0)
-               return false;
+               return false_object;
        else
        {
                array *a = allot_uninitialized_array<array>(depth / sizeof(cell));
                memcpy(a + 1,(void*)bottom,depth);
-               ctx->push(tag<array>(a));
-               return true;
+               return tag<array>(a);
        }
 }
 
+cell factor_vm::datastack_to_array(context *ctx)
+{
+       cell array = stack_to_array(ctx->datastack_seg->start,ctx->datastack);
+       if(array == false_object)
+       {
+               general_error(ERROR_DATASTACK_UNDERFLOW,false_object,false_object);
+               return false_object;
+       }
+       else
+               return array;
+}
+
 void factor_vm::primitive_datastack()
 {
-       if(!stack_to_array(ctx->datastack_region->start,ctx->datastack))
-               general_error(ERROR_DS_UNDERFLOW,false_object,false_object,NULL);
+       ctx->push(datastack_to_array(ctx));
+}
+
+void factor_vm::primitive_datastack_for()
+{
+       context *other_ctx = (context *)pinned_alien_offset(ctx->pop());
+       ctx->push(datastack_to_array(other_ctx));
+}
+
+cell factor_vm::retainstack_to_array(context *ctx)
+{
+       cell array = stack_to_array(ctx->retainstack_seg->start,ctx->retainstack);
+       if(array == false_object)
+       {
+               general_error(ERROR_RETAINSTACK_UNDERFLOW,false_object,false_object);
+               return false_object;
+       }
+       else
+               return array;
 }
 
 void factor_vm::primitive_retainstack()
 {
-       if(!stack_to_array(ctx->retainstack_region->start,ctx->retainstack))
-               general_error(ERROR_RS_UNDERFLOW,false_object,false_object,NULL);
+       ctx->push(retainstack_to_array(ctx));
+}
+
+void factor_vm::primitive_retainstack_for()
+{
+       context *other_ctx = (context *)pinned_alien_offset(ctx->pop());
+       ctx->push(retainstack_to_array(other_ctx));
 }
 
 /* returns pointer to top of stack */
@@ -144,14 +253,24 @@ cell factor_vm::array_to_stack(array *array, cell bottom)
        return bottom + depth - sizeof(cell);
 }
 
+void factor_vm::set_datastack(context *ctx, array *array)
+{
+       ctx->datastack = array_to_stack(array,ctx->datastack_seg->start);
+}
+
 void factor_vm::primitive_set_datastack()
 {
-       ctx->datastack = array_to_stack(untag_check<array>(ctx->pop()),ctx->datastack_region->start);
+       set_datastack(ctx,untag_check<array>(ctx->pop()));
+}
+
+void factor_vm::set_retainstack(context *ctx, array *array)
+{
+       ctx->retainstack = array_to_stack(array,ctx->retainstack_seg->start);
 }
 
 void factor_vm::primitive_set_retainstack()
 {
-       ctx->retainstack = array_to_stack(untag_check<array>(ctx->pop()),ctx->retainstack_region->start);
+       set_retainstack(ctx,untag_check<array>(ctx->pop()));
 }
 
 /* Used to implement call( */
@@ -162,12 +281,12 @@ void factor_vm::primitive_check_datastack()
        fixnum height = out - in;
        array *saved_datastack = untag_check<array>(ctx->pop());
        fixnum saved_height = array_capacity(saved_datastack);
-       fixnum current_height = (ctx->datastack - ctx->datastack_region->start + sizeof(cell)) / sizeof(cell);
+       fixnum current_height = (ctx->datastack - ctx->datastack_seg->start + sizeof(cell)) / sizeof(cell);
        if(current_height - height != saved_height)
                ctx->push(false_object);
        else
        {
-               cell *ds_bot = (cell *)ctx->datastack_region->start;
+               cell *ds_bot = (cell *)ctx->datastack_seg->start;
                for(fixnum i = 0; i < saved_height - in; i++)
                {
                        if(ds_bot[i] != array_nth(saved_datastack,i))
index e555bd4a92ec41099f6b38396abafcd2a360f868..582fab173f9bc7a0c7b3c89c161d50ba5b10fca0 100644 (file)
@@ -6,12 +6,16 @@ static const cell context_object_count = 10;
 enum context_object {
        OBJ_NAMESTACK,
        OBJ_CATCHSTACK,
-       OBJ_CONTEXT_ID,
+       OBJ_CONTEXT,
 };
 
-/* Assembly code makes assumptions about the layout of this struct */
+static const cell stack_reserved = 1024;
+
 struct context {
-       /* C stack pointer on entry */
+
+       // First 4 fields accessed directly by compiler. See basis/vm/vm.factor
+
+       /* Factor callstack pointers */
        stack_frame *callstack_top;
        stack_frame *callstack_bottom;
 
@@ -21,22 +25,26 @@ struct context {
        /* current retain stack top pointer */
        cell retainstack;
 
-       /* memory region holding current datastack */
-       segment *datastack_region;
+       /* C callstack pointer */
+       cell callstack_save;
 
-       /* memory region holding current retain stack */
-       segment *retainstack_region;
+       segment *datastack_seg;
+       segment *retainstack_seg;
+       segment *callstack_seg;
 
        /* context-specific special objects, accessed by context-object and
        set-context-object primitives */
        cell context_objects[context_object_count];
 
-       context *next;
+       context(cell datastack_size, cell retainstack_size, cell callstack_size);
+       ~context();
 
-       context(cell ds_size, cell rs_size);
        void reset_datastack();
        void reset_retainstack();
+       void reset_callstack();
        void reset_context_objects();
+       void reset();
+       void fix_stacks();
 
        cell peek()
        {
@@ -60,22 +68,11 @@ struct context {
                datastack += sizeof(cell);
                replace(tagged);
        }
-
-       static const cell stack_reserved = (64 * sizeof(cell));
-
-       void fix_stacks()
-       {
-               if(datastack + sizeof(cell) < datastack_region->start
-                       || datastack + stack_reserved >= datastack_region->end)
-                       reset_datastack();
-
-               if(retainstack + sizeof(cell) < retainstack_region->start
-                       || retainstack + stack_reserved >= retainstack_region->end)
-                       reset_retainstack();
-       }
 };
 
-VM_C_API void nest_stacks(factor_vm *vm);
-VM_C_API void unnest_stacks(factor_vm *vm);
+VM_C_API context *new_context(factor_vm *parent);
+VM_C_API void delete_context(factor_vm *parent, context *old_context);
+VM_C_API cell begin_callback(factor_vm *parent, cell quot);
+VM_C_API void end_callback(factor_vm *parent);
 
 }
index d09fc173ea5bcc1348d783ec811b825cac9df6d9..e6244e366e304475e730fc55fceb73d4b3d93f5c 100644 (file)
@@ -3,6 +3,8 @@ namespace factor
 
 #define FACTOR_CPU_STRING "ppc"
 
+#define CALLSTACK_BOTTOM(ctx) (stack_frame *)(ctx->callstack_seg->end - 32)
+
 /* In the instruction sequence:
 
    LOAD32 r3,...
old mode 100644 (file)
new mode 100755 (executable)
index ac8ac51..89d7fb7
@@ -5,6 +5,8 @@ namespace factor
 
 #define FRAME_RETURN_ADDRESS(frame,vm) *(void **)(vm->frame_successor(frame) + 1)
 
+#define CALLSTACK_BOTTOM(ctx) (stack_frame *)(ctx->callstack_seg->end - sizeof(cell) * 5)
+
 inline static void flush_icache(cell start, cell len) {}
 
 /* In the instruction sequence:
index 22ef39e8681f54d3f9f886bf1f04c5da5cc2b598..9b28215bb835d7a236b2a7837a6796b3ebb1dd97 100755 (executable)
@@ -159,7 +159,7 @@ cell object::size() const
        case WRAPPER_TYPE:
                return align(sizeof(wrapper),data_alignment);
        case CALLSTACK_TYPE:
-               return align(callstack_size(untag_fixnum(((callstack *)this)->length)),data_alignment);
+               return align(callstack_object_size(untag_fixnum(((callstack *)this)->length)),data_alignment);
        default:
                critical_error("Invalid header",(cell)this);
                return 0; /* can't happen */
index e82394951a0682315500c14b25300d48dffa1ca1..85335d49ae7f344fbb491ab1aa23b69d0954ff9b 100755 (executable)
@@ -145,13 +145,13 @@ void factor_vm::print_objects(cell *start, cell *end)
 void factor_vm::print_datastack()
 {
        std::cout << "==== DATA STACK:\n";
-       print_objects((cell *)ctx->datastack_region->start,(cell *)ctx->datastack);
+       print_objects((cell *)ctx->datastack_seg->start,(cell *)ctx->datastack);
 }
 
 void factor_vm::print_retainstack()
 {
        std::cout << "==== RETAIN STACK:\n";
-       print_objects((cell *)ctx->retainstack_region->start,(cell *)ctx->retainstack);
+       print_objects((cell *)ctx->retainstack_seg->start,(cell *)ctx->retainstack);
 }
 
 struct stack_frame_printer {
@@ -421,9 +421,9 @@ void factor_vm::factorbug()
                else if(strcmp(cmd,"t") == 0)
                        full_output = !full_output;
                else if(strcmp(cmd,"s") == 0)
-                       dump_memory(ctx->datastack_region->start,ctx->datastack);
+                       dump_memory(ctx->datastack_seg->start,ctx->datastack);
                else if(strcmp(cmd,"r") == 0)
-                       dump_memory(ctx->retainstack_region->start,ctx->retainstack);
+                       dump_memory(ctx->retainstack_seg->start,ctx->retainstack);
                else if(strcmp(cmd,".s") == 0)
                        print_datastack();
                else if(strcmp(cmd,".r") == 0)
index ae560012aa6f49902c5dbc123e437b4361e3b341..1867965108e04be7676cf9f5586e30bdc8bbb986 100755 (executable)
@@ -17,18 +17,20 @@ void critical_error(const char *msg, cell tagged)
        std::cout << "critical_error: " << msg;
        std::cout << ": " << std::hex << tagged << std::dec;
        std::cout << std::endl;
-       tls_vm()->factorbug();
+       current_vm()->factorbug();
 }
 
 void out_of_memory()
 {
        std::cout << "Out of memory\n\n";
-       tls_vm()->dump_generations();
+       current_vm()->dump_generations();
        exit(1);
 }
 
-void factor_vm::throw_error(cell error, stack_frame *callstack_top)
+void factor_vm::throw_error(cell error, stack_frame *stack)
 {
+       assert(stack);
+
        /* If the error handler is set, we rewind any C stack frames and
        pass the error to user-space. */
        if(!current_gc && to_boolean(special_objects[ERROR_HANDLER_QUOT]))
@@ -41,22 +43,13 @@ void factor_vm::throw_error(cell error, stack_frame *callstack_top)
                bignum_roots.clear();
                code_roots.clear();
 
-               /* If we had an underflow or overflow, stack pointers might be
-               out of bounds */
+               /* If we had an underflow or overflow, data or retain stack
+               pointers might be out of bounds */
                ctx->fix_stacks();
 
                ctx->push(error);
 
-               /* Errors thrown from C code pass NULL for this parameter.
-               Errors thrown from Factor code, or signal handlers, pass the
-               actual stack pointer at the time, since the saved pointer is
-               not necessarily up to date at that point. */
-               if(callstack_top)
-                       callstack_top = fix_callstack_top(callstack_top,ctx->callstack_bottom);
-               else
-                       callstack_top = ctx->callstack_top;
-
-               unwind_native_frames(special_objects[ERROR_HANDLER_QUOT],callstack_top);
+               unwind_native_frames(special_objects[ERROR_HANDLER_QUOT],stack);
        }
        /* Error was thrown in early startup before error handler is set, just
        crash. */
@@ -70,67 +63,61 @@ void factor_vm::throw_error(cell error, stack_frame *callstack_top)
        }
 }
 
-void factor_vm::general_error(vm_error_type error, cell arg1, cell arg2, stack_frame *callstack_top)
+void factor_vm::general_error(vm_error_type error, cell arg1, cell arg2, stack_frame *stack)
 {
        throw_error(allot_array_4(special_objects[OBJ_ERROR],
-               tag_fixnum(error),arg1,arg2),callstack_top);
+               tag_fixnum(error),arg1,arg2),stack);
 }
 
-void factor_vm::type_error(cell type, cell tagged)
+void factor_vm::general_error(vm_error_type error, cell arg1, cell arg2)
 {
-       general_error(ERROR_TYPE,tag_fixnum(type),tagged,NULL);
+       throw_error(allot_array_4(special_objects[OBJ_ERROR],
+               tag_fixnum(error),arg1,arg2),ctx->callstack_top);
 }
 
-void factor_vm::not_implemented_error()
+void factor_vm::type_error(cell type, cell tagged)
 {
-       general_error(ERROR_NOT_IMPLEMENTED,false_object,false_object,NULL);
+       general_error(ERROR_TYPE,tag_fixnum(type),tagged);
 }
 
-/* Test if 'fault' is in the guard page at the top or bottom (depending on
-offset being 0 or -1) of area+area_size */
-bool factor_vm::in_page(cell fault, cell area, cell area_size, int offset)
+void factor_vm::not_implemented_error()
 {
-       int pagesize = getpagesize();
-       area += area_size;
-       area += offset * pagesize;
-
-       return fault >= area && fault <= area + pagesize;
+       general_error(ERROR_NOT_IMPLEMENTED,false_object,false_object);
 }
 
-void factor_vm::memory_protection_error(cell addr, stack_frame *native_stack)
+void factor_vm::memory_protection_error(cell addr, stack_frame *stack)
 {
-       if(in_page(addr, ctx->datastack_region->start, 0, -1))
-               general_error(ERROR_DS_UNDERFLOW,false_object,false_object,native_stack);
-       else if(in_page(addr, ctx->datastack_region->start, ds_size, 0))
-               general_error(ERROR_DS_OVERFLOW,false_object,false_object,native_stack);
-       else if(in_page(addr, ctx->retainstack_region->start, 0, -1))
-               general_error(ERROR_RS_UNDERFLOW,false_object,false_object,native_stack);
-       else if(in_page(addr, ctx->retainstack_region->start, rs_size, 0))
-               general_error(ERROR_RS_OVERFLOW,false_object,false_object,native_stack);
-       else if(in_page(addr, nursery.end, 0, 0))
-               critical_error("allot_object() missed GC check",0);
+       /* Retain and call stack underflows are not supposed to happen */
+
+       if(ctx->datastack_seg->underflow_p(addr))
+               general_error(ERROR_DATASTACK_UNDERFLOW,false_object,false_object,stack);
+       else if(ctx->datastack_seg->overflow_p(addr))
+               general_error(ERROR_DATASTACK_OVERFLOW,false_object,false_object,stack);
+       else if(ctx->retainstack_seg->underflow_p(addr))
+               general_error(ERROR_RETAINSTACK_UNDERFLOW,false_object,false_object,stack);
+       else if(ctx->retainstack_seg->overflow_p(addr))
+               general_error(ERROR_RETAINSTACK_OVERFLOW,false_object,false_object,stack);
+       else if(ctx->callstack_seg->underflow_p(addr))
+               general_error(ERROR_CALLSTACK_OVERFLOW,false_object,false_object,stack);
+       else if(ctx->callstack_seg->overflow_p(addr))
+               general_error(ERROR_CALLSTACK_UNDERFLOW,false_object,false_object,stack);
        else
-               general_error(ERROR_MEMORY,allot_cell(addr),false_object,native_stack);
+               general_error(ERROR_MEMORY,allot_cell(addr),false_object,stack);
 }
 
-void factor_vm::signal_error(cell signal, stack_frame *native_stack)
+void factor_vm::signal_error(cell signal, stack_frame *stack)
 {
-       general_error(ERROR_SIGNAL,allot_cell(signal),false_object,native_stack);
+       general_error(ERROR_SIGNAL,allot_cell(signal),false_object,stack);
 }
 
 void factor_vm::divide_by_zero_error()
 {
-       general_error(ERROR_DIVIDE_BY_ZERO,false_object,false_object,NULL);
-}
-
-void factor_vm::fp_trap_error(unsigned int fpu_status, stack_frame *signal_callstack_top)
-{
-       general_error(ERROR_FP_TRAP,tag_fixnum(fpu_status),false_object,signal_callstack_top);
+       general_error(ERROR_DIVIDE_BY_ZERO,false_object,false_object);
 }
 
-void factor_vm::primitive_call_clear()
+void factor_vm::fp_trap_error(unsigned int fpu_status, stack_frame *stack)
 {
-       unwind_native_frames(ctx->pop(),ctx->callstack_bottom);
+       general_error(ERROR_FP_TRAP,tag_fixnum(fpu_status),false_object,stack);
 }
 
 /* For testing purposes */
@@ -146,7 +133,7 @@ void factor_vm::memory_signal_handler_impl()
 
 void memory_signal_handler_impl()
 {
-       tls_vm()->memory_signal_handler_impl();
+       current_vm()->memory_signal_handler_impl();
 }
 
 void factor_vm::misc_signal_handler_impl()
@@ -156,7 +143,7 @@ void factor_vm::misc_signal_handler_impl()
 
 void misc_signal_handler_impl()
 {
-       tls_vm()->misc_signal_handler_impl();
+       current_vm()->misc_signal_handler_impl();
 }
 
 void factor_vm::fp_signal_handler_impl()
@@ -166,7 +153,7 @@ void factor_vm::fp_signal_handler_impl()
 
 void fp_signal_handler_impl()
 {
-       tls_vm()->fp_signal_handler_impl();
+       current_vm()->fp_signal_handler_impl();
 }
 
 }
index 4b237e03a023c707fec6fc49cbe1e2ca3da37f68..34a23bd46dbda3b49f92dbd55072e9f355fc86cf 100755 (executable)
@@ -14,10 +14,12 @@ enum vm_error_type
        ERROR_C_STRING,
        ERROR_FFI,
        ERROR_UNDEFINED_SYMBOL,
-       ERROR_DS_UNDERFLOW,
-       ERROR_DS_OVERFLOW,
-       ERROR_RS_UNDERFLOW,
-       ERROR_RS_OVERFLOW,
+       ERROR_DATASTACK_UNDERFLOW,
+       ERROR_DATASTACK_OVERFLOW,
+       ERROR_RETAINSTACK_UNDERFLOW,
+       ERROR_RETAINSTACK_OVERFLOW,
+       ERROR_CALLSTACK_UNDERFLOW,
+       ERROR_CALLSTACK_OVERFLOW,
        ERROR_MEMORY,
        ERROR_FP_TRAP,
 };
index 4433095173b74b54c949a9fa3cd5e48de2afc481..89da7a2db7be4a0ea6c93204dc50d01f0c1d104c 100755 (executable)
@@ -3,19 +3,23 @@
 namespace factor
 {
 
-std::map<THREADHANDLE, factor_vm*> thread_vms;
-
 void init_globals()
 {
-       init_platform_globals();
+       init_mvm();
 }
 
 void factor_vm::default_parameters(vm_parameters *p)
 {
        p->image_path = NULL;
 
-       p->ds_size = 32 * sizeof(cell);
-       p->rs_size = 32 * sizeof(cell);
+       p->datastack_size = 32 * sizeof(cell);
+       p->retainstack_size = 32 * sizeof(cell);
+
+#ifdef FACTOR_PPC
+       p->callstack_size = 256 * sizeof(cell);
+#else
+       p->callstack_size = 128 * sizeof(cell);
+#endif
 
        p->code_size = 8 * sizeof(cell);
        p->young_size = sizeof(cell) / 4;
@@ -59,8 +63,9 @@ void factor_vm::init_parameters_from_args(vm_parameters *p, int argc, vm_char **
        {
                vm_char *arg = argv[i];
                if(STRCMP(arg,STRING_LITERAL("--")) == 0) break;
-               else if(factor_arg(arg,STRING_LITERAL("-datastack=%d"),&p->ds_size));
-               else if(factor_arg(arg,STRING_LITERAL("-retainstack=%d"),&p->rs_size));
+               else if(factor_arg(arg,STRING_LITERAL("-datastack=%d"),&p->datastack_size));
+               else if(factor_arg(arg,STRING_LITERAL("-retainstack=%d"),&p->retainstack_size));
+               else if(factor_arg(arg,STRING_LITERAL("-callstack=%d"),&p->callstack_size));
                else if(factor_arg(arg,STRING_LITERAL("-young=%d"),&p->young_size));
                else if(factor_arg(arg,STRING_LITERAL("-aging=%d"),&p->aging_size));
                else if(factor_arg(arg,STRING_LITERAL("-tenured=%d"),&p->tenured_size));
@@ -91,8 +96,9 @@ void factor_vm::prepare_boot_image()
 void factor_vm::init_factor(vm_parameters *p)
 {
        /* Kilobytes */
-       p->ds_size = align_page(p->ds_size << 10);
-       p->rs_size = align_page(p->rs_size << 10);
+       p->datastack_size = align_page(p->datastack_size << 10);
+       p->retainstack_size = align_page(p->retainstack_size << 10);
+       p->callstack_size = align_page(p->callstack_size << 10);
        p->callback_size = align_page(p->callback_size << 10);
 
        /* Megabytes */
@@ -117,7 +123,7 @@ void factor_vm::init_factor(vm_parameters *p)
 
        srand((unsigned int)system_micros());
        init_ffi();
-       init_stacks(p->ds_size,p->rs_size);
+       init_contexts(p->datastack_size,p->retainstack_size,p->callstack_size);
        init_callbacks(p->callback_size);
        load_image(p);
        init_c_io();
@@ -161,16 +167,12 @@ void factor_vm::start_factor(vm_parameters *p)
 {
        if(p->fep) factorbug();
 
-       nest_stacks();
        c_to_factor_toplevel(special_objects[OBJ_STARTUP_QUOT]);
-       unnest_stacks();
 }
 
 void factor_vm::stop_factor()
 {
-       nest_stacks();
        c_to_factor_toplevel(special_objects[OBJ_SHUTDOWN_QUOT]);
-       unnest_stacks();
 }
 
 char *factor_vm::factor_eval_string(char *string)
@@ -206,11 +208,6 @@ void factor_vm::start_standalone_factor(int argc, vm_char **argv)
        start_factor(&p);
 }
 
-struct startargs {
-       int argc;
-       vm_char **argv;
-};
-
 factor_vm *new_factor_vm()
 {
        factor_vm *newvm = new factor_vm();
@@ -220,28 +217,10 @@ factor_vm *new_factor_vm()
        return newvm;
 }
 
-// arg must be new'ed because we're going to delete it!
-void *start_standalone_factor_thread(void *arg) 
-{
-       factor_vm *newvm = new_factor_vm();
-       startargs *args = (startargs*) arg;
-       int argc = args->argc; vm_char **argv = args->argv;
-       delete args;
-       newvm->start_standalone_factor(argc, argv);
-       return 0;
-}
-
 VM_C_API void start_standalone_factor(int argc, vm_char **argv)
 {
        factor_vm *newvm = new_factor_vm();
        return newvm->start_standalone_factor(argc,argv);
 }
 
-VM_C_API THREADHANDLE start_standalone_factor_in_new_thread(int argc, vm_char **argv)
-{
-       startargs *args = new startargs;
-       args->argc = argc; args->argv = argv; 
-       return start_thread(start_standalone_factor_thread,args);
-}
-
 }
index cec59bcc5c412f4c85738ba7be5add194e8a25ad..f2dd6af0bf5b62b50edfb4b81eefa71c59fdf053 100755 (executable)
@@ -2,7 +2,7 @@ namespace factor
 {
 
 VM_C_API void init_globals();
+factor_vm *new_factor_vm();
 VM_C_API void start_standalone_factor(int argc, vm_char **argv);
-VM_C_API THREADHANDLE start_standalone_factor_in_new_thread(int argc, vm_char **argv);
 
 }
index a57f338c4473db4c59316cff42cbe588b6cebc8a..e01a05aa5ba8e4f5eee3dba8ca8b912c9813c3ab 100755 (executable)
--- a/vm/gc.cpp
+++ b/vm/gc.cpp
@@ -135,49 +135,57 @@ void factor_vm::gc(gc_op op, cell requested_bytes, bool trace_contexts_p)
 
        /* Keep trying to GC higher and higher generations until we don't run out
        of space */
-       if(setjmp(current_gc->gc_unwind))
+       for(;;)
        {
-               /* We come back here if a generation is full */
-               start_gc_again();
-       }
-
-       current_gc->event->op = current_gc->op;
-
-       switch(current_gc->op)
-       {
-       case collect_nursery_op:
-               collect_nursery();
-               break;
-       case collect_aging_op:
-               collect_aging();
-               if(data->high_fragmentation_p())
+               try
                {
-                       current_gc->op = collect_full_op;
-                       current_gc->event->op = collect_full_op;
-                       collect_full(trace_contexts_p);
+                       current_gc->event->op = current_gc->op;
+
+                       switch(current_gc->op)
+                       {
+                       case collect_nursery_op:
+                               collect_nursery();
+                               break;
+                       case collect_aging_op:
+                               collect_aging();
+                               if(data->high_fragmentation_p())
+                               {
+                                       current_gc->op = collect_full_op;
+                                       current_gc->event->op = collect_full_op;
+                                       collect_full(trace_contexts_p);
+                               }
+                               break;
+                       case collect_to_tenured_op:
+                               collect_to_tenured();
+                               if(data->high_fragmentation_p())
+                               {
+                                       current_gc->op = collect_full_op;
+                                       current_gc->event->op = collect_full_op;
+                                       collect_full(trace_contexts_p);
+                               }
+                               break;
+                       case collect_full_op:
+                               collect_full(trace_contexts_p);
+                               break;
+                       case collect_compact_op:
+                               collect_compact(trace_contexts_p);
+                               break;
+                       case collect_growing_heap_op:
+                               collect_growing_heap(requested_bytes,trace_contexts_p);
+                               break;
+                       default:
+                               critical_error("Bad GC op",current_gc->op);
+                               break;
+                       }
+
+                       break;
                }
-               break;
-       case collect_to_tenured_op:
-               collect_to_tenured();
-               if(data->high_fragmentation_p())
+               catch(const must_start_gc_again e)
                {
-                       current_gc->op = collect_full_op;
-                       current_gc->event->op = collect_full_op;
-                       collect_full(trace_contexts_p);
+                       /* We come back here if a generation is full */
+                       start_gc_again();
+                       continue;
                }
-               break;
-       case collect_full_op:
-               collect_full(trace_contexts_p);
-               break;
-       case collect_compact_op:
-               collect_compact(trace_contexts_p);
-               break;
-       case collect_growing_heap_op:
-               collect_growing_heap(requested_bytes,trace_contexts_p);
-               break;
-       default:
-               critical_error("Bad GC op",current_gc->op);
-               break;
        }
 
        end_gc();
index 5224dec3e296c21b515b4d4766095733a028eb0d..5129ced909179996cb829f3850520ed0a7bf5c96 100755 (executable)
--- a/vm/gc.hpp
+++ b/vm/gc.hpp
@@ -45,7 +45,6 @@ struct gc_event {
 struct gc_state {
        gc_op op;
        u64 start_time;
-       jmp_buf gc_unwind;
        gc_event *event;
 
        explicit gc_state(gc_op op_, factor_vm *parent);
index 101482b1dac740dbe905d8d04a986b25ae7e6579..40ffa28d114c4e70b0f248ef2afe127f5a3ee788 100755 (executable)
@@ -30,7 +30,7 @@ struct image_header {
 struct vm_parameters {
        const vm_char *image_path;
        const vm_char *executable_path;
-       cell ds_size, rs_size;
+       cell datastack_size, retainstack_size, callstack_size;
        cell young_size, aging_size, tenured_size;
        cell code_size;
        bool fep;
index dc8aa9d841d24a2f47b275a29aaa5b1ef61565f6..66ffddc24e7771151d80ad9c24026e6a94798918 100644 (file)
@@ -26,6 +26,10 @@ enum relocation_type {
        RT_CARDS_OFFSET,
        /* value of vm->decks_offset */
        RT_DECKS_OFFSET,
+       /* address of exception_handler -- this exists as a separate relocation
+       type since its used in a situation where relocation arguments cannot
+       be passed in, and so RT_DLSYM is inappropriate (Windows only) */
+       RT_EXCEPTION_HANDLER,
 };
 
 enum relocation_class {
@@ -105,6 +109,7 @@ struct relocation_entry {
                case RT_MEGAMORPHIC_CACHE_HITS:
                case RT_CARDS_OFFSET:
                case RT_DECKS_OFFSET:
+               case RT_EXCEPTION_HANDLER:
                        return 0;
                default:
                        critical_error("Bad rel type",rel_type());
index fdd872457efa88030857e6717b08dff1ff89159a..8ce7ff52564ddb66d91d00b998918b328f710a1a 100755 (executable)
--- a/vm/io.cpp
+++ b/vm/io.cpp
@@ -28,7 +28,7 @@ void factor_vm::io_error()
                return;
 #endif
 
-       general_error(ERROR_IO,tag_fixnum(errno),false_object,NULL);
+       general_error(ERROR_IO,tag_fixnum(errno),false_object);
 }
 
 FILE *factor_vm::safe_fopen(char *filename, char *mode)
index 3fa7dcbf078c3aa9534a7b83eaa3a0472015d86b..af14c3a49a963643db39ea74e459216d5913ef83 100644 (file)
@@ -35,19 +35,9 @@ void factor_vm::call_fault_handler(
        MACH_THREAD_STATE_TYPE *thread_state,
        MACH_FLOAT_STATE_TYPE *float_state)
 {
-       /* There is a race condition here, but in practice an exception
-       delivered during stack frame setup/teardown or while transitioning
-       from Factor to C is a sign of things seriously gone wrong, not just
-       a divide by zero or stack underflow in the listener */
-
-       /* Are we in compiled Factor code? Then use the current stack pointer */
-       if(in_code_heap_p(MACH_PROGRAM_COUNTER(thread_state)))
-               signal_callstack_top = (stack_frame *)MACH_STACK_POINTER(thread_state);
-       /* Are we in C? Then use the saved callstack top */
-       else
-               signal_callstack_top = NULL;
+       MACH_STACK_POINTER(thread_state) = (cell)fix_callstack_top((stack_frame *)MACH_STACK_POINTER(thread_state));
 
-       MACH_STACK_POINTER(thread_state) = align_stack_pointer(MACH_STACK_POINTER(thread_state));
+       signal_callstack_top = (stack_frame *)MACH_STACK_POINTER(thread_state);
 
        /* Now we point the program counter at the right handler function. */
        if(exception == EXC_BAD_ACCESS)
@@ -82,11 +72,14 @@ static void call_fault_handler(
        MACH_THREAD_STATE_TYPE *thread_state,
        MACH_FLOAT_STATE_TYPE *float_state)
 {
+       /* Look up the VM instance involved */
        THREADHANDLE thread_id = pthread_from_mach_thread_np(thread);
        assert(thread_id);
        std::map<THREADHANDLE, factor_vm*>::const_iterator vm = thread_vms.find(thread_id);
+
+       /* Handle the exception */
        if (vm != thread_vms.end())
-           vm->second->call_fault_handler(exception,code,exc_state,thread_state,float_state);
+               vm->second->call_fault_handler(exception,code,exc_state,thread_state,float_state);
 }
 
 /* Handle an exception by invoking the user's fault handler and/or forwarding
@@ -100,15 +93,14 @@ catch_exception_raise (mach_port_t exception_port,
        exception_data_t code,
        mach_msg_type_number_t code_count)
 {
-       MACH_EXC_STATE_TYPE exc_state;
-       MACH_THREAD_STATE_TYPE thread_state;
-       MACH_FLOAT_STATE_TYPE float_state;
-       mach_msg_type_number_t exc_state_count, thread_state_count, float_state_count;
+       /* 10.6 likes to report exceptions from child processes too. Ignore those */
+       if(task != mach_task_self()) return KERN_FAILURE;
 
        /* Get fault information and the faulting thread's register contents..
        
        See http://web.mit.edu/darwin/src/modules/xnu/osfmk/man/thread_get_state.html.  */
-       exc_state_count = MACH_EXC_STATE_COUNT;
+       MACH_EXC_STATE_TYPE exc_state;
+       mach_msg_type_number_t exc_state_count = MACH_EXC_STATE_COUNT;
        if (thread_get_state (thread, MACH_EXC_STATE_FLAVOR,
                              (natural_t *)&exc_state, &exc_state_count)
                != KERN_SUCCESS)
@@ -118,7 +110,8 @@ catch_exception_raise (mach_port_t exception_port,
                return KERN_FAILURE;
        }
 
-       thread_state_count = MACH_THREAD_STATE_COUNT;
+       MACH_THREAD_STATE_TYPE thread_state;
+       mach_msg_type_number_t thread_state_count = MACH_THREAD_STATE_COUNT;
        if (thread_get_state (thread, MACH_THREAD_STATE_FLAVOR,
                              (natural_t *)&thread_state, &thread_state_count)
                != KERN_SUCCESS)
@@ -128,7 +121,8 @@ catch_exception_raise (mach_port_t exception_port,
                return KERN_FAILURE;
        }
 
-       float_state_count = MACH_FLOAT_STATE_COUNT;
+       MACH_FLOAT_STATE_TYPE float_state;
+       mach_msg_type_number_t float_state_count = MACH_FLOAT_STATE_COUNT;
        if (thread_get_state (thread, MACH_FLOAT_STATE_FLAVOR,
                              (natural_t *)&float_state, &float_state_count)
                != KERN_SUCCESS)
index dca3d7473cf9b0405cae7f2d11091860b5c494a2..a111a86b699be1d910347f1de2ef28f28adffa84 100755 (executable)
@@ -16,7 +16,6 @@
 #include <fcntl.h>
 #include <limits.h>
 #include <math.h>
-#include <setjmp.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -132,6 +131,7 @@ namespace factor
 #include "jit.hpp"
 #include "quotations.hpp"
 #include "inline_cache.hpp"
+#include "mvm.hpp"
 #include "factor.hpp"
 #include "utilities.hpp"
 
index bb5d9c13c499b026214872e8e75552629b138789..a4622323449742677ce9f37786c019ea8e60f8d3 100755 (executable)
@@ -246,7 +246,7 @@ cell factor_vm::unbox_array_size_slow()
                }
        }
 
-       general_error(ERROR_ARRAY_SIZE,ctx->pop(),tag_fixnum(array_size_max),NULL);
+       general_error(ERROR_ARRAY_SIZE,ctx->pop(),tag_fixnum(array_size_max));
        return 0; /* can't happen */
 }
 
diff --git a/vm/mvm-none.cpp b/vm/mvm-none.cpp
new file mode 100644 (file)
index 0000000..ab1b53a
--- /dev/null
@@ -0,0 +1,28 @@
+#include "master.hpp"
+
+/* Multi-VM threading is not supported on NetBSD due to
+http://gnats.netbsd.org/25563 */
+
+namespace factor
+{
+
+factor_vm *global_vm;
+
+void init_mvm()
+{
+       global_vm = NULL;
+}
+
+void register_vm_with_thread(factor_vm *vm)
+{
+       assert(!global_vm);
+       global_vm = vm;
+}
+
+factor_vm *current_vm()
+{
+       assert(global_vm != NULL);
+       return global_vm;
+}
+
+}
diff --git a/vm/mvm-unix.cpp b/vm/mvm-unix.cpp
new file mode 100644 (file)
index 0000000..adba52b
--- /dev/null
@@ -0,0 +1,26 @@
+#include "master.hpp"
+
+namespace factor
+{
+
+pthread_key_t current_vm_tls_key;
+
+void init_mvm()
+{
+       if(pthread_key_create(&current_vm_tls_key, NULL) != 0)
+               fatal_error("pthread_key_create() failed",0);
+}
+
+void register_vm_with_thread(factor_vm *vm)
+{
+       pthread_setspecific(current_vm_tls_key,vm);
+}
+
+factor_vm *current_vm()
+{
+       factor_vm *vm = (factor_vm*)pthread_getspecific(current_vm_tls_key);
+       assert(vm != NULL);
+       return vm;
+}
+
+}
diff --git a/vm/mvm-windows-nt.cpp b/vm/mvm-windows-nt.cpp
new file mode 100644 (file)
index 0000000..92c2067
--- /dev/null
@@ -0,0 +1,27 @@
+#include "master.hpp"
+
+namespace factor
+{
+
+DWORD current_vm_tls_key; 
+
+void init_mvm()
+{
+       if((current_vm_tls_key = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+               fatal_error("TlsAlloc() failed",0);
+}
+
+void register_vm_with_thread(factor_vm *vm)
+{
+       if(!TlsSetValue(current_vm_tls_key, vm))
+               fatal_error("TlsSetValue() failed",0);
+}
+
+factor_vm *current_vm()
+{
+       factor_vm *vm = (factor_vm *)TlsGetValue(current_vm_tls_key);
+       assert(vm != NULL);
+       return vm;
+}
+
+}
diff --git a/vm/mvm.cpp b/vm/mvm.cpp
new file mode 100644 (file)
index 0000000..df5d85e
--- /dev/null
@@ -0,0 +1,31 @@
+#include "master.hpp"
+
+namespace factor
+{
+
+std::map<THREADHANDLE, factor_vm*> thread_vms;
+
+struct startargs {
+       int argc;
+       vm_char **argv;
+};
+
+// arg must be new'ed because we're going to delete it!
+void *start_standalone_factor_thread(void *arg) 
+{
+       factor_vm *newvm = new_factor_vm();
+       startargs *args = (startargs*) arg;
+       int argc = args->argc; vm_char **argv = args->argv;
+       delete args;
+       newvm->start_standalone_factor(argc, argv);
+       return 0;
+}
+
+VM_C_API THREADHANDLE start_standalone_factor_in_new_thread(int argc, vm_char **argv)
+{
+       startargs *args = new startargs;
+       args->argc = argc; args->argv = argv; 
+       return start_thread(start_standalone_factor_thread,args);
+}
+
+}
diff --git a/vm/mvm.hpp b/vm/mvm.hpp
new file mode 100644 (file)
index 0000000..52430b7
--- /dev/null
@@ -0,0 +1,12 @@
+namespace factor
+{
+
+void init_mvm();
+void register_vm_with_thread(factor_vm *vm);
+factor_vm *current_vm();
+
+VM_C_API THREADHANDLE start_standalone_factor_in_new_thread(int argc, vm_char **argv);
+
+extern std::map<THREADHANDLE, factor_vm *> thread_vms;
+
+}
index 772863d3f1f02cd35c74e33dd9848d6a28ce9c64..778df8642e6ff519dce79f564e02827a5be951dc 100644 (file)
@@ -92,7 +92,7 @@ enum special_object {
        OBJ_RUN_QUEUE = 65,
        OBJ_SLEEP_QUEUE = 66,
 
-       OBJ_VM_COMPILER = 67,    /* version string of the compiler we were built with */
+       OBJ_VM_COMPILER = 67,     /* version string of the compiler we were built with */
 };
 
 /* save-image-and-exit discards special objects that are filled in on startup
index 7797a7199b9c44545aaf43e8e112a923fec5711e..177a920d87f752ddafd70c71664640d84d9d5c2b 100644 (file)
@@ -6,3 +6,5 @@ extern "C" int getosreldate();
 #ifndef KERN_PROC_PATHNAME
 #define KERN_PROC_PATHNAME 12
 #endif
+
+#define UAP_STACK_POINTER_TYPE __register_t
index 301b68fb528bb96ce302f5d3b54675a12110c4bb..c7449e867b93f2ca41e92cea866c390145a081b8 100644 (file)
@@ -9,7 +9,7 @@ void factor_vm::c_to_factor_toplevel(cell quot)
        c_to_factor(quot);
 }
 
-void init_signals()
+void factor_vm::init_signals()
 {
        unix_init_signals();
 }
index ff5d29ecd715169681fa809244d71e5e697ba7c1..a40e891a6e7ae9318ec0c77acdac1416921d3322 100644 (file)
@@ -2,17 +2,9 @@ namespace factor
 {
 
 #define VM_C_API extern "C"
-#define NULL_DLL NULL
 
-void c_to_factor_toplevel(cell quot);
-void init_signals();
 void early_init();
 const char *vm_executable_path();
 const char *default_image_path();
 
-template<typename Type> Type align_stack_pointer(Type sp)
-{
-       return sp;
-}
-
 }
index 07eda12186d1437466ed8dec4c8c48a927228f59..8e131b9011b8df4ef4573c7a7598931689a6c4c1 100644 (file)
@@ -25,7 +25,7 @@ void flush_icache(cell start, cell len)
                : "r0","r1","r2");
 
        if(result < 0)
-               tls_vm()critical_error("flush_icache() failed",result);
+               critical_error("flush_icache() failed",result);
 }
 
 }
index de13896b9ab555ea0f9cf29fcf11732e74df275a..6c490de2602040bed7b965d6b6fd1d0e290832f0 100644 (file)
@@ -7,4 +7,6 @@ VM_C_API int inotify_init();
 VM_C_API int inotify_add_watch(int fd, const char *name, u32 mask);
 VM_C_API int inotify_rm_watch(int fd, u32 wd);
 
+#define UAP_STACK_POINTER_TYPE greg_t
+
 }
index 30fd4b2081bc9624dd553a668688673894518afe..90da9a26f3108ced64939f2f0d65bf5b453fa0f6 100644 (file)
@@ -62,11 +62,6 @@ inline static unsigned int uap_fpu_status(void *uap)
        return mach_fpu_status(UAP_FS(uap));
 }
 
-template<typename Type> Type align_stack_pointer(Type sp)
-{
-       return sp;
-}
-
 inline static void mach_clear_fpu_status(ppc_float_state_t *float_state)
 {
        FPSCR(float_state) &= 0x0007f8ff;
index a6fe8e27034d255056171e840882acb8da66c424..3d754ae9e48c0b00c2f774d7074564fa0132ddc1 100644 (file)
@@ -64,11 +64,6 @@ inline static unsigned int uap_fpu_status(void *uap)
        return mach_fpu_status(UAP_FS(uap));
 }
 
-template<typename Type> Type align_stack_pointer(Type sp)
-{
-       return (Type)((((cell)sp + 4) & ~15) - 4);
-}
-
 inline static void mach_clear_fpu_status(i386_float_state_t *float_state)
 {
         MXCSR(float_state) &= 0xffffffc0;
index cb1980ddbf66cb0056ebe9e29cb174d0fb508044..7cef436327076d200392898a3f80d9f99e6c3f7f 100644 (file)
@@ -62,11 +62,6 @@ inline static unsigned int uap_fpu_status(void *uap)
        return mach_fpu_status(UAP_FS(uap));
 }
 
-template<typename Type> Type align_stack_pointer(Type sp)
-{
-       return (Type)((((cell)sp + 8) & ~15) - 8);
-}
-
 inline static void mach_clear_fpu_status(x86_float_state64_t *float_state)
 {
        MXCSR(float_state) &= 0xffffffc0;
index 0d230f48e3651c0568e6f7935ebc80596def9521..27eba772159ccc6521c4bbea608263d298c1fe1e 100644 (file)
@@ -3,16 +3,14 @@ namespace factor
 
 #define VM_C_API extern "C" __attribute__((visibility("default")))
 #define FACTOR_OS_STRING "macosx"
-#define NULL_DLL "libfactor.dylib"
 
-void init_signals();
 void early_init();
 
 const char *vm_executable_path();
 const char *default_image_path();
 
-void c_to_factor_toplevel(cell quot);
-
 #define UAP_STACK_POINTER(ucontext) (((ucontext_t *)ucontext)->uc_stack.ss_sp)
 
+#define UAP_STACK_POINTER_TYPE void*
+
 }
index 92694a4599a19770b1db16807189e9221c9d0901..4a6a3cb2b4b65ecd7e55ae21fd95e9ff6ec1d656 100644 (file)
@@ -70,7 +70,7 @@ const char *default_image_path(void)
        return [returnVal UTF8String];
 }
 
-void init_signals(void)
+void factor_vm::init_signals(void)
 {
        unix_init_signals();
        mach_initialize();
@@ -87,11 +87,9 @@ Protocol *objc_getProtocol(char *name)
 
 u64 nano_count()
 {
-       u64 t;
+       u64 t = mach_absolute_time();
        mach_timebase_info_data_t info;
-       kern_return_t ret;
-       t = mach_absolute_time();
-       ret = mach_timebase_info(&info);
+       kern_return_t ret = mach_timebase_info(&info);
        if(ret != 0)
                fatal_error("mach_timebase_info failed",ret);
        return t * (info.numer/info.denom);
index d45b2ac1630eb74de287b6a73cbe66fb5e47c672..e79d1bf375efab975c2b8514fdda6c81c8b23ec2 100644 (file)
@@ -1,8 +1,5 @@
 #include <ucontext.h>
 
-namespace factor
-{
+#define UAP_PROGRAM_COUNTER(uap) _UC_MACHINE_PC((ucontext_t *)uap)
 
-#define UAP_PROGRAM_COUNTER(uap)    _UC_MACHINE_PC((ucontext_t *)uap)
-
-}
+#define UAP_STACK_POINTER_TYPE __greg_t
diff --git a/vm/os-openbsd.hpp b/vm/os-openbsd.hpp
new file mode 100644 (file)
index 0000000..b3b47c0
--- /dev/null
@@ -0,0 +1 @@
+#define UAP_STACK_POINTER_TYPE __register_t
index 15f8132a634e560e12db87c5bef62f0c9ac9971d..034dfcbf5f2f7643e93615c0177bc8eb9adad727 100644 (file)
@@ -13,31 +13,10 @@ THREADHANDLE start_thread(void *(*start_routine)(void *),void *args)
                fatal_error("pthread_attr_setdetachstate() failed",0);
        if (pthread_create (&thread, &attr, start_routine, args) != 0)
                fatal_error("pthread_create() failed",0);
-       pthread_attr_destroy (&attr);
+       pthread_attr_destroy(&attr);
        return thread;
 }
 
-pthread_key_t tlsKey = 0;
-
-void init_platform_globals()
-{
-       if (pthread_key_create(&tlsKey, NULL) != 0)
-               fatal_error("pthread_key_create() failed",0);
-
-}
-
-void register_vm_with_thread(factor_vm *vm)
-{
-       pthread_setspecific(tlsKey,vm);
-}
-
-factor_vm *tls_vm()
-{
-       factor_vm *vm = (factor_vm*)pthread_getspecific(tlsKey);
-       assert(vm != NULL);
-       return vm;
-}
-
 static void *null_dll;
 
 u64 system_micros()
@@ -67,8 +46,7 @@ void sleep_nanos(u64 nsec)
 
 void factor_vm::init_ffi()
 {
-       /* NULL_DLL is "libfactor.dylib" for OS X and NULL for generic unix */
-       null_dll = dlopen(NULL_DLL,RTLD_LAZY);
+       null_dll = dlopen(NULL,RTLD_LAZY);
 }
 
 void factor_vm::ffi_dlopen(dll *dll)
@@ -85,7 +63,7 @@ void *factor_vm::ffi_dlsym(dll *dll, symbol_char *symbol)
 void factor_vm::ffi_dlclose(dll *dll)
 {
        if(dlclose(dll->handle))
-               general_error(ERROR_FFI,false_object,false_object,NULL);
+               general_error(ERROR_FFI,false_object,false_object);
        dll->handle = NULL;
 }
 
@@ -99,11 +77,14 @@ void factor_vm::primitive_existsp()
 void factor_vm::move_file(const vm_char *path1, const vm_char *path2)
 {
        int ret = 0;
-       do {
+       do
+       {
                ret = rename((path1),(path2));
-       } while(ret < 0 && errno == EINTR);
+       }
+       while(ret < 0 && errno == EINTR);
+
        if(ret < 0)
-               general_error(ERROR_IO,tag_fixnum(errno),false_object,NULL);
+               general_error(ERROR_IO,tag_fixnum(errno),false_object);
 }
 
 segment::segment(cell size_, bool executable_p)
@@ -141,36 +122,29 @@ segment::~segment()
 
 void factor_vm::dispatch_signal(void *uap, void (handler)())
 {
-       if(in_code_heap_p(UAP_PROGRAM_COUNTER(uap)))
-       {
-               stack_frame *ptr = (stack_frame *)UAP_STACK_POINTER(uap);
-               assert(ptr);
-               signal_callstack_top = ptr;
-       }
-       else
-               signal_callstack_top = NULL;
-
-       UAP_STACK_POINTER(uap) = align_stack_pointer(UAP_STACK_POINTER(uap));
+       UAP_STACK_POINTER(uap) = (UAP_STACK_POINTER_TYPE)fix_callstack_top((stack_frame *)UAP_STACK_POINTER(uap));
        UAP_PROGRAM_COUNTER(uap) = (cell)handler;
+
+       signal_callstack_top = (stack_frame *)UAP_STACK_POINTER(uap);
 }
 
 void memory_signal_handler(int signal, siginfo_t *siginfo, void *uap)
 {
-       factor_vm *vm = tls_vm();
+       factor_vm *vm = current_vm();
        vm->signal_fault_addr = (cell)siginfo->si_addr;
        vm->dispatch_signal(uap,factor::memory_signal_handler_impl);
 }
 
 void misc_signal_handler(int signal, siginfo_t *siginfo, void *uap)
 {
-       factor_vm *vm = tls_vm();
+       factor_vm *vm = current_vm();
        vm->signal_number = signal;
        vm->dispatch_signal(uap,factor::misc_signal_handler_impl);
 }
 
 void fpe_signal_handler(int signal, siginfo_t *siginfo, void *uap)
 {
-       factor_vm *vm = tls_vm();
+       factor_vm *vm = current_vm();
        vm->signal_number = signal;
        vm->signal_fpu_status = fpu_status(uap_fpu_status(uap));
        uap_clear_fpu_status(uap);
@@ -194,8 +168,23 @@ static void sigaction_safe(int signum, const struct sigaction *act, struct sigac
                fatal_error("sigaction failed", 0);
 }
 
-void unix_init_signals()
+void factor_vm::unix_init_signals()
 {
+       /* OpenBSD doesn't support sigaltstack() if we link against
+       libpthread. See http://redmine.ruby-lang.org/issues/show/1239 */
+
+#ifndef __OpenBSD__
+       signal_callstack_seg = new segment(callstack_size,false);
+
+       stack_t signal_callstack;
+       signal_callstack.ss_sp = (char *)signal_callstack_seg->start;
+       signal_callstack.ss_size = signal_callstack_seg->size;
+       signal_callstack.ss_flags = 0;
+
+       if(sigaltstack(&signal_callstack,(stack_t *)NULL) < 0)
+               fatal_error("sigaltstack() failed",0);
+#endif
+
        struct sigaction memory_sigaction;
        struct sigaction misc_sigaction;
        struct sigaction fpe_sigaction;
@@ -204,7 +193,7 @@ void unix_init_signals()
        memset(&memory_sigaction,0,sizeof(struct sigaction));
        sigemptyset(&memory_sigaction.sa_mask);
        memory_sigaction.sa_sigaction = memory_signal_handler;
-       memory_sigaction.sa_flags = SA_SIGINFO;
+       memory_sigaction.sa_flags = SA_SIGINFO | SA_ONSTACK;
 
        sigaction_safe(SIGBUS,&memory_sigaction,NULL);
        sigaction_safe(SIGSEGV,&memory_sigaction,NULL);
@@ -212,14 +201,14 @@ void unix_init_signals()
        memset(&fpe_sigaction,0,sizeof(struct sigaction));
        sigemptyset(&fpe_sigaction.sa_mask);
        fpe_sigaction.sa_sigaction = fpe_signal_handler;
-       fpe_sigaction.sa_flags = SA_SIGINFO;
+       fpe_sigaction.sa_flags = SA_SIGINFO | SA_ONSTACK;
 
        sigaction_safe(SIGFPE,&fpe_sigaction,NULL);
 
        memset(&misc_sigaction,0,sizeof(struct sigaction));
        sigemptyset(&misc_sigaction.sa_mask);
        misc_sigaction.sa_sigaction = misc_signal_handler;
-       misc_sigaction.sa_flags = SA_SIGINFO;
+       misc_sigaction.sa_flags = SA_SIGINFO | SA_ONSTACK;
 
        sigaction_safe(SIGQUIT,&misc_sigaction,NULL);
        sigaction_safe(SIGILL,&misc_sigaction,NULL);
index 29378bb52331bba35e2c298af705fdc42237949f..3673c4e12114b5f09f7b0b78e4fd09d048f2c8c0 100644 (file)
@@ -39,18 +39,12 @@ typedef pthread_t THREADHANDLE;
 THREADHANDLE start_thread(void *(*start_routine)(void *),void *args);
 inline static THREADHANDLE thread_id() { return pthread_self(); }
 
-void unix_init_signals();
 void signal_handler(int signal, siginfo_t* siginfo, void* uap);
 void dump_stack_signal(int signal, siginfo_t* siginfo, void* uap);
 
 u64 system_micros();
 u64 nano_count();
 void sleep_nanos(u64 nsec);
-
-void init_platform_globals();
-
-void register_vm_with_thread(factor_vm *vm);
-factor_vm *tls_vm();
 void open_console();
 
 void move_file(const vm_char *path1, const vm_char *path2);
index 07d428fb4925a7bd33b23f6aecb522945213ea98..4f90d7f641d24ed5bfe34d85c6356aa8f8062d1f 100755 (executable)
@@ -8,27 +8,6 @@ THREADHANDLE start_thread(void *(*start_routine)(void *), void *args)
        return (void *)CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)start_routine, args, 0, 0);
 }
 
-DWORD dwTlsIndex; 
-
-void init_platform_globals()
-{
-       if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
-               fatal_error("TlsAlloc failed - out of indexes",0);
-}
-
-void register_vm_with_thread(factor_vm *vm)
-{
-       if (! TlsSetValue(dwTlsIndex, vm))
-               fatal_error("TlsSetValue failed",0);
-}
-
-factor_vm *tls_vm()
-{
-       factor_vm *vm = (factor_vm*)TlsGetValue(dwTlsIndex);
-       assert(vm != NULL);
-       return vm;
-}
-
 u64 system_micros()
 {
        FILETIME t;
@@ -69,15 +48,10 @@ void sleep_nanos(u64 nsec)
        Sleep((DWORD)(nsec/1000000));
 }
 
-LONG factor_vm::exception_handler(PEXCEPTION_POINTERS pe)
+LONG factor_vm::exception_handler(PEXCEPTION_RECORD e, void *frame, PCONTEXT c, void *dispatch)
 {
-       PEXCEPTION_RECORD e = (PEXCEPTION_RECORD)pe->ExceptionRecord;
-       CONTEXT *c = (CONTEXT*)pe->ContextRecord;
-
-       if(in_code_heap_p(c->EIP))
-               signal_callstack_top = (stack_frame *)c->ESP;
-       else
-               signal_callstack_top = NULL;
+       c->ESP = (cell)fix_callstack_top((stack_frame *)c->ESP);
+       signal_callstack_top = (stack_frame *)c->ESP;
 
        switch (e->ExceptionCode)
        {
@@ -104,35 +78,23 @@ LONG factor_vm::exception_handler(PEXCEPTION_POINTERS pe)
                MXCSR(c) &= 0xffffffc0;
                c->EIP = (cell)factor::fp_signal_handler_impl;
                break;
-       case 0x40010006:
-               /* If the Widcomm bluetooth stack is installed, the BTTray.exe
-               process injects code into running programs. For some reason this
-               results in random SEH exceptions with this (undocumented)
-               exception code being raised. The workaround seems to be ignoring
-               this altogether, since that is what happens if SEH is not
-               enabled. Don't really have any idea what this exception means. */
-               break;
        default:
                signal_number = e->ExceptionCode;
                c->EIP = (cell)factor::misc_signal_handler_impl;
                break;
        }
-       return EXCEPTION_CONTINUE_EXECUTION;
+
+       return ExceptionContinueExecution;
 }
 
-FACTOR_STDCALL(LONG) exception_handler(PEXCEPTION_POINTERS pe)
+LONG exception_handler(PEXCEPTION_RECORD e, void *frame, PCONTEXT c, void *dispatch)
 {
-       return tls_vm()->exception_handler(pe);
+       return current_vm()->exception_handler(e,frame,c,dispatch);
 }
 
 void factor_vm::c_to_factor_toplevel(cell quot)
 {
-       if(!AddVectoredExceptionHandler(0, (PVECTORED_EXCEPTION_HANDLER)factor::exception_handler))
-               fatal_error("AddVectoredExceptionHandler failed", 0);
-
        c_to_factor(quot);
-
-       RemoveVectoredExceptionHandler((void *)factor::exception_handler);
 }
 
 void factor_vm::open_console()
index 8ad34ed147c7011d1eb94363343c82a7183043bf..d84ac972982991b63c83d90704afb9ce6135603c 100755 (executable)
@@ -20,15 +20,9 @@ typedef char symbol_char;
 
 #define FACTOR_OS_STRING "winnt"
 
-#define FACTOR_DLL L"factor.dll"
+#define FACTOR_DLL NULL
 
-#ifdef _MSC_VER
-       #define FACTOR_STDCALL(return_type) return_type __stdcall
-#else
-       #define FACTOR_STDCALL(return_type) __attribute__((stdcall)) return_type
-#endif
-
-FACTOR_STDCALL(LONG) exception_handler(PEXCEPTION_POINTERS pe);
+LONG exception_handler(PEXCEPTION_RECORD e, void *frame, PCONTEXT c, void *dispatch);
 
 // SSE traps raise these exception codes, which are defined in internal NT headers
 // but not winbase.h
@@ -45,8 +39,4 @@ typedef HANDLE THREADHANDLE;
 THREADHANDLE start_thread(void *(*start_routine)(void *),void *args);
 inline static THREADHANDLE thread_id() { return GetCurrentThread(); }
 
-void init_platform_globals();
-void register_vm_with_thread(factor_vm *vm);
-factor_vm *tls_vm();
-
 }
index 08f59321725f63cb0d1224b16a8d81c051a648d3..1ff1b174b5b3a80d380a134f9733b49b4f89bb24 100755 (executable)
@@ -140,7 +140,9 @@ long getpagesize()
 void factor_vm::move_file(const vm_char *path1, const vm_char *path2)
 {
        if(MoveFileEx((path1),(path2),MOVEFILE_REPLACE_EXISTING) == false)
-               general_error(ERROR_IO,tag_fixnum(GetLastError()),false_object,NULL);
+               general_error(ERROR_IO,tag_fixnum(GetLastError()),false_object);
 }
 
+void factor_vm::init_signals() {}
+
 }
index 92a3c73a99ed42f96c215bc995dacca2e48f9b0b..020a506038dc4d001531867c6b6c9bb62f6af0c8 100755 (executable)
@@ -43,7 +43,6 @@ typedef wchar_t vm_char;
 /* Difference between Jan 1 00:00:00 1601 and Jan 1 00:00:00 1970 */
 #define EPOCH_OFFSET 0x019db1ded53e8000LL
 
-inline static void init_signals() {}
 inline static void early_init() {}
 
 u64 system_micros();
index 2a38c911715c776a3cdda93646f0f26809681de6..a71aae1e89b5dbbb03615f28849fe5813286f4dd 100755 (executable)
@@ -48,6 +48,7 @@
                        #endif
                #elif defined(__OpenBSD__)
                        #define FACTOR_OS_STRING "openbsd"
+                       #include "os-openbsd.hpp"
 
                        #if defined(FACTOR_X86)
                                #include "os-openbsd-x86.32.hpp"
@@ -58,6 +59,7 @@
                        #endif
                #elif defined(__NetBSD__)
                        #define FACTOR_OS_STRING "netbsd"
+                       #include "os-netbsd.hpp"
 
                        #if defined(FACTOR_X86)
                                #include "os-netbsd-x86.32.hpp"
@@ -67,7 +69,6 @@
                                #error "Unsupported NetBSD flavor"
                        #endif
 
-                       #include "os-netbsd.hpp"
                #elif defined(linux)
                        #define FACTOR_OS_STRING "linux"
                        #include "os-linux.hpp"
index df36ed84b213289ab807facd231652374cb0dbe0..ff0947912cad70cd3c35a3f1cb35e224bc753afb 100644 (file)
@@ -2,157 +2,159 @@ namespace factor
 {
 
 /* Generated with PRIMITIVE in primitives.cpp */
-#define EACH_PRIMITIVE(_) \
-    _(alien_address) \
-    _(all_instances) \
-    _(array) \
-    _(array_to_quotation) \
-    _(become) \
-    _(bignum_add) \
-    _(bignum_and) \
-    _(bignum_bitp) \
-    _(bignum_divint) \
-    _(bignum_divmod) \
-    _(bignum_eq) \
-    _(bignum_greater) \
-    _(bignum_greatereq) \
-    _(bignum_less) \
-    _(bignum_lesseq) \
-    _(bignum_log2) \
-    _(bignum_mod) \
-    _(bignum_multiply) \
-    _(bignum_not) \
-    _(bignum_or) \
-    _(bignum_shift) \
-    _(bignum_subtract) \
-    _(bignum_to_fixnum) \
-    _(bignum_to_float) \
-    _(bignum_xor) \
-    _(bits_double) \
-    _(bits_float) \
-    _(byte_array) \
-    _(byte_array_to_bignum) \
-    _(call_clear) \
-    _(callback) \
-    _(callstack) \
-    _(callstack_to_array) \
-    _(check_datastack) \
-    _(clone) \
-    _(code_blocks) \
-    _(code_room) \
-    _(compact_gc) \
-    _(compute_identity_hashcode) \
-    _(context_object) \
-    _(data_room) \
-    _(datastack) \
-    _(die) \
-    _(disable_gc_events) \
-    _(dispatch_stats) \
-    _(displaced_alien) \
-    _(dlclose) \
-    _(dll_validp) \
-    _(dlopen) \
-    _(dlsym) \
-    _(double_bits) \
-    _(enable_gc_events) \
-    _(existsp) \
-    _(exit) \
-    _(fclose) \
-    _(fflush) \
-    _(fgetc) \
-    _(fixnum_divint) \
-    _(fixnum_divmod) \
-    _(fixnum_shift) \
-    _(fixnum_to_bignum) \
-    _(fixnum_to_float) \
-    _(float_add) \
-    _(float_bits) \
-    _(float_divfloat) \
-    _(float_eq) \
-    _(float_greater) \
-    _(float_greatereq) \
-    _(float_less) \
-    _(float_lesseq) \
-    _(float_mod) \
-    _(float_multiply) \
-    _(float_subtract) \
-    _(float_to_bignum) \
-    _(float_to_fixnum) \
-    _(float_to_str) \
-    _(fopen) \
-    _(fputc) \
-    _(fread) \
-    _(fseek) \
-    _(ftell) \
-    _(full_gc) \
-    _(fwrite) \
-    _(identity_hashcode) \
-    _(innermost_stack_frame_executing) \
-    _(innermost_stack_frame_scan) \
-    _(jit_compile) \
-    _(load_locals) \
-    _(lookup_method) \
-    _(mega_cache_miss) \
-    _(minor_gc) \
-    _(modify_code_heap) \
-    _(nano_count) \
-    _(optimized_p) \
-    _(profiling) \
-    _(quot_compiled_p) \
-    _(quotation_code) \
-    _(reset_dispatch_stats) \
-    _(resize_array) \
-    _(resize_byte_array) \
-    _(resize_string) \
-    _(retainstack) \
-    _(save_image) \
-    _(save_image_and_exit) \
-    _(set_context_object) \
-    _(set_datastack) \
-    _(set_innermost_stack_frame_quot) \
-    _(set_retainstack) \
-    _(set_slot) \
-    _(set_special_object) \
-    _(set_string_nth_fast) \
-    _(set_string_nth_slow) \
-    _(size) \
-    _(sleep) \
-    _(special_object) \
-    _(string) \
-    _(string_nth) \
-    _(strip_stack_traces) \
-    _(system_micros) \
-    _(tuple) \
-    _(tuple_boa) \
-    _(unimplemented) \
-    _(uninitialized_byte_array) \
-    _(word) \
-    _(word_code) \
-    _(wrapper)
 
-/* These are generated with macros in alien.cpp, and not with PRIMIIVE in
-primitives.cpp */
+#define EACH_PRIMITIVE(_) \
+       _(alien_address) \
+       _(all_instances) \
+       _(array) \
+       _(array_to_quotation) \
+       _(become) \
+       _(bignum_add) \
+       _(bignum_and) \
+       _(bignum_bitp) \
+       _(bignum_divint) \
+       _(bignum_divmod) \
+       _(bignum_eq) \
+       _(bignum_greater) \
+       _(bignum_greatereq) \
+       _(bignum_less) \
+       _(bignum_lesseq) \
+       _(bignum_log2) \
+       _(bignum_mod) \
+       _(bignum_multiply) \
+       _(bignum_not) \
+       _(bignum_or) \
+       _(bignum_shift) \
+       _(bignum_subtract) \
+       _(bignum_to_fixnum) \
+       _(bignum_to_float) \
+       _(bignum_xor) \
+       _(bits_double) \
+       _(bits_float) \
+       _(byte_array) \
+       _(byte_array_to_bignum) \
+       _(callback) \
+       _(callstack) \
+       _(callstack_for) \
+       _(callstack_to_array) \
+       _(check_datastack) \
+       _(clone) \
+       _(code_blocks) \
+       _(code_room) \
+       _(compact_gc) \
+       _(compute_identity_hashcode) \
+       _(context_object) \
+       _(context_object_for) \
+       _(current_callback) \
+       _(data_room) \
+       _(datastack) \
+       _(datastack_for) \
+       _(die) \
+       _(disable_gc_events) \
+       _(dispatch_stats) \
+       _(displaced_alien) \
+       _(dlclose) \
+       _(dll_validp) \
+       _(dlopen) \
+       _(dlsym) \
+       _(double_bits) \
+       _(enable_gc_events) \
+       _(existsp) \
+       _(exit) \
+       _(fclose) \
+       _(fflush) \
+       _(fgetc) \
+       _(fixnum_divint) \
+       _(fixnum_divmod) \
+       _(fixnum_shift) \
+       _(fixnum_to_bignum) \
+       _(fixnum_to_float) \
+       _(float_add) \
+       _(float_bits) \
+       _(float_divfloat) \
+       _(float_eq) \
+       _(float_greater) \
+       _(float_greatereq) \
+       _(float_less) \
+       _(float_lesseq) \
+       _(float_mod) \
+       _(float_multiply) \
+       _(float_subtract) \
+       _(float_to_bignum) \
+       _(float_to_fixnum) \
+       _(float_to_str) \
+       _(fopen) \
+       _(fputc) \
+       _(fread) \
+       _(fseek) \
+       _(ftell) \
+       _(full_gc) \
+       _(fwrite) \
+       _(identity_hashcode) \
+       _(innermost_stack_frame_executing) \
+       _(innermost_stack_frame_scan) \
+       _(jit_compile) \
+       _(load_locals) \
+       _(lookup_method) \
+       _(mega_cache_miss) \
+       _(minor_gc) \
+       _(modify_code_heap) \
+       _(nano_count) \
+       _(optimized_p) \
+       _(profiling) \
+       _(quot_compiled_p) \
+       _(quotation_code) \
+       _(reset_dispatch_stats) \
+       _(resize_array) \
+       _(resize_byte_array) \
+       _(resize_string) \
+       _(retainstack) \
+       _(retainstack_for) \
+       _(save_image) \
+       _(save_image_and_exit) \
+       _(set_context_object) \
+       _(set_datastack) \
+       _(set_innermost_stack_frame_quot) \
+       _(set_retainstack) \
+       _(set_slot) \
+       _(set_special_object) \
+       _(set_string_nth_fast) \
+       _(set_string_nth_slow) \
+       _(size) \
+       _(sleep) \
+       _(special_object) \
+       _(string) \
+       _(string_nth) \
+       _(strip_stack_traces) \
+       _(system_micros) \
+       _(tuple) \
+       _(tuple_boa) \
+       _(unimplemented) \
+       _(uninitialized_byte_array) \
+       _(word) \
+       _(word_code) \
+       _(wrapper)
 
 #define EACH_ALIEN_PRIMITIVE(_) \
-    _(signed_cell,fixnum,from_signed_cell,to_fixnum) \
-    _(unsigned_cell,cell,from_unsigned_cell,to_cell) \
-    _(signed_8,s64,from_signed_8,to_signed_8) \
-    _(unsigned_8,u64,from_unsigned_8,to_unsigned_8) \
-    _(signed_4,s32,from_signed_4,to_fixnum) \
-    _(unsigned_4,u32,from_unsigned_4,to_cell) \
-    _(signed_2,s16,from_signed_2,to_fixnum) \
-    _(unsigned_2,u16,from_unsigned_2,to_cell) \
-    _(signed_1,s8,from_signed_1,to_fixnum) \
-    _(unsigned_1,u8,from_unsigned_1,to_cell) \
-    _(float,float,from_float,to_float) \
-    _(double,double,from_double,to_double) \
-    _(cell,void *,allot_alien,pinned_alien_offset)
+       _(signed_cell,fixnum,from_signed_cell,to_fixnum) \
+       _(unsigned_cell,cell,from_unsigned_cell,to_cell) \
+       _(signed_8,s64,from_signed_8,to_signed_8) \
+       _(unsigned_8,u64,from_unsigned_8,to_unsigned_8) \
+       _(signed_4,s32,from_signed_4,to_fixnum) \
+       _(unsigned_4,u32,from_unsigned_4,to_cell) \
+       _(signed_2,s16,from_signed_2,to_fixnum) \
+       _(unsigned_2,u16,from_unsigned_2,to_cell) \
+       _(signed_1,s8,from_signed_1,to_fixnum) \
+       _(unsigned_1,u8,from_unsigned_1,to_cell) \
+       _(float,float,from_float,to_float) \
+       _(double,double,from_double,to_double) \
+       _(cell,void *,allot_alien,pinned_alien_offset)
 
 #define DECLARE_PRIMITIVE(name) VM_C_API void primitive_##name(factor_vm *parent);
 
 #define DECLARE_ALIEN_PRIMITIVE(name, type, from, to) \
-    DECLARE_PRIMITIVE(alien_##name) \
-    DECLARE_PRIMITIVE(set_alien_##name)
+       DECLARE_PRIMITIVE(alien_##name) \
+       DECLARE_PRIMITIVE(set_alien_##name)
 
 EACH_PRIMITIVE(DECLARE_PRIMITIVE)
 EACH_ALIEN_PRIMITIVE(DECLARE_ALIEN_PRIMITIVE)
index 5cedada57803e9afe1962ef8ed31f13dab2c4d98..7f86c3548522d38213ab04a680bb44a6bf377037 100644 (file)
@@ -15,6 +15,16 @@ struct segment {
 
        explicit segment(cell size, bool executable_p);
        ~segment();
+
+       bool underflow_p(cell addr)
+       {
+               return (addr >= start - getpagesize() && addr < start);
+       }
+
+       bool overflow_p(cell addr)
+       {
+               return (addr >= end && addr < end + getpagesize());
+       }
 };
 
 }
index e8ff7e30d25d567b86466c3db158d6dc5e05e909..d4dd44bed1a59b81cc78b5bdc50b04dedfb8ed75 100644 (file)
@@ -170,15 +170,17 @@ void slot_visitor<Visitor>::visit_roots()
 template<typename Visitor>
 void slot_visitor<Visitor>::visit_contexts()
 {
-       context *ctx = parent->ctx;
-
-       while(ctx)
+       std::set<context *>::const_iterator begin = parent->active_contexts.begin();
+       std::set<context *>::const_iterator end = parent->active_contexts.end();
+       while(begin != end)
        {
-               visit_stack_elements(ctx->datastack_region,(cell *)ctx->datastack);
-               visit_stack_elements(ctx->retainstack_region,(cell *)ctx->retainstack);
+               context *ctx = *begin;
+
+               visit_stack_elements(ctx->datastack_seg,(cell *)ctx->datastack);
+               visit_stack_elements(ctx->retainstack_seg,(cell *)ctx->retainstack);
                visit_object_array(ctx->context_objects,ctx->context_objects + context_object_count);
 
-               ctx = ctx->next;
+               begin++;
        }
 }
 
index be43371087b969b3454ac1a42f149ea05387efe7..e9ade19cc6f3bfc362e36b12d3e2dead26a231b1 100755 (executable)
--- a/vm/vm.cpp
+++ b/vm/vm.cpp
@@ -5,6 +5,7 @@ namespace factor
 
 factor_vm::factor_vm() :
        nursery(0,0),
+       callback_id(0),
        c_to_factor_func(NULL),
        profiling_p(false),
        gc_off(false),
@@ -12,9 +13,20 @@ factor_vm::factor_vm() :
        gc_events(NULL),
        fep_disabled(false),
        full_output(false),
-       last_nano_count(0)
+       last_nano_count(0),
+       signal_callstack_seg(NULL)
 {
        primitive_reset_dispatch_stats();
 }
 
+factor_vm::~factor_vm()
+{
+       delete_contexts();
+       if(signal_callstack_seg)
+       {
+               delete signal_callstack_seg;
+               signal_callstack_seg = NULL;
+       }
+}
+
 }
index f20145b43f2a58cfde9d0782711be5f29aa19a82..36ec3260d6563352128e28876f5d052b92836ec2 100755 (executable)
--- a/vm/vm.hpp
+++ b/vm/vm.hpp
@@ -6,11 +6,14 @@ struct code_root;
 
 struct factor_vm
 {
-       // First five fields accessed directly by assembler. See vm.factor
+       // First 5 fields accessed directly by compiler. See basis/vm/vm.factor
 
-       /* Current stacks */
+       /* Current context */
        context *ctx;
-       
+
+       /* Spare context -- for callbacks */
+       context *spare_ctx;
+
        /* New objects are allocated here */
        nursery_space nursery;
 
@@ -23,10 +26,19 @@ struct factor_vm
        cell special_objects[special_object_count];
 
        /* Data stack and retain stack sizes */
-       cell ds_size, rs_size;
+       cell datastack_size, retainstack_size, callstack_size;
+
+       /* Stack of callback IDs */
+       std::vector<int> callback_ids;
+
+       /* Next callback ID */
+       int callback_id;
 
-       /* Pooling unused contexts to make callbacks cheaper */
-       context *unused_contexts;
+       /* Pooling unused contexts to make context allocation cheaper */
+       std::vector<context *> unused_contexts;
+
+       /* Active contexts, for tracing by the GC */
+       std::set<context *> active_contexts;
 
        /* Canonical truth value. In Factor, 't' */
        cell true_object;
@@ -95,32 +107,41 @@ struct factor_vm
        decrease */
        u64 last_nano_count;
 
+       /* Stack for signal handlers, only used on Unix */
+       segment *signal_callstack_seg;
+
        // contexts
-       context *alloc_context();
-       void dealloc_context(context *old_context);
-       void nest_stacks();
-       void unnest_stacks();
-       void init_stacks(cell ds_size_, cell rs_size_);
+       context *new_context();
+       void init_context(context *ctx);
+       void delete_context(context *old_context);
+       void init_contexts(cell datastack_size_, cell retainstack_size_, cell callstack_size_);
+       void delete_contexts();
+       cell begin_callback(cell quot);
+       void end_callback();
+       void primitive_current_callback();
        void primitive_context_object();
+       void primitive_context_object_for();
        void primitive_set_context_object();
-       bool stack_to_array(cell bottom, cell top);
-       cell array_to_stack(array *array, cell bottom);
+       cell stack_to_array(cell bottom, cell top);
+       cell datastack_to_array(context *ctx);
        void primitive_datastack();
+       void primitive_datastack_for();
+       cell retainstack_to_array(context *ctx);
        void primitive_retainstack();
+       void primitive_retainstack_for();
+       cell array_to_stack(array *array, cell bottom);
+       void set_datastack(context *ctx, array *array);
        void primitive_set_datastack();
+       void set_retainstack(context *ctx, array *array);
        void primitive_set_retainstack();
        void primitive_check_datastack();
        void primitive_load_locals();
 
-       template<typename Iterator> void iterate_active_frames(Iterator &iter)
+       template<typename Iterator> void iterate_active_callstacks(Iterator &iter)
        {
-               context *ctx = this->ctx;
-
-               while(ctx)
-               {
-                       iterate_callstack(ctx,iter);
-                       ctx = ctx->next;
-               }
+               std::set<context *>::const_iterator begin = active_contexts.begin();
+               std::set<context *>::const_iterator end = active_contexts.end();
+               while(begin != end) iterate_callstack(*begin++,iter);
        }
 
        // run
@@ -148,20 +169,19 @@ struct factor_vm
        void primitive_profiling();
 
        // errors
-       void throw_error(cell error, stack_frame *callstack_top);
+       void throw_error(cell error, stack_frame *stack);
+       void general_error(vm_error_type error, cell arg1, cell arg2, stack_frame *stack);
+       void general_error(vm_error_type error, cell arg1, cell arg2);
+       void type_error(cell type, cell tagged);
        void not_implemented_error();
-       bool in_page(cell fault, cell area, cell area_size, int offset);
-       void memory_protection_error(cell addr, stack_frame *native_stack);
-       void signal_error(cell signal, stack_frame *native_stack);
+       void memory_protection_error(cell addr, stack_frame *stack);
+       void signal_error(cell signal, stack_frame *stack);
        void divide_by_zero_error();
-       void fp_trap_error(unsigned int fpu_status, stack_frame *signal_callstack_top);
-       void primitive_call_clear();
+       void fp_trap_error(unsigned int fpu_status, stack_frame *stack);
        void primitive_unimplemented();
        void memory_signal_handler_impl();
        void misc_signal_handler_impl();
        void fp_signal_handler_impl();
-       void type_error(cell type, cell tagged);
-       void general_error(vm_error_type error, cell arg1, cell arg2, stack_frame *native_stack);
 
        // bignum
        int bignum_equal_p(bignum * x, bignum * y);
@@ -327,7 +347,7 @@ struct factor_vm
        template<typename Array> bool reallot_array_in_place_p(Array *array, cell capacity);
        template<typename Array> Array *reallot_array(Array *array_, cell capacity);
 
-       //debug
+       // debug
        void print_chars(string* str);
        void print_word(word* word, cell nesting);
        void print_factor_string(string* str);
@@ -350,7 +370,7 @@ struct factor_vm
        void factorbug();
        void primitive_die();
 
-       //arrays
+       // arrays
        inline void set_array_nth(array *array, cell slot, cell value);
        array *allot_array(cell capacity, cell fill_);
        void primitive_array();
@@ -360,7 +380,7 @@ struct factor_vm
        void primitive_resize_array();
        cell std_vector_to_array(std::vector<cell> &elements);
 
-       //strings
+       // strings
        cell string_nth(const string *str, cell index);
        void set_string_nth_fast(string *str, cell index, cell ch);
        void set_string_nth_slow(string *str_, cell index, cell ch);
@@ -376,13 +396,13 @@ struct factor_vm
        void primitive_set_string_nth_fast();
        void primitive_set_string_nth_slow();
 
-       //booleans
+       // booleans
        cell tag_boolean(cell untagged)
        {
                return (untagged ? true_object : false_object);
        }
 
-       //byte arrays
+       // byte arrays
        byte_array *allot_byte_array(cell size);
        void primitive_byte_array();
        void primitive_uninitialized_byte_array();
@@ -390,11 +410,11 @@ struct factor_vm
 
        template<typename Type> byte_array *byte_array_from_value(Type *value);
 
-       //tuples
+       // tuples
        void primitive_tuple();
        void primitive_tuple_boa();
 
-       //words
+       // words
        word *allot_word(cell name_, cell vocab_, cell hashcode_);
        void primitive_word();
        void primitive_word_code();
@@ -405,7 +425,7 @@ struct factor_vm
        cell find_all_words();
        void compile_all_words();
 
-       //math
+       // math
        void primitive_bignum_to_fixnum();
        void primitive_float_to_fixnum();
        void primitive_fixnum_divint();
@@ -491,7 +511,7 @@ struct factor_vm
        // tagged
        template<typename Type> Type *untag_check(cell value);
 
-       //io
+       // io
        void init_c_io();
        void io_error();
        FILE* safe_fopen(char *filename, char *mode);
@@ -514,7 +534,7 @@ struct factor_vm
        void primitive_fflush();
        void primitive_fclose();
 
-       //code_block
+       // code_block
        cell compute_entry_point_address(cell obj);
        cell compute_entry_point_pic_address(word *w, cell tagged_quot);
        cell compute_entry_point_pic_address(cell w_);
@@ -551,11 +571,11 @@ struct factor_vm
        cell code_blocks();
        void primitive_code_blocks();
 
-       //callbacks
+       // callbacks
        void init_callbacks(cell size);
        void primitive_callback();
 
-       //image
+       // image
        void init_objects(image_header *h);
        void load_data_heap(FILE *file, image_header *h, vm_parameters *p);
        void load_code_heap(FILE *file, image_header *h, vm_parameters *p);
@@ -566,13 +586,15 @@ struct factor_vm
        void fixup_code(cell data_offset, cell code_offset);
        void load_image(vm_parameters *p);
 
-       //callstack
+       // callstack
        template<typename Iterator> void iterate_callstack_object(callstack *stack_, Iterator &iterator);
        void check_frame(stack_frame *frame);
        callstack *allot_callstack(cell size);
-       stack_frame *fix_callstack_top(stack_frame *top, stack_frame *bottom);
-       stack_frame *second_from_top_stack_frame();
+       stack_frame *fix_callstack_top(stack_frame *top);
+       stack_frame *second_from_top_stack_frame(context *ctx);
+       cell capture_callstack(context *ctx);
        void primitive_callstack();
+       void primitive_callstack_for();
        code_block *frame_code(stack_frame *frame);
        code_block_type frame_type(stack_frame *frame);
        cell frame_executing(stack_frame *frame);
@@ -586,7 +608,7 @@ struct factor_vm
        void primitive_set_innermost_stack_frame_quot();
        template<typename Iterator> void iterate_callstack(context *ctx, Iterator &iterator);
 
-       //alien
+       // alien
        char *pinned_alien_offset(cell obj);
        cell allot_alien(cell delegate_, cell displacement);
        cell allot_alien(void *address);
@@ -603,7 +625,7 @@ struct factor_vm
        cell from_small_struct(cell x, cell y, cell size);
        cell from_medium_struct(cell x1, cell x2, cell x3, cell x4, cell size);
 
-       //quotations
+       // quotations
        void primitive_jit_compile();
        code_block *lazy_jit_compile_block();
        void primitive_array_to_quotation();
@@ -618,7 +640,7 @@ struct factor_vm
        cell find_all_quotations();
        void initialize_all_quotations();
 
-       //dispatch
+       // dispatch
        cell search_lookup_alist(cell table, cell klass);
        cell search_lookup_hash(cell table, cell klass, cell hashcode);
        cell nth_superclass(tuple_layout *layout, fixnum echelon);
@@ -633,7 +655,7 @@ struct factor_vm
        void primitive_reset_dispatch_stats();
        void primitive_dispatch_stats();
 
-       //inline cache
+       // inline cache
        void init_inline_caching(int max_size);
        void deallocate_inline_cache(cell return_address);
        cell determine_inline_cache_type(array *cache_entries);
@@ -645,11 +667,11 @@ struct factor_vm
        void update_pic_transitions(cell pic_size);
        void *inline_cache_miss(cell return_address);
 
-       //entry points
+       // entry points
        void c_to_factor(cell quot);
        void unwind_native_frames(cell quot, stack_frame *to);
 
-       //factor
+       // factor
        void default_parameters(vm_parameters *p);
        bool factor_arg(const vm_char *str, const vm_char *arg, cell *value);
        void init_parameters_from_args(vm_parameters *p, int argc, vm_char **argv);
@@ -673,6 +695,7 @@ struct factor_vm
        void *ffi_dlsym(dll *dll, symbol_char *symbol);
        void ffi_dlclose(dll *dll);
        void c_to_factor_toplevel(cell quot);
+       void init_signals();
 
        // os-windows
   #if defined(WINDOWS)
@@ -683,10 +706,12 @@ struct factor_vm
 
   #if defined(WINNT)
        void open_console();
-       LONG exception_handler(PEXCEPTION_POINTERS pe);
+       LONG exception_handler(PEXCEPTION_RECORD e, void *frame, PCONTEXT c, void *dispatch);
   #endif
+
   #else  // UNIX
        void dispatch_signal(void *uap, void (handler)());
+       void unix_init_signals();
   #endif
 
   #ifdef __APPLE__
@@ -694,9 +719,7 @@ struct factor_vm
   #endif
 
        factor_vm();
-
+       ~factor_vm();
 };
 
-extern std::map<THREADHANDLE, factor_vm *> thread_vms;
-
 }