]> gitweb.factorcode.org Git - factor.git/commitdiff
Merge branch 'master' of git://factorcode.org/git/factor
authorAaron Schaefer <aaron@elasticdog.com>
Fri, 1 May 2009 23:48:25 +0000 (19:48 -0400)
committerAaron Schaefer <aaron@elasticdog.com>
Fri, 1 May 2009 23:48:25 +0000 (19:48 -0400)
384 files changed:
Makefile [changed mode: 0644->0755]
basis/alarms/alarms.factor
basis/alien/libraries/libraries-docs.factor [changed mode: 0644->0755]
basis/alien/remote-control/remote-control.factor
basis/bootstrap/compiler/compiler.factor
basis/bootstrap/image/image.factor
basis/bootstrap/stage2.factor
basis/calendar/windows/windows.factor
basis/cocoa/cocoa.factor
basis/cocoa/dialogs/dialogs.factor
basis/command-line/command-line-docs.factor
basis/compiler/cfg/intrinsics/allot/allot.factor
basis/compiler/cfg/intrinsics/intrinsics.factor
basis/compiler/cfg/value-numbering/value-numbering-tests.factor
basis/compiler/codegen/codegen.factor
basis/compiler/codegen/fixup/fixup.factor
basis/compiler/compiler-docs.factor
basis/compiler/compiler.factor
basis/compiler/constants/constants.factor
basis/compiler/tests/call-effect.factor [new file with mode: 0644]
basis/compiler/tests/codegen.factor
basis/compiler/tests/float.factor
basis/compiler/tests/generic.factor [new file with mode: 0644]
basis/compiler/tests/intrinsics.factor
basis/compiler/tests/optimizer.factor
basis/compiler/tests/peg-regression.factor
basis/compiler/tests/pic-problem-1.factor [new file with mode: 0644]
basis/compiler/tests/redefine14.factor
basis/compiler/tests/redefine17.factor [new file with mode: 0644]
basis/compiler/tests/redefine3.factor
basis/compiler/tests/simple.factor
basis/compiler/tests/spilling.factor
basis/compiler/tree/debugger/debugger.factor
basis/compiler/tree/escape-analysis/check/check.factor
basis/compiler/tree/escape-analysis/escape-analysis-tests.factor
basis/compiler/tree/escape-analysis/simple/simple.factor
basis/compiler/tree/propagation/info/info.factor
basis/compiler/tree/propagation/inlining/inlining.factor
basis/compiler/tree/propagation/propagation-tests.factor
basis/compiler/tree/propagation/simple/simple.factor
basis/compiler/tree/propagation/slots/slots.factor
basis/compiler/tree/tuple-unboxing/tuple-unboxing-tests.factor
basis/compiler/tree/tuple-unboxing/tuple-unboxing.factor
basis/core-foundation/fsevents/fsevents.factor
basis/cpu/ppc/bootstrap.factor
basis/cpu/x86/32/32.factor
basis/cpu/x86/32/bootstrap.factor
basis/cpu/x86/64/bootstrap.factor
basis/cpu/x86/assembler/assembler-tests.factor
basis/cpu/x86/assembler/assembler.factor
basis/cpu/x86/bootstrap.factor
basis/debugger/debugger-docs.factor
basis/debugger/debugger.factor
basis/delegate/delegate-tests.factor
basis/documents/elements/elements.factor
basis/ftp/client/client.factor
basis/hints/hints.factor
basis/http/client/client-docs.factor
basis/http/client/post-data/post-data-docs.factor [new file with mode: 0644]
basis/io/backend/windows/nt/nt.factor
basis/io/backend/windows/nt/privileges/privileges.factor
basis/io/backend/windows/windows.factor
basis/io/encodings/string/string.factor
basis/io/files/links/links-docs.factor
basis/io/files/links/links.factor
basis/io/files/links/unix/unix.factor
basis/io/files/windows/nt/nt.factor
basis/io/launcher/launcher.factor
basis/io/launcher/unix/unix-tests.factor
basis/io/mmap/windows/windows.factor
basis/io/monitors/windows/nt/nt.factor
basis/io/servers/connection/connection-tests.factor
basis/io/sockets/secure/unix/unix-tests.factor
basis/io/streams/byte-array/byte-array-tests.factor
basis/io/styles/styles-docs.factor [changed mode: 0644->0755]
basis/io/styles/styles.factor
basis/locals/locals-tests.factor
basis/macros/macros-docs.factor [changed mode: 0644->0755]
basis/math/complex/complex-docs.factor
basis/math/complex/complex.factor
basis/math/functions/functions-docs.factor
basis/math/functions/functions.factor
basis/math/ratios/ratios-docs.factor
basis/math/ratios/ratios.factor
basis/peg/peg-tests.factor
basis/random/windows/windows.factor
basis/refs/refs-docs.factor [changed mode: 0644->0755]
basis/see/see.factor
basis/stack-checker/backend/backend.factor
basis/stack-checker/call-effect/call-effect-tests.factor
basis/stack-checker/call-effect/call-effect.factor
basis/stack-checker/errors/errors-docs.factor [changed mode: 0644->0755]
basis/stack-checker/errors/errors.factor
basis/stack-checker/known-words/known-words.factor
basis/stack-checker/stack-checker-docs.factor
basis/stack-checker/transforms/transforms.factor
basis/strings/tables/tables-tests.factor
basis/strings/tables/tables.factor
basis/tools/continuations/continuations.factor
basis/tools/crossref/crossref.factor
basis/tools/deploy/backend/backend.factor
basis/tools/deploy/shaker/shaker.factor
basis/tools/deploy/test/test.factor
basis/tools/disassembler/disassembler-tests.factor
basis/tools/disassembler/udis/udis.factor
basis/tools/scaffold/scaffold.factor
basis/tools/scaffold/windows/authors.txt [new file with mode: 0755]
basis/tools/scaffold/windows/tags.txt [new file with mode: 0644]
basis/tools/scaffold/windows/windows.factor [new file with mode: 0755]
basis/tools/time/time.factor
basis/tools/vocabs/vocabs.factor
basis/tools/walker/walker-tests.factor
basis/tuple-arrays/summary.txt [new file with mode: 0755]
basis/tuple-arrays/tags.txt [new file with mode: 0755]
basis/ui/backend/windows/windows.factor
basis/ui/gadgets/sliders/sliders.factor
basis/ui/gadgets/tables/tables.factor
basis/ui/gestures/gestures.factor
basis/ui/tools/browser/browser.factor
basis/ui/tools/common/common.factor
basis/ui/tools/error-list/error-list.factor
basis/ui/tools/listener/completion/completion.factor
basis/ui/tools/listener/listener-tests.factor
basis/ui/ui.factor
basis/unix/unix.factor
basis/windows/advapi32/advapi32.factor
basis/windows/dinput/constants/constants.factor
basis/windows/errors/errors-tests.factor [new file with mode: 0755]
basis/windows/errors/errors.factor
basis/windows/fonts/fonts.factor
basis/windows/fonts/tags.txt [new file with mode: 0644]
basis/windows/kernel32/kernel32.factor
basis/windows/ole32/ole32.factor
basis/windows/shell32/shell32.factor
basis/windows/time/time.factor
basis/windows/types/types.factor
basis/windows/uniscribe/uniscribe.factor
basis/windows/user32/user32.factor
basis/windows/windows.factor
basis/windows/winsock/winsock.factor
basis/xmode/code2html/code2html.factor
build-support/factor.sh
core/bootstrap/layouts/layouts.factor
core/bootstrap/primitives.factor
core/checksums/checksums.factor
core/classes/builtin/builtin.factor
core/classes/mixin/mixin-tests.factor
core/classes/mixin/mixin.factor
core/classes/tuple/tuple-tests.factor
core/combinators/combinators-docs.factor [changed mode: 0644->0755]
core/combinators/combinators-tests.factor [changed mode: 0644->0755]
core/compiler/units/units-tests.factor
core/compiler/units/units.factor
core/effects/effects-docs.factor
core/effects/effects-tests.factor
core/effects/effects.factor
core/generic/generic-docs.factor
core/generic/generic-tests.factor
core/generic/generic.factor
core/generic/hook/authors.txt [new file with mode: 0644]
core/generic/hook/hook-docs.factor [new file with mode: 0644]
core/generic/hook/hook.factor [new file with mode: 0644]
core/generic/math/math-docs.factor
core/generic/math/math-tests.factor [new file with mode: 0644]
core/generic/math/math.factor
core/generic/single/authors.txt [new file with mode: 0644]
core/generic/single/single-docs.factor [new file with mode: 0644]
core/generic/single/single-tests.factor [new file with mode: 0644]
core/generic/single/single.factor [new file with mode: 0644]
core/generic/standard/authors.txt
core/generic/standard/engines/engines.factor [deleted file]
core/generic/standard/engines/predicate/predicate.factor [deleted file]
core/generic/standard/engines/predicate/summary.txt [deleted file]
core/generic/standard/engines/summary.txt [deleted file]
core/generic/standard/engines/tag/summary.txt [deleted file]
core/generic/standard/engines/tag/tag.factor [deleted file]
core/generic/standard/engines/tuple/summary.txt [deleted file]
core/generic/standard/engines/tuple/tuple.factor [deleted file]
core/generic/standard/standard-docs.factor
core/generic/standard/standard-tests.factor [deleted file]
core/generic/standard/standard.factor
core/generic/standard/summary.txt [deleted file]
core/hashtables/hashtables-docs.factor [changed mode: 0644->0755]
core/init/init.factor
core/io/files/files-tests.factor
core/io/files/files.factor
core/io/io-docs.factor
core/io/io.factor
core/io/streams/c/c-tests.factor
core/kernel/kernel-docs.factor
core/layouts/layouts.factor
core/math/math.factor
core/namespaces/namespaces-docs.factor [changed mode: 0644->0755]
core/namespaces/namespaces.factor
core/parser/parser.factor
core/sequences/sequences-docs.factor
core/sets/sets-docs.factor
core/slots/slots-tests.factor
core/strings/strings-tests.factor
core/syntax/syntax-docs.factor
core/syntax/syntax.factor
core/vocabs/vocabs.factor
core/words/words-docs.factor
core/words/words.factor
extra/audio/audio.factor [new file with mode: 0644]
extra/audio/wav/wav.factor [new file with mode: 0644]
extra/benchmark/benchmark.factor
extra/benchmark/typecheck3/typecheck3.factor
extra/benchmark/typecheck4/authors.txt [deleted file]
extra/benchmark/typecheck4/typecheck4.factor [deleted file]
extra/bson/authors.txt [new file with mode: 0644]
extra/bson/bson.factor [new file with mode: 0644]
extra/bson/constants/authors.txt [new file with mode: 0644]
extra/bson/constants/constants.factor [new file with mode: 0644]
extra/bson/constants/summary.txt [new file with mode: 0644]
extra/bson/reader/authors.txt [new file with mode: 0644]
extra/bson/reader/reader.factor [new file with mode: 0644]
extra/bson/reader/summary.txt [new file with mode: 0644]
extra/bson/summary.txt [new file with mode: 0644]
extra/bson/writer/authors.txt [new file with mode: 0644]
extra/bson/writer/summary.txt [new file with mode: 0644]
extra/bson/writer/writer.factor [new file with mode: 0644]
extra/contributors/contributors.factor
extra/crypto/hmac/hmac-tests.factor
extra/crypto/hmac/hmac.factor
extra/drills/deployed/deploy.factor [new file with mode: 0644]
extra/drills/deployed/deployed.factor [new file with mode: 0644]
extra/drills/deployed/tags.txt [new file with mode: 0644]
extra/drills/drills.factor
extra/file-trees/file-trees-tests.factor [new file with mode: 0644]
extra/file-trees/file-trees.factor [new file with mode: 0644]
extra/fuel/fuel-tests.factor [new file with mode: 0644]
extra/fuel/fuel.factor
extra/game-input/dinput/dinput.factor
extra/game-input/iokit/iokit.factor
extra/game-loop/game-loop.factor [new file with mode: 0644]
extra/irc/gitbot/gitbot.factor
extra/mason/common/common.factor
extra/merger/deploy.factor [new file with mode: 0644]
extra/merger/merger.factor [new file with mode: 0644]
extra/merger/tags.txt [new file with mode: 0644]
extra/modules/remote-loading/authors.txt [new file with mode: 0644]
extra/modules/remote-loading/remote-loading.factor [new file with mode: 0644]
extra/modules/remote-loading/summary.txt [new file with mode: 0644]
extra/modules/rpc-server/authors.txt [new file with mode: 0644]
extra/modules/rpc-server/rpc-server.factor [new file with mode: 0644]
extra/modules/rpc-server/summary.txt [new file with mode: 0644]
extra/modules/rpc/authors.txt [new file with mode: 0644]
extra/modules/rpc/rpc-docs.factor [new file with mode: 0644]
extra/modules/rpc/rpc.factor [new file with mode: 0644]
extra/modules/rpc/summary.txt [new file with mode: 0644]
extra/modules/uploads/authors.txt [new file with mode: 0644]
extra/modules/uploads/summary.txt [new file with mode: 0644]
extra/modules/uploads/uploads.factor [new file with mode: 0644]
extra/modules/using/authors.txt [new file with mode: 0644]
extra/modules/using/summary.txt [new file with mode: 0644]
extra/modules/using/tests/tags.txt [new file with mode: 0644]
extra/modules/using/tests/test-server.factor [new file with mode: 0644]
extra/modules/using/tests/tests.factor [new file with mode: 0644]
extra/modules/using/using-docs.factor [new file with mode: 0644]
extra/modules/using/using.factor [new file with mode: 0644]
extra/mongodb/authors.txt [new file with mode: 0644]
extra/mongodb/benchmark/authors.txt [new file with mode: 0644]
extra/mongodb/benchmark/benchmark.factor [new file with mode: 0644]
extra/mongodb/benchmark/summary.txt [new file with mode: 0644]
extra/mongodb/connection/authors.txt [new file with mode: 0644]
extra/mongodb/connection/connection.factor [new file with mode: 0644]
extra/mongodb/connection/summary.txt [new file with mode: 0644]
extra/mongodb/driver/authors.txt [new file with mode: 0644]
extra/mongodb/driver/driver-docs.factor [new file with mode: 0644]
extra/mongodb/driver/driver.factor [new file with mode: 0644]
extra/mongodb/driver/summary.txt [new file with mode: 0644]
extra/mongodb/driver/tags.txt [new file with mode: 0644]
extra/mongodb/mmm/authors.txt [new file with mode: 0644]
extra/mongodb/mmm/mmm.factor [new file with mode: 0644]
extra/mongodb/mmm/summary.txt [new file with mode: 0644]
extra/mongodb/mongodb-docs.factor [new file with mode: 0644]
extra/mongodb/mongodb.factor [new file with mode: 0644]
extra/mongodb/msg/authors.txt [new file with mode: 0644]
extra/mongodb/msg/msg.factor [new file with mode: 0644]
extra/mongodb/msg/summary.txt [new file with mode: 0644]
extra/mongodb/operations/authors.txt [new file with mode: 0644]
extra/mongodb/operations/operations.factor [new file with mode: 0644]
extra/mongodb/operations/summary.txt [new file with mode: 0644]
extra/mongodb/summary.txt [new file with mode: 0644]
extra/mongodb/tags.txt [new file with mode: 0644]
extra/mongodb/tuple/authors.txt [new file with mode: 0644]
extra/mongodb/tuple/collection/authors.txt [new file with mode: 0644]
extra/mongodb/tuple/collection/collection.factor [new file with mode: 0644]
extra/mongodb/tuple/collection/summary.txt [new file with mode: 0644]
extra/mongodb/tuple/index/authors.txt [new file with mode: 0644]
extra/mongodb/tuple/index/index.factor [new file with mode: 0644]
extra/mongodb/tuple/index/summary.txt [new file with mode: 0644]
extra/mongodb/tuple/persistent/authors.txt [new file with mode: 0644]
extra/mongodb/tuple/persistent/persistent.factor [new file with mode: 0644]
extra/mongodb/tuple/persistent/summary.txt [new file with mode: 0644]
extra/mongodb/tuple/state/authors.txt [new file with mode: 0644]
extra/mongodb/tuple/state/state.factor [new file with mode: 0644]
extra/mongodb/tuple/state/summary.txt [new file with mode: 0644]
extra/mongodb/tuple/summary.txt [new file with mode: 0644]
extra/mongodb/tuple/tuple.factor [new file with mode: 0644]
extra/morse/morse.factor
extra/peg-lexer/peg-lexer.factor
extra/str-fry/authors.txt [new file with mode: 0644]
extra/str-fry/str-fry.factor [new file with mode: 0644]
extra/str-fry/summary.txt [new file with mode: 0644]
extra/system-info/windows/nt/nt.factor
extra/system-info/windows/windows.factor
extra/tar/tar.factor
extra/ui/frp/authors.txt [new file with mode: 0644]
extra/ui/frp/frp-docs.factor [new file with mode: 0644]
extra/ui/frp/frp.factor [new file with mode: 0644]
extra/ui/frp/summary.txt [new file with mode: 0644]
extra/ui/gadgets/alerts/alerts.factor
extra/ui/gadgets/alerts/authors.txt [new file with mode: 0644]
extra/ui/gadgets/alerts/summary.txt [new file with mode: 0644]
extra/ui/gadgets/book-extras/authors.txt [new file with mode: 0644]
extra/ui/gadgets/book-extras/summary.txt [new file with mode: 0644]
extra/ui/gadgets/comboboxes/authors.txt [new file with mode: 0644]
extra/ui/gadgets/comboboxes/comboboxes.factor [new file with mode: 0644]
extra/ui/gadgets/comboboxes/summary.txt [new file with mode: 0644]
extra/wordtimer/wordtimer.factor
misc/fuel/fuel-debug-uses.el
misc/fuel/fuel-mode.el
misc/fuel/fuel-syntax.el
vm/Config.unix [changed mode: 0644->0755]
vm/Config.x86.32
vm/arrays.c [new file with mode: 0644]
vm/arrays.h [new file with mode: 0644]
vm/bignumint.h
vm/booleans.c [new file with mode: 0644]
vm/booleans.h [new file with mode: 0644]
vm/byte_arrays.c [new file with mode: 0644]
vm/byte_arrays.h [new file with mode: 0644]
vm/callstack.c
vm/callstack.h
vm/code_block.c
vm/code_block.h
vm/code_gc.c
vm/code_gc.h
vm/code_heap.c
vm/code_heap.h
vm/cpu-ppc.S
vm/cpu-x86.32.S
vm/cpu-x86.64.S
vm/cpu-x86.S
vm/cpu-x86.h
vm/data_gc.c
vm/data_gc.h
vm/data_heap.c
vm/data_heap.h
vm/debug.c
vm/dispatch.c [new file with mode: 0644]
vm/dispatch.h [new file with mode: 0644]
vm/factor.c
vm/image.c
vm/image.h
vm/inline_cache.c [new file with mode: 0644]
vm/inline_cache.h [new file with mode: 0644]
vm/jit.c [new file with mode: 0644]
vm/jit.h [new file with mode: 0644]
vm/layouts.h
vm/local_roots.h
vm/master.h
vm/math.c
vm/math.h
vm/os-windows.c
vm/os-windows.h
vm/primitives.c
vm/profiler.c
vm/profiler.h
vm/quotations.c
vm/quotations.h
vm/run.c
vm/run.h
vm/strings.c [new file with mode: 0644]
vm/strings.h [new file with mode: 0644]
vm/tuples.c [new file with mode: 0644]
vm/tuples.h [new file with mode: 0644]
vm/types.c [deleted file]
vm/types.h [deleted file]
vm/utilities.c
vm/words.c [new file with mode: 0644]
vm/words.h [new file with mode: 0644]

old mode 100644 (file)
new mode 100755 (executable)
index c19d83e..33d4221
--- a/Makefile
+++ b/Makefile
@@ -9,11 +9,10 @@ VERSION = 0.92
 
 BUNDLE = Factor.app
 LIBPATH = -L/usr/X11R6/lib
-CFLAGS = -Wall
-FFI_TEST_CFLAGS = -fPIC
+CFLAGS = -Wall -Werror
 
 ifdef DEBUG
-       CFLAGS += -g
+       CFLAGS += -g -DFACTOR_DEBUG
 else
        CFLAGS += -O3
 endif
@@ -28,7 +27,10 @@ endif
 
 DLL_OBJS = $(PLAF_DLL_OBJS) \
        vm/alien.o \
+       vm/arrays.o \
        vm/bignum.o \
+       vm/booleans.o \
+       vm/byte_arrays.o \
        vm/callstack.o \
        vm/code_block.o \
        vm/code_gc.o \
@@ -36,17 +38,22 @@ DLL_OBJS = $(PLAF_DLL_OBJS) \
        vm/data_gc.o \
        vm/data_heap.o \
        vm/debug.o \
+       vm/dispatch.o \
        vm/errors.o \
        vm/factor.o \
        vm/image.o \
+       vm/inline_cache.o \
        vm/io.o \
+       vm/jit.o \
        vm/math.o \
        vm/primitives.o \
        vm/profiler.o \
        vm/quotations.o \
        vm/run.o \
-       vm/types.o \
-       vm/utilities.o
+       vm/strings.o \
+       vm/tuples.o \
+       vm/utilities.o \
+       vm/words.o
 
 EXE_OBJS = $(PLAF_EXE_OBJS)
 
@@ -183,5 +190,5 @@ vm/ffi_test.o: vm/ffi_test.c
 
 .m.o:
        $(CC) -c $(CFLAGS) -o $@ $<
-       
+
 .PHONY: factor
index 9cc05b41591cd8974def94d2f10646a3f7598e8a..f9fdce806f5f606bd1ef5532e19ab42f8ac3694c 100644 (file)
@@ -71,7 +71,7 @@ ERROR: bad-alarm-frequency frequency ;
     ] when* ;
 
 : init-alarms ( -- )
-    alarms global [ cancel-alarms <min-heap> ] change-at
+    alarms [ cancel-alarms <min-heap> ] change-global
     [ alarm-thread-loop t ] "Alarms" spawn-server
     alarm-thread set-global ;
 
old mode 100644 (file)
new mode 100755 (executable)
index c555061..eac7655
@@ -15,7 +15,7 @@ HELP: libraries
 { $description "A global hashtable that keeps a list of open libraries. Use the " { $link add-library } " word to construct a library and add it with a single call." } ;
 
 HELP: library
-{ $values { "name" "a string" } { "library" "a hashtable" } }
+{ $values { "name" "a string" } { "library" assoc } }
 { $description "Looks up a library by its logical name. The library object is a hashtable with the following keys:"
     { $list
         { { $snippet "name" } " - the full path of the C library binary" }
index 4da06ec4c96ba23bc60cdc034210bbd3488d8af6..b72c79e47818a8be27331e26d887e14996ee047e 100644 (file)
@@ -15,7 +15,7 @@ IN: alien.remote-control
     "void" { "long" } "cdecl" [ sleep ] alien-callback ;
 
 : ?callback ( word -- alien )
-    dup optimized>> [ execute ] [ drop f ] if ; inline
+    dup optimized? [ execute ] [ drop f ] if ; inline
 
 : init-remote-control ( -- )
     \ eval-callback ?callback 16 setenv
index 89a0ed86fef63b2ea93148c895cebe921f9e0378..7940703140ba13959d5d74bd47a4041057e9f8fb 100644 (file)
@@ -5,7 +5,7 @@ sequences namespaces parser kernel kernel.private classes
 classes.private arrays hashtables vectors classes.tuple sbufs
 hashtables.private sequences.private math classes.tuple.private
 growable namespaces.private assocs words command-line vocabs io
-io.encodings.string libc splitting math.parser
+io.encodings.string libc splitting math.parser memory
 compiler.units math.order compiler.tree.builder
 compiler.tree.optimizer compiler.cfg.optimizer ;
 IN: bootstrap.compiler
@@ -23,10 +23,13 @@ IN: bootstrap.compiler
 
 "cpu." cpu name>> append require
 
-enable-compiler
+enable-optimizer
+
+! Push all tuple layouts to tenured space to improve method caching
+gc
 
 : compile-unoptimized ( words -- )
-    [ optimized>> not ] filter compile ;
+    [ optimized? not ] filter compile ;
 
 nl
 "Compiling..." write flush
index 504afae018e38bfb8a8c36c8a7510428b9afc659..cad40b63848fda7dd99be8c01a1fbc3f0765c477 100644 (file)
@@ -3,14 +3,13 @@
 USING: alien arrays byte-arrays generic assocs hashtables assocs
 hashtables.private io io.binary io.files io.encodings.binary
 io.pathnames kernel kernel.private math namespaces make parser
-prettyprint sequences sequences.private strings sbufs
-vectors words quotations assocs system layouts splitting
-grouping growable classes classes.builtin classes.tuple
-classes.tuple.private words.private vocabs
-vocabs.loader source-files definitions debugger
-quotations.private sequences.private combinators
-math.order math.private accessors
-slots.private compiler.units fry ;
+prettyprint sequences sequences.private strings sbufs vectors words
+quotations assocs system layouts splitting grouping growable classes
+classes.builtin classes.tuple classes.tuple.private vocabs
+vocabs.loader source-files definitions debugger quotations.private
+sequences.private combinators math.order math.private accessors
+slots.private generic.single.private compiler.units compiler.constants
+fry ;
 IN: bootstrap.image
 
 : arch ( os cpu -- arch )
@@ -94,13 +93,30 @@ CONSTANT: -1-offset             9
 
 SYMBOL: sub-primitives
 
-: make-jit ( quot rc rt offset -- quad )
-    [ [ call( -- ) ] { } make ] 3dip 4array ;
+SYMBOL: jit-define-rc
+SYMBOL: jit-define-rt
+SYMBOL: jit-define-offset
 
-: jit-define ( quot rc rt offset name -- )
+: compute-offset ( -- offset )
+    building get length jit-define-rc get rc-absolute-cell = bootstrap-cell 4 ? - ;
+
+: jit-rel ( rc rt -- )
+    jit-define-rt set
+    jit-define-rc set
+    compute-offset jit-define-offset set ;
+
+: make-jit ( quot -- quad )
+    [
+        call( -- )
+        jit-define-rc get
+        jit-define-rt get
+        jit-define-offset get 3array
+    ] B{ } make prefix ;
+
+: jit-define ( quot name -- )
     [ make-jit ] dip set ;
 
-: define-sub-primitive ( quot rc rt offset word -- )
+: define-sub-primitive ( quot word -- )
     [ make-jit ] dip sub-primitives get set-at ;
 
 ! The image being constructed; a vector of word-size integers
@@ -119,7 +135,6 @@ SYMBOL: bootstrap-global
 SYMBOL: bootstrap-boot-quot
 
 ! JIT parameters
-SYMBOL: jit-code-format
 SYMBOL: jit-prolog
 SYMBOL: jit-primitive-word
 SYMBOL: jit-primitive
@@ -129,20 +144,36 @@ SYMBOL: jit-push-immediate
 SYMBOL: jit-if-word
 SYMBOL: jit-if-1
 SYMBOL: jit-if-2
-SYMBOL: jit-dispatch-word
-SYMBOL: jit-dispatch
 SYMBOL: jit-dip-word
 SYMBOL: jit-dip
 SYMBOL: jit-2dip-word
 SYMBOL: jit-2dip
 SYMBOL: jit-3dip-word
 SYMBOL: jit-3dip
+SYMBOL: jit-execute-word
+SYMBOL: jit-execute-jump
+SYMBOL: jit-execute-call
 SYMBOL: jit-epilog
 SYMBOL: jit-return
 SYMBOL: jit-profiling
-SYMBOL: jit-declare-word
 SYMBOL: jit-save-stack
 
+! PIC stubs
+SYMBOL: pic-load
+SYMBOL: pic-tag
+SYMBOL: pic-hi-tag
+SYMBOL: pic-tuple
+SYMBOL: pic-hi-tag-tuple
+SYMBOL: pic-check-tag
+SYMBOL: pic-check
+SYMBOL: pic-hit
+SYMBOL: pic-miss-word
+
+! Megamorphic dispatch
+SYMBOL: mega-lookup
+SYMBOL: mega-lookup-word
+SYMBOL: mega-miss-word
+
 ! Default definition for undefined words
 SYMBOL: undefined-quot
 
@@ -150,7 +181,6 @@ SYMBOL: undefined-quot
     H{
         { bootstrap-boot-quot 20 }
         { bootstrap-global 21 }
-        { jit-code-format 22 }
         { jit-prolog 23 }
         { jit-primitive-word 24 }
         { jit-primitive 25 }
@@ -159,20 +189,32 @@ SYMBOL: undefined-quot
         { jit-if-word 28 }
         { jit-if-1 29 }
         { jit-if-2 30 }
-        { jit-dispatch-word 31 }
-        { jit-dispatch 32 }
         { jit-epilog 33 }
         { jit-return 34 }
         { jit-profiling 35 }
         { jit-push-immediate 36 }
-        { jit-declare-word 42 }
-        { jit-save-stack 43 }
-        { jit-dip-word 44 }
-        { jit-dip 45 }
-        { jit-2dip-word 46 }
-        { jit-2dip 47 }
-        { jit-3dip-word 48 }
-        { jit-3dip 49 }
+        { jit-save-stack 38 }
+        { jit-dip-word 39 }
+        { jit-dip 40 }
+        { jit-2dip-word 41 }
+        { jit-2dip 42 }
+        { jit-3dip-word 43 }
+        { jit-3dip 44 }
+        { jit-execute-word 45 }
+        { jit-execute-jump 46 }
+        { jit-execute-call 47 }
+        { pic-load 48 }
+        { pic-tag 49 }
+        { pic-hi-tag 50 }
+        { pic-tuple 51 }
+        { pic-hi-tag-tuple 52 }
+        { pic-check-tag 53 }
+        { pic-check 54 }
+        { pic-hit 55 }
+        { pic-miss-word 56 }
+        { mega-lookup 57 }
+        { mega-lookup-word 58 }
+        { mega-miss-word 59 }
         { undefined-quot 60 }
     } ; inline
 
@@ -205,8 +247,8 @@ SYMBOL: undefined-quot
 
 : emit-fixnum ( n -- ) tag-fixnum emit ;
 
-: emit-object ( header tag quot -- addr )
-    swap here-as [ swap tag-fixnum emit call align-here ] dip ;
+: emit-object ( class quot -- addr )
+    over tag-number here-as [ swap type-number tag-fixnum emit call align-here ] dip ;
     inline
 
 ! Write an object to the image.
@@ -251,7 +293,7 @@ GENERIC: ' ( obj -- ptr )
 
 M: bignum '
     [
-        bignum tag-number dup [ emit-bignum ] emit-object
+        bignum [ emit-bignum ] emit-object
     ] cache-object ;
 
 ! Fixnums
@@ -274,7 +316,7 @@ M: fake-bignum ' n>> tag-fixnum ;
 
 M: float '
     [
-        float tag-number dup [
+        float [
             align-here double>bits emit-64
         ] emit-object
     ] cache-object ;
@@ -309,7 +351,7 @@ M: f '
                     [ vocabulary>> , ]
                     [ def>> , ]
                     [ props>> , ]
-                    [ drop f , ]
+                    [ direct-entry-def>> , ] ! direct-entry-def
                     [ drop 0 , ] ! count
                     [ word-sub-primitive , ]
                     [ drop 0 , ] ! xt
@@ -318,8 +360,7 @@ M: f '
                 } cleave
             ] { } make [ ' ] map
         ] bi
-        \ word type-number object tag-number
-        [ emit-seq ] emit-object
+        \ word [ emit-seq ] emit-object
     ] keep put-object ;
 
 : word-error ( word msg -- * )
@@ -340,8 +381,7 @@ M: word ' ;
 ! Wrappers
 
 M: wrapper '
-    wrapped>> ' wrapper type-number object tag-number
-    [ emit ] emit-object ;
+    wrapped>> ' wrapper [ emit ] emit-object ;
 
 ! Strings
 : native> ( object -- object )
@@ -370,7 +410,7 @@ M: wrapper '
 
 : emit-string ( string -- ptr )
     [ length ] [ extended-part ' ] [ ] tri
-    string type-number object tag-number [
+    string [
         [ emit-fixnum ]
         [ emit ]
         [ f ' emit ascii-part pad-bytes emit-bytes ]
@@ -387,12 +427,11 @@ M: string '
 
 : emit-dummy-array ( obj type -- ptr )
     [ assert-empty ] [
-        type-number object tag-number
         [ 0 emit-fixnum ] emit-object
     ] bi* ;
 
 M: byte-array '
-    byte-array type-number object tag-number [
+    byte-array [
         dup length emit-fixnum
         pad-bytes emit-bytes
     ] emit-object ;
@@ -406,7 +445,7 @@ ERROR: tuple-removed class ;
 : (emit-tuple) ( tuple -- pointer )
     [ tuple-slots ]
     [ class transfer-word require-tuple-layout ] bi prefix [ ' ] map
-    tuple type-number dup [ emit-seq ] emit-object ;
+    tuple [ emit-seq ] emit-object ;
 
 : emit-tuple ( tuple -- pointer )
     dup class name>> "tombstone" =
@@ -421,8 +460,7 @@ M: tombstone '
 
 ! Arrays
 : emit-array ( array -- offset )
-    [ ' ] map array type-number object tag-number
-    [ [ length emit-fixnum ] [ emit-seq ] bi ] emit-object ;
+    [ ' ] map array [ [ length emit-fixnum ] [ emit-seq ] bi ] emit-object ;
 
 M: array ' emit-array ;
 
@@ -448,7 +486,7 @@ M: tuple-layout-array '
 M: quotation '
     [
         array>> '
-        quotation type-number object tag-number [
+        quotation [
             emit ! array
             f ' emit ! compiled
             f ' emit ! cached-effect
@@ -480,15 +518,16 @@ M: quotation '
 
 : emit-jit-data ( -- )
     \ if jit-if-word set
-    \ dispatch jit-dispatch-word set
     \ do-primitive jit-primitive-word set
-    \ declare jit-declare-word set
     \ dip jit-dip-word set
     \ 2dip jit-2dip-word set
     \ 3dip jit-3dip-word set
+    \ (execute) jit-execute-word set
+    \ inline-cache-miss \ pic-miss-word set
+    \ mega-cache-lookup \ mega-lookup-word set
+    \ mega-cache-miss \ mega-miss-word set
     [ undefined ] undefined-quot set
     {
-        jit-code-format
         jit-prolog
         jit-primitive-word
         jit-primitive
@@ -498,19 +537,31 @@ M: quotation '
         jit-if-word
         jit-if-1
         jit-if-2
-        jit-dispatch-word
-        jit-dispatch
         jit-dip-word
         jit-dip
         jit-2dip-word
         jit-2dip
         jit-3dip-word
         jit-3dip
+        jit-execute-word
+        jit-execute-jump
+        jit-execute-call
         jit-epilog
         jit-return
         jit-profiling
-        jit-declare-word
         jit-save-stack
+        pic-load
+        pic-tag
+        pic-hi-tag
+        pic-tuple
+        pic-hi-tag-tuple
+        pic-check-tag
+        pic-check
+        pic-hit
+        pic-miss-word
+        mega-lookup
+        mega-lookup-word
+        mega-miss-word
         undefined-quot
     } [ emit-userenv ] each ;
 
index cc853e4842875cbb0015598c287d7e50cbb98534..14c08c070aec92d9b857483e93c4ee724795644e 100644 (file)
@@ -35,10 +35,6 @@ SYMBOL: bootstrap-time
     "Core bootstrap completed in " write core-bootstrap-time get print-time
     "Bootstrap completed in "      write bootstrap-time      get print-time
 
-    [ optimized>> ] count-words " compiled words" print
-    [ symbol? ] count-words " symbol words" print
-    [ ] count-words " words total" print
-    
     "Bootstrapping is complete." print
     "Now, you can run Factor:" print
     vm write " -i=" write "output-image" get print flush ;
index 508cbb0a49596f6839bd65b60751097e85e1b443..caab530a23fb798437af2d216567a0e99e1ee36f 100644 (file)
@@ -1,5 +1,5 @@
-USING: calendar namespaces alien.c-types system windows
-windows.kernel32 kernel math combinators ;
+USING: calendar namespaces alien.c-types system
+windows.kernel32 kernel math combinators windows.errors ;
 IN: calendar.windows
 
 M: windows gmt-offset ( -- hours minutes seconds )
index 69d698f9b10c1943a4170eebe2f92d64ddd59cf8..3e933e66430a231cf6794b5c9374af1a21180d4c 100644 (file)
@@ -7,7 +7,7 @@ compiler.units lexer init ;
 IN: cocoa
 
 : (remember-send) ( selector variable -- )
-    global [ dupd ?set-at ] change-at ;
+    [ dupd ?set-at ] change-global ;
 
 SYMBOL: sent-messages
 
index 84a1ad46a3a0c1c64689b041978dfbdbfe59e03a..7761286127dcf780590cd21d9d3000605d791749 100644 (file)
@@ -12,6 +12,9 @@ IN: cocoa.dialogs
     dup 1 -> setResolvesAliases:
     dup 1 -> setAllowsMultipleSelection: ;
 
+: <NSDirPanel> ( -- panel ) <NSOpenPanel>
+   dup 1 -> setCanChooseDirectories: ;
+
 : <NSSavePanel> ( -- panel )
     NSSavePanel -> savePanel
     dup 1 -> setCanChooseFiles:
@@ -21,10 +24,12 @@ IN: cocoa.dialogs
 CONSTANT: NSOKButton 1
 CONSTANT: NSCancelButton 0
 
-: open-panel ( -- paths )
-    <NSOpenPanel>
+: (open-panel) ( panel -- paths )
     dup -> runModal NSOKButton =
     [ -> filenames CF>string-array ] [ drop f ] if ;
+    
+: open-panel ( -- paths ) <NSOpenPanel> (open-panel) ;
+: open-dir-panel ( -- paths ) <NSDirPanel> (open-panel) ;
 
 : split-path ( path -- dir file )
     "/" split1-last [ <NSString> ] bi@ ;
index 3d06bd97b7a88232a44a2ea69e222d893a4660f6..5aeb49d6f27397a0ac22f9386879bbd7f721fd11 100644 (file)
@@ -1,5 +1,4 @@
-USING: help.markup help.syntax parser vocabs.loader strings
-command-line.private ;
+USING: help.markup help.syntax parser vocabs.loader strings ;
 IN: command-line
 
 HELP: run-bootstrap-init
@@ -53,6 +52,7 @@ ARTICLE: "runtime-cli-args" "Command line switches for the VM"
     { { $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 "-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)." ;
index 3a4c702bc563535758057098911c9a15c41c10eb..938dbbccbf9a073e9677da362bffc263fe04499c 100644 (file)
@@ -27,11 +27,11 @@ IN: compiler.cfg.intrinsics.allot
         [ tuple ##set-slots ] [ ds-push drop ] 2bi
     ] [ drop emit-primitive ] if ;
 
-: store-length ( len reg -- )
-    [ ^^load-literal ] dip 1 object tag-number ##set-slot-imm ;
+: store-length ( len reg class -- )
+    [ [ ^^load-literal ] dip 1 ] dip tag-number ##set-slot-imm ;
 
-: store-initial-element ( elt reg len -- )
-    [ 2 + object tag-number ##set-slot-imm ] with with each ;
+:: store-initial-element ( len reg elt class -- )
+    len [ [ elt reg ] dip 2 + class tag-number ##set-slot-imm ] each ;
 
 : expand-<array>? ( obj -- ? )
     dup integer? [ 0 8 between? ] [ drop f ] if ;
@@ -42,8 +42,8 @@ IN: compiler.cfg.intrinsics.allot
             [let | elt [ ds-pop ]
                    reg [ len ^^allot-array ] |
                 ds-drop
-                len reg store-length
-                elt reg len store-initial-element
+                len reg array store-length
+                len reg elt array store-initial-element
                 reg ds-push
             ]
         ] [ node emit-primitive ] if
@@ -57,16 +57,16 @@ IN: compiler.cfg.intrinsics.allot
 : emit-allot-byte-array ( len -- dst )
     ds-drop
     dup ^^allot-byte-array
-    [ store-length ] [ ds-push ] [ ] tri ;
+    [ byte-array store-length ] [ ds-push ] [ ] tri ;
 
 : emit-(byte-array) ( node -- )
     dup node-input-infos first literal>> dup expand-<byte-array>?
     [ nip emit-allot-byte-array drop ] [ drop emit-primitive ] if ;
 
-: emit-<byte-array> ( node -- )
-    dup node-input-infos first literal>> dup expand-<byte-array>? [
-        nip
-        [ 0 ^^load-literal ] dip
-        [ emit-allot-byte-array ] keep
-        bytes>cells store-initial-element
-    ] [ drop emit-primitive ] if ;
+:: emit-<byte-array> ( node -- )
+    node node-input-infos first literal>> dup expand-<byte-array>? [
+        :> len
+        0 ^^load-literal :> elt
+        len emit-allot-byte-array :> reg
+        len reg elt byte-array store-initial-element
+    ] [ drop node emit-primitive ] if ;
index 3d0a7bec9c39a50667b4d4695bb884c3d652646b..ec819f9440e24dd7c92db3c0725de7537ac94dfb 100644 (file)
@@ -52,8 +52,6 @@ IN: compiler.cfg.intrinsics
     arrays:<array>
     byte-arrays:<byte-array>
     byte-arrays:(byte-array)
-    math.private:<complex>
-    math.private:<ratio>
     kernel:<wrapper>
     alien.accessors:alien-unsigned-1
     alien.accessors:set-alien-unsigned-1
@@ -140,8 +138,6 @@ IN: compiler.cfg.intrinsics
         { \ arrays:<array> [ emit-<array> iterate-next ] }
         { \ byte-arrays:<byte-array> [ emit-<byte-array> iterate-next ] }
         { \ byte-arrays:(byte-array) [ emit-(byte-array) iterate-next ] }
-        { \ math.private:<complex> [ emit-simple-allot iterate-next ] }
-        { \ math.private:<ratio> [ emit-simple-allot iterate-next ] }
         { \ kernel:<wrapper> [ emit-simple-allot iterate-next ] }
         { \ alien.accessors:alien-unsigned-1 [ 1 emit-alien-unsigned-getter iterate-next ] }
         { \ alien.accessors:set-alien-unsigned-1 [ 1 emit-alien-integer-setter iterate-next ] }
index ac9603522effc4debda56f26f76806817b5d699c..abd272081784564b405efe15ed95adc43ab528d0 100644 (file)
@@ -92,7 +92,7 @@ sequences ;
         T{ ##load-reference f V int-regs 1 + }
         T{ ##peek f V int-regs 2 D 0 }
         T{ ##compare f V int-regs 4 V int-regs 2 V int-regs 1 cc> }
-        T{ ##compare-imm f V int-regs 6 V int-regs 4 7 cc/= }
+        T{ ##compare-imm f V int-regs 6 V int-regs 4 5 cc/= }
         T{ ##replace f V int-regs 6 D 0 }
     } value-numbering trim-temps
 ] unit-test
@@ -110,7 +110,7 @@ sequences ;
         T{ ##load-reference f V int-regs 1 + }
         T{ ##peek f V int-regs 2 D 0 }
         T{ ##compare f V int-regs 4 V int-regs 2 V int-regs 1 cc<= }
-        T{ ##compare-imm f V int-regs 6 V int-regs 4 7 cc= }
+        T{ ##compare-imm f V int-regs 6 V int-regs 4 5 cc= }
         T{ ##replace f V int-regs 6 D 0 }
     } value-numbering trim-temps
 ] unit-test
@@ -132,7 +132,7 @@ sequences ;
         T{ ##unbox-float f V double-float-regs 10 V int-regs 8 }
         T{ ##unbox-float f V double-float-regs 11 V int-regs 9 }
         T{ ##compare-float f V int-regs 12 V double-float-regs 10 V double-float-regs 11 cc< }
-        T{ ##compare-imm f V int-regs 14 V int-regs 12 7 cc= }
+        T{ ##compare-imm f V int-regs 14 V int-regs 12 5 cc= }
         T{ ##replace f V int-regs 14 D 0 }
     } value-numbering trim-temps
 ] unit-test
@@ -149,6 +149,6 @@ sequences ;
         T{ ##peek f V int-regs 29 D -1 }
         T{ ##peek f V int-regs 30 D -2 }
         T{ ##compare f V int-regs 33 V int-regs 29 V int-regs 30 cc<= }
-        T{ ##compare-imm-branch f V int-regs 33 7 cc/= }
+        T{ ##compare-imm-branch f V int-regs 33 5 cc/= }
     } value-numbering trim-temps
 ] unit-test
index 2a0456e3b7a820533a4a997be8eedffd0497dc8a..c19707a6943128031f8c83a75ee6b6f3a44977ee 100755 (executable)
@@ -44,7 +44,7 @@ SYMBOL: calls
 
 SYMBOL: compiling-word
 
-: compiled-stack-traces? ( -- ? ) 59 getenv ;
+: compiled-stack-traces? ( -- ? ) 67 getenv ;
 
 ! Mapping _label IDs to label instances
 SYMBOL: labels
index 3a047a8d3915481cb035583bce86803bbf977ed7..99f258d93c618faa0f143b9f575c59a23792b144 100755 (executable)
@@ -3,15 +3,13 @@
 USING: arrays byte-arrays byte-vectors generic assocs hashtables
 io.binary kernel kernel.private math namespaces make sequences
 words quotations strings alien.accessors alien.strings layouts
-system combinators math.bitwise words.private math.order
+system combinators math.bitwise math.order
 accessors growable cpu.architecture compiler.constants ;
 IN: compiler.codegen.fixup
 
 GENERIC: fixup* ( obj -- )
 
-: code-format ( -- n ) 22 getenv ;
-
-: compiled-offset ( -- n ) building get length code-format * ;
+: compiled-offset ( -- n ) building get length ;
 
 SYMBOL: relocation-table
 SYMBOL: label-table
@@ -25,7 +23,7 @@ TUPLE: label-fixup label class ;
 M: label-fixup fixup*
     dup class>> rc-absolute?
     [ "Absolute labels not supported" throw ] when
-    [ label>> ] [ class>> ] bi compiled-offset 4 - rot
+    [ class>> ] [ label>> ] bi compiled-offset 4 - swap
     3array label-table get push ;
 
 TUPLE: rel-fixup class type ;
@@ -58,6 +56,9 @@ SYMBOL: literal-table
 : rel-word ( word class -- )
     [ add-literal ] dip rt-xt rel-fixup ;
 
+: rel-word-direct ( word class -- )
+    [ add-literal ] dip rt-xt-direct rel-fixup ;
+
 : rel-primitive ( word class -- )
     [ def>> first add-literal ] dip rt-primitive rel-fixup ;
 
@@ -88,4 +89,4 @@ SYMBOL: literal-table
         literal-table get >array
         relocation-table get >byte-array
         label-table get resolve-labels
-    ] { } make 4array ;
+    ] B{ } make 4array ;
index b96d5e573a2cb7bd6fab83cce68ed665607524cc..306ab515a8854c41f4543b64326bcc8ea068123e 100644 (file)
@@ -1,19 +1,19 @@
 USING: assocs compiler.cfg.builder compiler.cfg.optimizer
 compiler.errors compiler.tree.builder compiler.tree.optimizer
 compiler.units help.markup help.syntax io parser quotations
-sequences words words.private ;
+sequences words ;
 IN: compiler
 
-HELP: enable-compiler
+HELP: enable-optimizer
 { $description "Enables the optimizing compiler." } ;
 
-HELP: disable-compiler
+HELP: disable-optimizer
 { $description "Disable the optimizing compiler." } ;
 
 ARTICLE: "compiler-usage" "Calling the optimizing compiler"
 "Normally, new word definitions are recompiled automatically. This can be changed:"
-{ $subsection disable-compiler }
-{ $subsection enable-compiler }
+{ $subsection disable-optimizer }
+{ $subsection enable-optimizer }
 "Removing a word's optimized definition:"
 { $subsection decompile }
 "Compiling a single quotation:"
index ee91d04b3d93fd1eba5d0117aee9a6d64daeb760..e418f0ef608320cccd9d7e36002539568cbfa658 100644 (file)
@@ -2,19 +2,20 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors kernel namespaces arrays sequences io words fry
 continuations vocabs assocs dlists definitions math graphs generic
-combinators deques search-deques macros io source-files.errors
-stack-checker stack-checker.state stack-checker.inlining
-stack-checker.errors combinators.short-circuit compiler.errors
-compiler.units compiler.tree.builder compiler.tree.optimizer
-compiler.cfg.builder compiler.cfg.optimizer compiler.cfg.linearization
-compiler.cfg.two-operand compiler.cfg.linear-scan
-compiler.cfg.stack-frame compiler.codegen compiler.utilities ;
+generic.single combinators deques search-deques macros io
+source-files.errors stack-checker stack-checker.state
+stack-checker.inlining stack-checker.errors combinators.short-circuit
+compiler.errors compiler.units compiler.tree.builder
+compiler.tree.optimizer compiler.cfg.builder compiler.cfg.optimizer
+compiler.cfg.linearization compiler.cfg.two-operand
+compiler.cfg.linear-scan compiler.cfg.stack-frame compiler.codegen
+compiler.utilities ;
 IN: compiler
 
 SYMBOL: compile-queue
 SYMBOL: compiled
 
-: queue-compile? ( word -- ? )
+: compile? ( word -- ? )
     #! Don't attempt to compile certain words.
     {
         [ "forgotten" word-prop ]
@@ -24,7 +25,7 @@ SYMBOL: compiled
     } 1|| not ;
 
 : queue-compile ( word -- )
-    dup queue-compile? [ compile-queue get push-front ] [ drop ] if ;
+    dup compile? [ compile-queue get push-front ] [ drop ] if ;
 
 : recompile-callers? ( word -- ? )
     changed-effects get key? ;
@@ -41,6 +42,14 @@ SYMBOL: compiled
     H{ } clone generic-dependencies set
     clear-compiler-error ;
 
+GENERIC: no-compile? ( word -- ? )
+
+M: word no-compile? "no-compile" word-prop ;
+
+M: method-body no-compile? "method-generic" word-prop no-compile? ;
+
+M: predicate-engine-word no-compile? "owner-generic" word-prop no-compile? ;
+
 : ignore-error? ( word error -- ? )
     #! Ignore some errors on inline combinators, macros, and special
     #! words such as 'call'.
@@ -48,8 +57,8 @@ SYMBOL: compiled
         {
             [ macro? ]
             [ inline? ]
+            [ no-compile? ]
             [ "special" word-prop ]
-            [ "no-compile" word-prop ]
         } 1||
     ] [
         {
@@ -80,32 +89,46 @@ SYMBOL: compiled
 : not-compiled-def ( word error -- def )
     '[ _ _ not-compiled ] [ ] like ;
 
+: ignore-error ( word error -- * )
+    drop
+    [ clear-compiler-error ]
+    [ dup def>> deoptimize-with ]
+    bi ;
+
+: remember-error ( word error -- * )
+    [ swap <compiler-error> compiler-error ]
+    [ [ drop ] [ not-compiled-def ] 2bi deoptimize-with ]
+    2bi ;
+
 : deoptimize ( word error -- * )
     #! If the error is ignorable, compile the word with the
     #! non-optimizing compiler, using its definition. Otherwise,
     #! if the compiler error is not ignorable, use a dummy
     #! definition from 'not-compiled-def' which throws an error.
-    2dup ignore-error? [
-        drop
-        [ dup def>> deoptimize-with ]
-        [ clear-compiler-error ]
-        bi
-    ] [
-        [ swap <compiler-error> compiler-error ]
-        [ [ drop ] [ not-compiled-def ] 2bi deoptimize-with ]
-        2bi
-    ] if ;
+    {
+        { [ dup inference-error? not ] [ rethrow ] }
+        { [ 2dup ignore-error? ] [ ignore-error ] }
+        [ remember-error ]
+    } cond ;
+
+: optimize? ( word -- ? )
+    {
+        [ predicate-engine-word? ]
+        [ contains-breakpoints? ]
+        [ single-generic? ]
+    } 1|| not ;
 
 : frontend ( word -- nodes )
     #! If the word contains breakpoints, don't optimize it, since
     #! the walker does not support this.
-    dup contains-breakpoints? [ dup def>> deoptimize-with ] [
-        [ build-tree ] [ deoptimize ] recover optimize-tree
-    ] if ;
+    dup optimize?
+    [ [ build-tree ] [ deoptimize ] recover optimize-tree ]
+    [ dup def>> deoptimize-with ]
+    if ;
 
 : compile-dependency ( word -- )
     #! If a word calls an unoptimized word, try to compile the callee.
-    dup optimized>> [ drop ] [ queue-compile ] if ;
+    dup optimized? [ drop ] [ queue-compile ] if ;
 
 ! Only switch this off for debugging.
 SYMBOL: compile-dependencies?
@@ -161,15 +184,21 @@ M: optimizing-compiler recompile ( words -- alist )
     [
         <hashed-dlist> compile-queue set
         H{ } clone compiled set
-        [ queue-compile ] each
+        [
+            [ queue-compile ]
+            [ subwords [ compile-dependency ] each ] bi
+        ] each
         compile-queue get compile-loop
         compiled get >alist
     ] with-scope ;
 
-: enable-compiler ( -- )
+: with-optimizer ( quot -- )
+    [ optimizing-compiler compiler-impl ] dip with-variable ; inline
+
+: enable-optimizer ( -- )
     optimizing-compiler compiler-impl set-global ;
 
-: disable-compiler ( -- )
+: disable-optimizer ( -- )
     f compiler-impl set-global ;
 
 : recompile-all ( -- )
index b3757bf008ae4ddf0966fbdd2bf518b77b53e66b..2f0494b58aecbfb64f38a46384472420faa6c629 100644 (file)
@@ -1,6 +1,7 @@
-! Copyright (C) 2008 Slava Pestov.
+! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: math kernel layouts system strings ;
+USING: math kernel layouts system strings words quotations byte-arrays
+alien arrays ;
 IN: compiler.constants
 
 ! These constants must match vm/memory.h
@@ -11,18 +12,17 @@ CONSTANT: deck-bits 18
 ! These constants must match vm/layouts.h
 : header-offset ( -- n ) object tag-number neg ; inline
 : float-offset ( -- n ) 8 float tag-number - ; inline
-: string-offset ( -- n ) 4 bootstrap-cells object tag-number - ; inline
+: string-offset ( -- n ) 4 bootstrap-cells string tag-number - ; inline
 : string-aux-offset ( -- n ) 2 bootstrap-cells string tag-number - ; inline
-: profile-count-offset ( -- n ) 7 bootstrap-cells object tag-number - ; inline
-: byte-array-offset ( -- n ) 2 bootstrap-cells object tag-number - ; inline
-: alien-offset ( -- n ) 3 bootstrap-cells object tag-number - ; inline
-: underlying-alien-offset ( -- n ) bootstrap-cell object tag-number - ; inline
+: profile-count-offset ( -- n ) 7 bootstrap-cells \ word tag-number - ; inline
+: byte-array-offset ( -- n ) 2 bootstrap-cells byte-array tag-number - ; inline
+: alien-offset ( -- n ) 3 bootstrap-cells alien tag-number - ; inline
+: underlying-alien-offset ( -- n ) bootstrap-cell alien tag-number - ; inline
 : tuple-class-offset ( -- n ) bootstrap-cell tuple tag-number - ; inline
-: class-hash-offset ( -- n ) bootstrap-cell object tag-number - ; inline
-: word-xt-offset ( -- n ) 9 bootstrap-cells object tag-number - ; inline
-: quot-xt-offset ( -- n ) 5 bootstrap-cells object tag-number - ; inline
-: word-code-offset ( -- n ) 10 bootstrap-cells object tag-number - ; inline
-: array-start-offset ( -- n ) 2 bootstrap-cells object tag-number - ; inline
+: word-xt-offset ( -- n ) 9 bootstrap-cells \ word tag-number - ; inline
+: quot-xt-offset ( -- n ) 5 bootstrap-cells quotation tag-number - ; inline
+: word-code-offset ( -- n ) 10 bootstrap-cells \ word tag-number - ; inline
+: array-start-offset ( -- n ) 2 bootstrap-cells array tag-number - ; inline
 : compiled-header-size ( -- n ) 5 bootstrap-cells ; inline
 
 ! Relocation classes
@@ -41,10 +41,12 @@ CONSTANT: rt-primitive   0
 CONSTANT: rt-dlsym       1
 CONSTANT: rt-dispatch    2
 CONSTANT: rt-xt          3
-CONSTANT: rt-here        4
-CONSTANT: rt-this        5
-CONSTANT: rt-immediate   6
-CONSTANT: rt-stack-chain 7
+CONSTANT: rt-xt-direct   4
+CONSTANT: rt-here        5
+CONSTANT: rt-this        6
+CONSTANT: rt-immediate   7
+CONSTANT: rt-stack-chain 8
+CONSTANT: rt-untagged    9
 
 : rc-absolute? ( n -- ? )
     [ rc-absolute-ppc-2/2 = ]
diff --git a/basis/compiler/tests/call-effect.factor b/basis/compiler/tests/call-effect.factor
new file mode 100644 (file)
index 0000000..a9fd313
--- /dev/null
@@ -0,0 +1,14 @@
+IN: compiler.tests.call-effect
+USING: tools.test combinators generic.single sequences kernel ;
+
+: execute-ic-test ( a b -- c ) execute( a -- c ) ;
+
+! VM type check error
+[ 1 f execute-ic-test ] [ second 3 = ] must-fail-with
+
+: call-test ( q -- ) call( -- ) ;
+
+[ ] [ [ ] call-test ] unit-test
+[ ] [ f [ drop ] curry call-test ] unit-test
+[ ] [ [ ] [ ] compose call-test ] unit-test
+[ [ 1 2 3 ] call-test ] [ wrong-values? ] must-fail-with
\ No newline at end of file
index c746fdfb45ba5b06fe915ee888ec4169dbac4658..8fbe13ce51945bca40f457993e40f791ae0feaf8 100644 (file)
@@ -26,7 +26,7 @@ IN: compiler.tests.codegen
 
 [ 2 3 4 ] [ 3 [ 2 swap 4 ] compile-call ] unit-test
 
-[ { 1 2 3 } { 1 4 3 } 3 3 ]
+[ { 1 2 3 } { 1 4 3 } 2 2 ]
 [ { 1 2 3 } { 1 4 3 } [ over tag over tag ] compile-call ]
 unit-test
 
@@ -37,7 +37,7 @@ unit-test
 
 : foo ( -- ) ;
 
-[ 5 5 ]
+[ 3 3 ]
 [ 1.2 [ tag [ foo ] keep ] compile-call ]
 unit-test
 
@@ -211,7 +211,7 @@ TUPLE: my-tuple ;
     { tuple vector } 3 slot { word } declare
     dup 1 slot 0 fixnum-bitand { [ ] } dispatch ;
 
-[ t ] [ \ dispatch-alignment-regression optimized>> ] unit-test
+[ t ] [ \ dispatch-alignment-regression optimized? ] unit-test
 
 [ vector ] [ dispatch-alignment-regression ] unit-test
 
index 1a604dbd8ede3ae83e17a3458059eeb9ea6bd5a2..7074b73845e46aacafbf77d71d5844840d33cd6f 100644 (file)
@@ -9,7 +9,7 @@ math.private tools.test math.floats.private ;
 
 [ 3.0 1 2 3 ] [ 1.0 2.0 [ float+ 1 2 3 ] compile-call ] unit-test
 
-[ 5 ] [ 1.0 [ 2.0 float+ tag ] compile-call ] unit-test
+[ 3 ] [ 1.0 [ 2.0 float+ tag ] compile-call ] unit-test
 
 [ 3.0 ] [ 1.0 [ 2.0 float+ ] compile-call ] unit-test
 [ 3.0 ] [ 1.0 [ 2.0 swap float+ ] compile-call ] unit-test
diff --git a/basis/compiler/tests/generic.factor b/basis/compiler/tests/generic.factor
new file mode 100644 (file)
index 0000000..6b0ef2d
--- /dev/null
@@ -0,0 +1,11 @@
+IN: compiler.tests.generic
+USING: tools.test math kernel compiler.units definitions ;
+
+GENERIC: bad ( -- )
+M: integer bad ;
+M: object bad ;
+
+[ 0 bad ] must-fail
+[ "" bad ] must-fail
+
+[ ] [ [ \ bad forget ] with-compilation-unit ] unit-test
\ No newline at end of file
index a6e827ea3372c337cc6d877deb2fdad832fcaa19..5ca0f3f109905d0a8b2a5c8cb18f74f9284d9fa5 100644 (file)
@@ -342,12 +342,12 @@ cell 8 = [
 ] unit-test
 
 [ 1 2 ] [
-    1 2 [ <complex> ] compile-call
+    1 2 [ complex boa ] compile-call
     dup real-part swap imaginary-part
 ] unit-test
 
 [ 1 2 ] [
-    1 2 [ <ratio> ] compile-call dup numerator swap denominator
+    1 2 [ ratio boa ] compile-call dup numerator swap denominator
 ] unit-test
 
 [ \ + ] [ \ + [ <wrapper> ] compile-call ] unit-test
index bd7008f9099a51f80e944a5eb8ea3ccb1f24fdbe..f19a950711e1993f6b42d3f8e9d6e0df34fdf38a 100644 (file)
@@ -4,13 +4,13 @@ sbufs strings tools.test vectors words sequences.private
 quotations classes classes.algebra classes.tuple.private
 continuations growable namespaces hints alien.accessors
 compiler.tree.builder compiler.tree.optimizer sequences.deep
-compiler ;
+compiler definitions ;
 IN: compiler.tests.optimizer
 
 GENERIC: xyz ( obj -- obj )
 M: array xyz xyz ;
 
-[ t ] [ \ xyz optimized>> ] unit-test
+[ t ] [ M\ array xyz optimized? ] unit-test
 
 ! Test predicate inlining
 : pred-test-1 ( a -- b c )
@@ -95,7 +95,7 @@ TUPLE: pred-test ;
 ! regression
 GENERIC: void-generic ( obj -- * )
 : breakage ( -- * ) "hi" void-generic ;
-[ t ] [ \ breakage optimized>> ] unit-test
+[ t ] [ \ breakage optimized? ] unit-test
 [ breakage ] must-fail
 
 ! regression
@@ -120,7 +120,7 @@ GENERIC: void-generic ( obj -- * )
 ! compiling <tuple> with a non-literal class failed
 : <tuple>-regression ( class -- tuple ) <tuple> ;
 
-[ t ] [ \ <tuple>-regression optimized>> ] unit-test
+[ t ] [ \ <tuple>-regression optimized? ] unit-test
 
 GENERIC: foozul ( a -- b )
 M: reversed foozul ;
@@ -229,7 +229,7 @@ USE: binary-search.private
 : node-successor-f-bug ( x -- * )
     [ 3 throw ] [ empty-compound ] compose [ 3 throw ] if ;
 
-[ t ] [ \ node-successor-f-bug optimized>> ] unit-test
+[ t ] [ \ node-successor-f-bug optimized? ] unit-test
 
 [ ] [ [ new ] build-tree optimize-tree drop ] unit-test
 
@@ -243,7 +243,7 @@ USE: binary-search.private
         ] if
     ] if ;
 
-[ t ] [ \ lift-throw-tail-regression optimized>> ] unit-test
+[ t ] [ \ lift-throw-tail-regression optimized? ] unit-test
 [ 3 "an integer" ] [ 3 lift-throw-tail-regression ] unit-test
 [ "hi" "a string" ] [ "hi" lift-throw-tail-regression ] unit-test
 
@@ -274,7 +274,7 @@ HINTS: recursive-inline-hang array ;
 : recursive-inline-hang-1 ( -- a )
     { } recursive-inline-hang ;
 
-[ t ] [ \ recursive-inline-hang-1 optimized>> ] unit-test
+[ t ] [ \ recursive-inline-hang-1 optimized? ] unit-test
 
 DEFER: recursive-inline-hang-3
 
@@ -325,7 +325,7 @@ PREDICATE: list < improper-list
     dup "a" get { array-capacity } declare >=
     [ dup "b" get { array-capacity } declare >= [ 3 ] [ 4 ] if ] [ 5 ] if ;
 
-[ t ] [ \ interval-inference-bug optimized>> ] unit-test
+[ t ] [ \ interval-inference-bug optimized? ] unit-test
 
 [ ] [ 1 "a" set 2 "b" set ] unit-test
 [ 2 3 ] [ 2 interval-inference-bug ] unit-test
@@ -384,3 +384,9 @@ DEFER: loop-bbb
     1 >bignum 2 >bignum
     [ { bignum integer } declare [ shift ] keep 1+ ] compile-call
 ] unit-test
+
+: broken-declaration ( -- ) \ + declare ;
+
+[ f ] [ \ broken-declaration optimized? ] unit-test
+
+[ ] [ [ \ broken-declaration forget ] with-compilation-unit ] unit-test
\ No newline at end of file
index e10713530596f2daed2c236a41049a666ad8f368..95d454fed18d1b6ec12a1a02b7f6e0a5d448432c 100644 (file)
@@ -4,7 +4,7 @@
 ! optimization, which would batch generic word updates at the
 ! end of a compilation unit.
 
-USING: kernel accessors peg.ebnf ;
+USING: kernel accessors peg.ebnf words ;
 IN: compiler.tests.peg-regression
 
 TUPLE: pipeline-expr background ;
@@ -22,5 +22,5 @@ pipeline = "hello" => [[ ast>pipeline-expr ]]
 
 USE: tools.test
 
-[ t ] [ \ expr optimized>> ] unit-test
-[ t ] [ \ ast>pipeline-expr optimized>> ] unit-test
+[ t ] [ \ expr optimized? ] unit-test
+[ t ] [ \ ast>pipeline-expr optimized? ] unit-test
diff --git a/basis/compiler/tests/pic-problem-1.factor b/basis/compiler/tests/pic-problem-1.factor
new file mode 100644 (file)
index 0000000..4adf0b3
--- /dev/null
@@ -0,0 +1,14 @@
+IN: compiler.tests.pic-problem-1
+USING: kernel sequences prettyprint memory tools.test ;
+
+TUPLE: x ;
+
+M: x length drop 0 ;
+
+INSTANCE: x sequence
+
+<< gc >>
+
+CONSTANT: blah T{ x }
+
+[ T{ x } ] [ blah ] unit-test
\ No newline at end of file
index 807f3ed2c7161c3c2726cbeb1d26ef58e1bc7807..a72db4833ca7db960ecbabae9af4b33a7e860ba0 100644 (file)
@@ -1,8 +1,8 @@
 USING: compiler.units definitions tools.test sequences ;
 IN: compiler.tests.redefine14
 
-TUPLE: bad ;
-! 
-M: bad length 1 2 3 ;
-! 
-! [ ] [ [ { bad length } forget ] with-compilation-unit ] unit-test
+TUPLE: bad ;
+
+M: bad length 1 2 3 ;
+
+[ ] [ [ M\ bad length forget ] with-compilation-unit ] unit-test
diff --git a/basis/compiler/tests/redefine17.factor b/basis/compiler/tests/redefine17.factor
new file mode 100644 (file)
index 0000000..4ed3e36
--- /dev/null
@@ -0,0 +1,49 @@
+IN: compiler.tests.redefine17
+USING: tools.test classes.mixin compiler.units arrays kernel.private
+strings sequences vocabs definitions kernel ;
+
+<< "compiler.tests.redefine17" words forget-all >>
+
+GENERIC: bong ( a -- b )
+
+M: array bong ;
+
+M: string bong length ;
+
+MIXIN: mixin
+
+INSTANCE: array mixin
+
+: blah ( a -- b ) { mixin } declare bong ;
+
+[ { } ] [ { } blah ] unit-test
+
+[ ] [ [ \ array \ mixin remove-mixin-instance ] with-compilation-unit ] unit-test
+
+[ ] [ [ \ string \ mixin add-mixin-instance ] with-compilation-unit ] unit-test
+
+[ 0 ] [ "" blah ] unit-test
+
+MIXIN: mixin1
+
+INSTANCE: string mixin1
+
+MIXIN: mixin2
+
+GENERIC: billy ( a -- b )
+
+M: mixin2 billy ;
+
+M: array billy drop "BILLY" ;
+
+INSTANCE: string mixin2
+
+: bully ( a -- b ) { mixin1 } declare billy ;
+
+[ "" ] [ "" bully ] unit-test
+
+[ ] [ [ \ string \ mixin1 remove-mixin-instance ] with-compilation-unit ] unit-test
+
+[ ] [ [ \ array \ mixin1 add-mixin-instance ] with-compilation-unit ] unit-test
+
+[ "BILLY" ] [ { } bully ] unit-test
index 51ce33c1bd738d9fafd8c48097ca8a6158115dc1..0a5eb8457918921af36e133abc398780af86ddca 100644 (file)
@@ -14,7 +14,7 @@ M: empty-mixin sheeple drop "wake up" ;
 : sheeple-test ( -- string ) { } sheeple ;
 
 [ "sheeple" ] [ sheeple-test ] unit-test
-[ t ] [ \ sheeple-test optimized>> ] unit-test
+[ t ] [ \ sheeple-test optimized? ] unit-test
 [ t ] [ object \ sheeple method \ sheeple-test "compiled-uses" word-prop key? ] unit-test
 [ f ] [ empty-mixin \ sheeple method \ sheeple-test "compiled-uses" word-prop key? ] unit-test
 
@@ -27,6 +27,6 @@ M: empty-mixin sheeple drop "wake up" ;
 [ ] [ [ array empty-mixin remove-mixin-instance ] with-compilation-unit ] unit-test
 
 [ "sheeple" ] [ sheeple-test ] unit-test
-[ t ] [ \ sheeple-test optimized>> ] unit-test
+[ t ] [ \ sheeple-test optimized? ] unit-test
 [ t ] [ object \ sheeple method \ sheeple-test "compiled-uses" word-prop key? ] unit-test
 [ f ] [ empty-mixin \ sheeple method \ sheeple-test "compiled-uses" word-prop key? ] unit-test
index 82cc97e0f6a4c115ce4c92cf61b5b8b68cea30de..88dc9a53b1509889e02235a733c96f93f9b915cd 100644 (file)
@@ -235,6 +235,6 @@ M: f single-combination-test-2 single-combination-test-4 ;
 10 [
     [ "compiler.tests.foo" forget-vocab ] with-compilation-unit
     [ t ] [
-        "USING: prettyprint words accessors ; IN: compiler.tests.foo : (recursive) ( -- ) (recursive) (recursive) ; inline recursive : recursive ( -- ) (recursive) ; \\ (recursive) optimized>>" eval( -- obj )
+        "USING: prettyprint words accessors ; IN: compiler.tests.foo : (recursive) ( -- ) (recursive) (recursive) ; inline recursive : recursive ( -- ) (recursive) ; \\ (recursive) optimized?" eval( -- obj )
     ] unit-test
 ] times
index 2ec6fbde9520e6ebe54b7288875a693e2ad29c80..e518ff8df2fa73051db4abf15c7bc9f0cff6fc5c 100644 (file)
@@ -1,5 +1,5 @@
 USING: math.private kernel combinators accessors arrays
-generalizations tools.test ;
+generalizations tools.test words ;
 IN: compiler.tests.spilling
 
 : float-spill-bug ( a -- b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b )
@@ -47,7 +47,7 @@ IN: compiler.tests.spilling
 [ 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 2.0 ]
 [ 1.0 float-spill-bug ] unit-test
 
-[ t ] [ \ float-spill-bug optimized>> ] unit-test
+[ t ] [ \ float-spill-bug optimized? ] unit-test
 
 : float-fixnum-spill-bug ( object -- object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object object )
     {
@@ -132,7 +132,7 @@ IN: compiler.tests.spilling
 [ 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 2.0 2 ]
 [ 1.0 float-fixnum-spill-bug ] unit-test
 
-[ t ] [ \ float-fixnum-spill-bug optimized>> ] unit-test
+[ t ] [ \ float-fixnum-spill-bug optimized? ] unit-test
 
 : resolve-spill-bug ( a b -- c )
     [ 1 fixnum+fast ] bi@ dup 10 fixnum< [
@@ -159,7 +159,7 @@ IN: compiler.tests.spilling
         16 narray
     ] if ;
 
-[ t ] [ \ resolve-spill-bug optimized>> ] unit-test
+[ t ] [ \ resolve-spill-bug optimized? ] unit-test
 
 [ 4 ] [ 1 1 resolve-spill-bug ] unit-test
 
index b1dc04082eb68663dd531d444134b58eeec51a39..60cab92843e58676ef01684d2695e138f98663ce 100644 (file)
@@ -153,7 +153,7 @@ SYMBOL: node-count
             [ 1+ ] dip
             dup #call? [
                 word>> {
-                    { [ dup "intrinsics" word-prop over "if-intrinsics" word-prop or ] [ intrinsics-called ] }
+                    { [ dup "intrinsic" word-prop ] [ intrinsics-called ] }
                     { [ dup generic? ] [ generics-called ] }
                     { [ dup method-body? ] [ methods-called ] }
                     [ words-called ]
index 333b3fa636f9c792779c81d746f1d45395ec0280..ed253ad89bedd73fc621f12e3bbaa27bcf1a736c 100644 (file)
@@ -12,7 +12,6 @@ M: #push run-escape-analysis*
 
 M: #call run-escape-analysis*
     {
-        { [ dup word>> \ <complex> eq? ] [ t ] }
         { [ dup immutable-tuple-boa? ] [ t ] }
         [ f ] 
     } cond nip ;
index bcb8b2f80a2b4c5c4d0b1a92d2b13195f86b6e79..5f89372ebe2d7bec6898d15156f6c6390b5a9caf 100644 (file)
@@ -17,7 +17,7 @@ GENERIC: count-unboxed-allocations* ( m node -- n )
     out-d>> first escaping-allocation? [ 1+ ] unless ;
 
 M: #call count-unboxed-allocations*
-    dup [ immutable-tuple-boa? ] [ word>> \ <complex> eq? ] bi or
+    dup immutable-tuple-boa?
     [ (count-unboxed-allocations) ] [ drop ] if ;
 
 M: #push count-unboxed-allocations*
@@ -291,7 +291,7 @@ C: <ro-box> ro-box
 
 [ 0 ] [ [ bad-tuple-fib-3 i>> ] count-unboxed-allocations ] unit-test
 
-[ 1 ] [ [ <complex> >rect ] count-unboxed-allocations ] unit-test
+[ 1 ] [ [ complex boa >rect ] count-unboxed-allocations ] unit-test
 
 [ 0 ] [ [ 1 cons boa 2 cons boa ] count-unboxed-allocations ] unit-test
 
index fe1e60dbc25d1aa5dc6d5ba39ab347ed37a921b4..729d6a04907f8789aeedbc15d1cd5a46051a9ad7 100644 (file)
@@ -47,9 +47,6 @@ M: #push escape-analysis*
     [ record-unknown-allocation ]
     if ;
 
-: record-complex-allocation ( #call -- )
-    [ in-d>> ] [ out-d>> first ] bi record-allocation ;
-
 : slot-offset ( #call -- n/f )
     dup in-d>>
     [ first node-value-info class>> ]
@@ -71,7 +68,6 @@ M: #push escape-analysis*
 M: #call escape-analysis*
     dup word>> {
         { \ <tuple-boa> [ record-tuple-allocation ] }
-        { \ <complex> [ record-complex-allocation ] }
         { \ slot [ record-slot-call ] }
         [ drop record-unknown-allocation ]
     } case ;
index a22b7aa1727f70f801c062b5a16279fffac94a17..4d4b22218ded24298154318b4bf04084589abcad 100644 (file)
@@ -59,29 +59,18 @@ CONSTANT: object-info T{ value-info f object full-interval }
 
 : <value-info> ( -- info ) \ value-info new ;
 
-: read-only-slots ( values class -- slots )
-    all-slots
-    [ read-only>> [ drop f ] unless ] 2map
-    f prefix ;
-
 DEFER: <literal-info>
 
+: tuple-slot-infos ( tuple -- slots )
+    [ tuple-slots ] [ class all-slots ] bi
+    [ read-only>> [ <literal-info> ] [ drop f ] if ] 2map
+    f prefix ;
+
 : init-literal-info ( info -- info )
     dup literal>> class >>class
     dup literal>> dup real? [ [a,a] >>interval ] [
         [ [-inf,inf] >>interval ] dip
-        {
-            { [ dup complex? ] [
-                [ real-part <literal-info> ]
-                [ imaginary-part <literal-info> ] bi
-                2array >>slots
-            ] }
-            { [ dup tuple? ] [
-                [ tuple-slots [ <literal-info> ] map ] [ class ] bi
-                read-only-slots >>slots
-            ] }
-            [ drop ]
-        } cond
+        dup tuple? [ tuple-slot-infos >>slots ] [ drop ] if
     ] if ; inline
 
 : init-value-info ( info -- info )
index aa66b2f6d75b8d33bd11250a6dbaa949f4eb7e9f..2a7d4313148a346c01f8c006393b55924b220632 100755 (executable)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors kernel arrays sequences math math.order
-math.partial-dispatch generic generic.standard generic.math
+math.partial-dispatch generic generic.standard generic.single generic.math
 classes.algebra classes.union sets quotations assocs combinators
 words namespaces continuations classes fry combinators.smart hints
 locals
@@ -188,9 +188,7 @@ SYMBOL: history
     { curry compose } memq? ;
 
 : never-inline-word? ( word -- ? )
-    [ deferred? ]
-    [ "default" word-prop ]
-    [ { call execute } memq? ] tri or or ;
+    [ deferred? ] [ "default" word-prop ] [ \ call eq? ] tri or or ;
 
 : custom-inlining? ( word -- ? )
     "custom-inlining" word-prop ;
index f6308ac40ac4dd61b5992c8386a4009f0380c3f8..eba41dbfdf89447add34b20b193156836c49afa6 100644 (file)
@@ -9,7 +9,7 @@ compiler.tree.propagation.info compiler.tree.def-use
 compiler.tree.debugger compiler.tree.checker
 slots.private words hashtables classes assocs locals
 specialized-arrays.double system sorting math.libm
-math.intervals ;
+math.intervals quotations ;
 IN: compiler.tree.propagation.tests
 
 [ V{ } ] [ [ ] final-classes ] unit-test
@@ -357,7 +357,7 @@ TUPLE: immutable-prop-test-tuple { x sequence read-only } ;
 ] unit-test
 
 [ V{ complex } ] [
-    [ <complex> ] final-classes
+    [ complex boa ] final-classes
 ] unit-test
 
 [ V{ complex } ] [
@@ -375,7 +375,7 @@ TUPLE: immutable-prop-test-tuple { x sequence read-only } ;
 [ V{ complex } ] [
     [
         { float float object } declare
-        [ "Oops" throw ] [ <complex> ] if
+        [ "Oops" throw ] [ complex boa ] if
     ] final-classes
 ] unit-test
 
@@ -590,7 +590,7 @@ MIXIN: empty-mixin
 
 [ V{ float } ] [
     [
-        [ { float float } declare <complex> ]
+        [ { float float } declare complex boa ]
         [ 2drop C{ 0.0 0.0 } ]
         if real-part
     ] final-classes
@@ -686,3 +686,8 @@ TUPLE: littledan-2 { from read-only } { to read-only } ;
 [ V{ 0 } ] [ [ { } length ] final-literals ] unit-test
 
 [ V{ 1 } ] [ [ { } length 1+ f <array> length ] final-literals ] unit-test
+
+! Mutable tuples with circularity should not cause problems
+TUPLE: circle me ;
+
+[ ] [ circle new dup >>me 1quotation final-info drop ] unit-test
\ No newline at end of file
index 9937c6b9c4d51da1e2acc5f09442809cea9b6faf..5837d59ef9b0a0f3143b67c681b2cc4d44fb3f62 100644 (file)
@@ -109,7 +109,7 @@ M: #declare propagate-before
 
 : output-value-infos ( #call word -- infos )
     {
-        { [ dup tuple-constructor? ] [ propagate-tuple-constructor ] }
+        { [ dup \ <tuple-boa> eq? ] [ drop propagate-<tuple-boa> ] }
         { [ dup sequence-constructor? ] [ propagate-sequence-constructor ] }
         { [ dup predicate? ] [ propagate-predicate ] }
         { [ dup "outputs" word-prop ] [ call-outputs-quot ] }
index 8192b1c5209b3ad3b1f4d3e3990d69f112792919..86114772f752a4e185881d349a8bae89637dc0fd 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2008 Slava Pestov.
+! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: fry assocs arrays byte-arrays strings accessors sequences
 kernel slots classes.algebra classes.tuple classes.tuple.private
@@ -8,9 +8,6 @@ IN: compiler.tree.propagation.slots
 
 ! Propagation of immutable slots and array lengths
 
-! Revisit this code when delegation is removed and when complex
-! numbers become tuples.
-
 UNION: fixed-length-sequence array byte-array string ;
 
 : sequence-constructor? ( word -- ? )
@@ -29,33 +26,26 @@ UNION: fixed-length-sequence array byte-array string ;
     [ constructor-output-class <class-info> ]
     bi* value-info-intersect 1array ;
 
-: tuple-constructor? ( word -- ? )
-    { <tuple-boa> <complex> } memq? ;
-
 : fold-<tuple-boa> ( values class -- info )
     [ [ literal>> ] map ] dip prefix >tuple
     <literal-info> ;
 
+: read-only-slots ( values class -- slots )
+    all-slots
+    [ read-only>> [ value-info ] [ drop f ] if ] 2map
+    f prefix ;
+
 : (propagate-tuple-constructor) ( values class -- info )
-    [ [ value-info ] map ] dip [ read-only-slots ] keep
+    [ read-only-slots ] keep
     over rest-slice [ dup [ literal?>> ] when ] all? [
         [ rest-slice ] dip fold-<tuple-boa>
     ] [
         <tuple-info>
     ] if ;
 
-: propagate-<tuple-boa> ( #call -- info )
+: propagate-<tuple-boa> ( #call -- infos )
     in-d>> unclip-last
-    value-info literal>> first (propagate-tuple-constructor) ;
-
-: propagate-<complex> ( #call -- info )
-    in-d>> [ value-info ] map complex <tuple-info> ;
-
-: propagate-tuple-constructor ( #call word -- infos )
-    {
-        { \ <tuple-boa> [ propagate-<tuple-boa> ] }
-        { \ <complex> [ propagate-<complex> ] }
-    } case 1array ;
+    value-info literal>> first (propagate-tuple-constructor) 1array ;
 
 : read-only-slot? ( n class -- ? )
     all-slots [ offset>> = ] with find nip
index 8654a6f983e778b9d28ae006025d900c3fd88126..70670648b1666816d80b597bde1f3de9473b5bb4 100644 (file)
@@ -32,7 +32,6 @@ TUPLE: empty-tuple ;
     [ dup [ drop f ] [ "A" throw ] if ]
     [ [ ] [ ] curry curry dup 2 slot swap 3 slot dup 2 slot swap 3 slot drop ]
     [ [ ] [ ] curry curry call ]
-    [ <complex> <complex> dup 1 slot drop 2 slot drop ]
     [ 1 cons boa over [ "A" throw ] when car>> ]
     [ [ <=> ] sort ]
     [ [ <=> ] with search ]
index 1e00efa83596ead29d6b421a7aa86a313e265548..107ea59902d48e64009108a8d4fa9d1681c75b9a 100755 (executable)
@@ -36,9 +36,6 @@ M: #push unbox-tuples* ( #push -- nodes )
 : unbox-<tuple-boa> ( #call -- nodes )
     dup unbox-output? [ in-d>> 1 tail* #drop ] when ;
 
-: unbox-<complex> ( #call -- nodes )
-    dup unbox-output? [ drop { } ] when ;
-
 : (flatten-values) ( values accum -- )
     dup '[
         dup unboxed-allocation
@@ -70,7 +67,6 @@ M: #push unbox-tuples* ( #push -- nodes )
 M: #call unbox-tuples*
     dup word>> {
         { \ <tuple-boa> [ unbox-<tuple-boa> ] }
-        { \ <complex> [ unbox-<complex> ] }
         { \ slot [ unbox-slot-access ] }
         [ drop ]
     } case ;
index 46f6639ab8f4b6b57693659944b1ec591dc9c092..1956cd9c20d4d6761d978fa8afa4ff765652a3f0 100644 (file)
@@ -151,8 +151,8 @@ SYMBOL: event-stream-callbacks
     \ event-stream-counter counter ;
 
 [
-    event-stream-callbacks global
-    [ [ drop expired? not ] assoc-filter H{ } assoc-like ] change-at
+    event-stream-callbacks
+    [ [ drop expired? not ] assoc-filter H{ } assoc-like ] change-global
 ] "core-foundation" add-init-hook
 
 : add-event-source-callback ( quot -- id )
index 1431d471c161b4496c8ea064aac2966de4953f22..7278fd20929f7e0a6d8fcca4878e7972e7288bfb 100644 (file)
@@ -2,15 +2,13 @@
 ! See http://factorcode.org/license.txt for BSD license.\r
 USING: bootstrap.image.private kernel kernel.private namespaces\r
 system cpu.ppc.assembler compiler.codegen.fixup compiler.units\r
-compiler.constants math math.private layouts words words.private\r
+compiler.constants math math.private layouts words\r
 vocabs slots.private locals.backend ;\r
 IN: bootstrap.ppc\r
 \r
 4 \ cell set\r
 big-endian on\r
 \r
-4 jit-code-format set\r
-\r
 CONSTANT: ds-reg 29\r
 CONSTANT: rs-reg 30\r
 \r
@@ -23,7 +21,7 @@ CONSTANT: rs-reg 30
 : xt-save ( -- n ) stack-frame 2 bootstrap-cells - ;\r
 \r
 [\r
-    0 6 LOAD32\r
+    0 6 LOAD32 rc-absolute-ppc-2/2 rt-immediate jit-rel\r
     11 6 profile-count-offset LWZ\r
     11 11 1 tag-fixnum ADDI\r
     11 6 profile-count-offset STW\r
@@ -31,65 +29,50 @@ CONSTANT: rs-reg 30
     11 11 compiled-header-size ADDI\r
     11 MTCTR\r
     BCTR\r
-] rc-absolute-ppc-2/2 rt-immediate 1 jit-profiling jit-define\r
+] jit-profiling jit-define\r
 \r
 [\r
-    0 6 LOAD32\r
+    0 6 LOAD32 rc-absolute-ppc-2/2 rt-this jit-rel\r
     0 MFLR\r
     1 1 stack-frame SUBI\r
     6 1 xt-save STW\r
     stack-frame 6 LI\r
     6 1 next-save STW\r
     0 1 lr-save stack-frame + STW\r
-] rc-absolute-ppc-2/2 rt-this 1 jit-prolog jit-define\r
+] jit-prolog jit-define\r
 \r
 [\r
-    0 6 LOAD32\r
+    0 6 LOAD32 rc-absolute-ppc-2/2 rt-immediate jit-rel\r
     6 ds-reg 4 STWU\r
-] rc-absolute-ppc-2/2 rt-immediate 1 jit-push-immediate jit-define\r
+] jit-push-immediate jit-define\r
 \r
 [\r
-    0 6 LOAD32\r
+    0 6 LOAD32 rc-absolute-ppc-2/2 rt-stack-chain jit-rel\r
     7 6 0 LWZ\r
     1 7 0 STW\r
-] rc-absolute-ppc-2/2 rt-stack-chain 1 jit-save-stack jit-define\r
+] jit-save-stack jit-define\r
 \r
 [\r
-    0 6 LOAD32\r
+    0 6 LOAD32 rc-absolute-ppc-2/2 rt-primitive jit-rel\r
     6 MTCTR\r
     BCTR\r
-] rc-absolute-ppc-2/2 rt-primitive 1 jit-primitive jit-define\r
+] jit-primitive jit-define\r
 \r
-[ 0 BL ] rc-relative-ppc-3 rt-xt 0 jit-word-call jit-define\r
+[ 0 BL rc-relative-ppc-3 rt-xt-direct jit-rel ] jit-word-call jit-define\r
 \r
-[ 0 B ] rc-relative-ppc-3 rt-xt 0 jit-word-jump jit-define\r
+[ 0 B rc-relative-ppc-3 rt-xt jit-rel ] jit-word-jump jit-define\r
 \r
 [\r
     3 ds-reg 0 LWZ\r
     ds-reg dup 4 SUBI\r
     0 3 \ f tag-number CMPI\r
     2 BEQ\r
-    0 B\r
-] rc-relative-ppc-3 rt-xt 4 jit-if-1 jit-define\r
-\r
-[\r
-    0 B\r
-] rc-relative-ppc-3 rt-xt 0 jit-if-2 jit-define\r
-\r
-: jit-jump-quot ( -- )\r
-    4 3 quot-xt-offset LWZ\r
-    4 MTCTR\r
-    BCTR ;\r
+    0 B rc-relative-ppc-3 rt-xt jit-rel\r
+] jit-if-1 jit-define\r
 \r
 [\r
-    0 3 LOAD32\r
-    6 ds-reg 0 LWZ\r
-    6 6 1 SRAWI\r
-    3 3 6 ADD\r
-    3 3 array-start-offset LWZ\r
-    ds-reg dup 4 SUBI\r
-    jit-jump-quot\r
-] rc-absolute-ppc-2/2 rt-immediate 1 jit-dispatch jit-define\r
+    0 B rc-relative-ppc-3 rt-xt jit-rel\r
+] jit-if-2 jit-define\r
 \r
 : jit->r ( -- )\r
     4 ds-reg 0 LWZ\r
@@ -139,29 +122,29 @@ CONSTANT: rs-reg 30
 \r
 [\r
     jit->r\r
-    0 BL\r
+    0 BL rc-relative-ppc-3 rt-xt jit-rel\r
     jit-r>\r
-] rc-relative-ppc-3 rt-xt 3 jit-dip jit-define\r
+] jit-dip jit-define\r
 \r
 [\r
     jit-2>r\r
-    0 BL\r
+    0 BL rc-relative-ppc-3 rt-xt jit-rel\r
     jit-2r>\r
-] rc-relative-ppc-3 rt-xt 6 jit-2dip jit-define\r
+] jit-2dip jit-define\r
 \r
 [\r
     jit-3>r\r
-    0 BL\r
+    0 BL rc-relative-ppc-3 rt-xt jit-rel\r
     jit-3r>\r
-] rc-relative-ppc-3 rt-xt 8 jit-3dip jit-define\r
+] jit-3dip jit-define\r
 \r
 [\r
     0 1 lr-save stack-frame + LWZ\r
     1 1 stack-frame ADDI\r
     0 MTLR\r
-] f f f jit-epilog jit-define\r
+] jit-epilog jit-define\r
 \r
-[ BLR ] f f f jit-return jit-define\r
+[ BLR ] jit-return jit-define\r
 \r
 ! Sub-primitives\r
 \r
@@ -169,8 +152,10 @@ CONSTANT: rs-reg 30
 [\r
     3 ds-reg 0 LWZ\r
     ds-reg dup 4 SUBI\r
-    jit-jump-quot\r
-] f f f \ (call) define-sub-primitive\r
+    4 3 quot-xt-offset LWZ\r
+    4 MTCTR\r
+    BCTR\r
+] \ (call) define-sub-primitive\r
 \r
 [\r
     3 ds-reg 0 LWZ\r
@@ -178,7 +163,7 @@ CONSTANT: rs-reg 30
     4 3 word-xt-offset LWZ\r
     4 MTCTR\r
     BCTR\r
-] f f f \ (execute) define-sub-primitive\r
+] \ (execute) define-sub-primitive\r
 \r
 ! Objects\r
 [\r
@@ -186,7 +171,7 @@ CONSTANT: rs-reg 30
     3 3 tag-mask get ANDI\r
     3 3 tag-bits get SLWI\r
     3 ds-reg 0 STW\r
-] f f f \ tag define-sub-primitive\r
+] \ tag define-sub-primitive\r
 \r
 [\r
     3 ds-reg 0 LWZ\r
@@ -195,25 +180,25 @@ CONSTANT: rs-reg 30
     4 4 0 0 31 tag-bits get - RLWINM\r
     4 3 3 LWZX\r
     3 ds-reg 0 STW\r
-] f f f \ slot define-sub-primitive\r
+] \ slot define-sub-primitive\r
 \r
 ! Shufflers\r
 [\r
     ds-reg dup 4 SUBI\r
-] f f f \ drop define-sub-primitive\r
+] \ drop define-sub-primitive\r
 \r
 [\r
     ds-reg dup 8 SUBI\r
-] f f f \ 2drop define-sub-primitive\r
+] \ 2drop define-sub-primitive\r
 \r
 [\r
     ds-reg dup 12 SUBI\r
-] f f f \ 3drop define-sub-primitive\r
+] \ 3drop define-sub-primitive\r
 \r
 [\r
     3 ds-reg 0 LWZ\r
     3 ds-reg 4 STWU\r
-] f f f \ dup define-sub-primitive\r
+] \ dup define-sub-primitive\r
 \r
 [\r
     3 ds-reg 0 LWZ\r
@@ -221,7 +206,7 @@ CONSTANT: rs-reg 30
     ds-reg dup 8 ADDI\r
     3 ds-reg 0 STW\r
     4 ds-reg -4 STW\r
-] f f f \ 2dup define-sub-primitive\r
+] \ 2dup define-sub-primitive\r
 \r
 [\r
     3 ds-reg 0 LWZ\r
@@ -231,36 +216,36 @@ CONSTANT: rs-reg 30
     3 ds-reg 0 STW\r
     4 ds-reg -4 STW\r
     5 ds-reg -8 STW\r
-] f f f \ 3dup define-sub-primitive\r
+] \ 3dup define-sub-primitive\r
 \r
 [\r
     3 ds-reg 0 LWZ\r
     ds-reg dup 4 SUBI\r
     3 ds-reg 0 STW\r
-] f f f \ nip define-sub-primitive\r
+] \ nip define-sub-primitive\r
 \r
 [\r
     3 ds-reg 0 LWZ\r
     ds-reg dup 8 SUBI\r
     3 ds-reg 0 STW\r
-] f f f \ 2nip define-sub-primitive\r
+] \ 2nip define-sub-primitive\r
 \r
 [\r
     3 ds-reg -4 LWZ\r
     3 ds-reg 4 STWU\r
-] f f f \ over define-sub-primitive\r
+] \ over define-sub-primitive\r
 \r
 [\r
     3 ds-reg -8 LWZ\r
     3 ds-reg 4 STWU\r
-] f f f \ pick define-sub-primitive\r
+] \ pick define-sub-primitive\r
 \r
 [\r
     3 ds-reg 0 LWZ\r
     4 ds-reg -4 LWZ\r
     4 ds-reg 0 STW\r
     3 ds-reg 4 STWU\r
-] f f f \ dupd define-sub-primitive\r
+] \ dupd define-sub-primitive\r
 \r
 [\r
     3 ds-reg 0 LWZ\r
@@ -268,21 +253,21 @@ CONSTANT: rs-reg 30
     3 ds-reg 4 STWU\r
     4 ds-reg -4 STW\r
     3 ds-reg -8 STW\r
-] f f f \ tuck define-sub-primitive\r
+] \ tuck define-sub-primitive\r
 \r
 [\r
     3 ds-reg 0 LWZ\r
     4 ds-reg -4 LWZ\r
     3 ds-reg -4 STW\r
     4 ds-reg 0 STW\r
-] f f f \ swap define-sub-primitive\r
+] \ swap define-sub-primitive\r
 \r
 [\r
     3 ds-reg -4 LWZ\r
     4 ds-reg -8 LWZ\r
     3 ds-reg -8 STW\r
     4 ds-reg -4 STW\r
-] f f f \ swapd define-sub-primitive\r
+] \ swapd define-sub-primitive\r
 \r
 [\r
     3 ds-reg 0 LWZ\r
@@ -291,7 +276,7 @@ CONSTANT: rs-reg 30
     4 ds-reg -8 STW\r
     3 ds-reg -4 STW\r
     5 ds-reg 0 STW\r
-] f f f \ rot define-sub-primitive\r
+] \ rot define-sub-primitive\r
 \r
 [\r
     3 ds-reg 0 LWZ\r
@@ -300,13 +285,13 @@ CONSTANT: rs-reg 30
     3 ds-reg -8 STW\r
     5 ds-reg -4 STW\r
     4 ds-reg 0 STW\r
-] f f f \ -rot define-sub-primitive\r
+] \ -rot define-sub-primitive\r
 \r
-[ jit->r ] f f f \ load-local define-sub-primitive\r
+[ jit->r ] \ load-local define-sub-primitive\r
 \r
 ! Comparisons\r
 : jit-compare ( insn -- )\r
-    0 3 LOAD32\r
+    0 3 LOAD32 rc-absolute-ppc-2/2 rt-immediate jit-rel\r
     4 ds-reg 0 LWZ\r
     5 ds-reg -4 LWZU\r
     5 0 4 CMP\r
@@ -315,8 +300,7 @@ CONSTANT: rs-reg 30
     3 ds-reg 0 STW ;\r
 \r
 : define-jit-compare ( insn word -- )\r
-    [ [ jit-compare ] curry rc-absolute-ppc-2/2 rt-immediate 1 ] dip\r
-    define-sub-primitive ;\r
+    [ [ jit-compare ] curry ] dip define-sub-primitive ;\r
 \r
 \ BEQ \ eq? define-jit-compare\r
 \ BGE \ fixnum>= define-jit-compare\r
@@ -336,7 +320,7 @@ CONSTANT: rs-reg 30
     2 BNE\r
     1 tag-fixnum 4 LI\r
     4 ds-reg 0 STW\r
-] f f f \ both-fixnums? define-sub-primitive\r
+] \ both-fixnums? define-sub-primitive\r
 \r
 : jit-math ( insn -- )\r
     3 ds-reg 0 LWZ\r
@@ -344,9 +328,9 @@ CONSTANT: rs-reg 30
     [ 5 3 4 ] dip execute( dst src1 src2 -- )\r
     5 ds-reg 0 STW ;\r
 \r
-[ \ ADD jit-math ] f f f \ fixnum+fast define-sub-primitive\r
+[ \ ADD jit-math ] \ fixnum+fast define-sub-primitive\r
 \r
-[ \ SUBF jit-math ] f f f \ fixnum-fast define-sub-primitive\r
+[ \ SUBF jit-math ] \ fixnum-fast define-sub-primitive\r
 \r
 [\r
     3 ds-reg 0 LWZ\r
@@ -354,20 +338,20 @@ CONSTANT: rs-reg 30
     4 4 tag-bits get SRAWI\r
     5 3 4 MULLW\r
     5 ds-reg 0 STW\r
-] f f f \ fixnum*fast define-sub-primitive\r
+] \ fixnum*fast define-sub-primitive\r
 \r
-[ \ AND jit-math ] f f f \ fixnum-bitand define-sub-primitive\r
+[ \ AND jit-math ] \ fixnum-bitand define-sub-primitive\r
 \r
-[ \ OR jit-math ] f f f \ fixnum-bitor define-sub-primitive\r
+[ \ OR jit-math ] \ fixnum-bitor define-sub-primitive\r
 \r
-[ \ XOR jit-math ] f f f \ fixnum-bitxor define-sub-primitive\r
+[ \ XOR jit-math ] \ fixnum-bitxor define-sub-primitive\r
 \r
 [\r
     3 ds-reg 0 LWZ\r
     3 3 NOT\r
     3 3 tag-mask get XORI\r
     3 ds-reg 0 STW\r
-] f f f \ fixnum-bitnot define-sub-primitive\r
+] \ fixnum-bitnot define-sub-primitive\r
 \r
 [\r
     3 ds-reg 0 LWZ\r
@@ -382,7 +366,7 @@ CONSTANT: rs-reg 30
     2 BGT\r
     5 7 MR\r
     5 ds-reg 0 STW\r
-] f f f \ fixnum-shift-fast define-sub-primitive\r
+] \ fixnum-shift-fast define-sub-primitive\r
 \r
 [\r
     3 ds-reg 0 LWZ\r
@@ -392,7 +376,7 @@ CONSTANT: rs-reg 30
     6 5 3 MULLW\r
     7 6 4 SUBF\r
     7 ds-reg 0 STW\r
-] f f f \ fixnum-mod define-sub-primitive\r
+] \ fixnum-mod define-sub-primitive\r
 \r
 [\r
     3 ds-reg 0 LWZ\r
@@ -401,7 +385,7 @@ CONSTANT: rs-reg 30
     5 4 3 DIVW\r
     5 5 tag-bits get SLWI\r
     5 ds-reg 0 STW\r
-] f f f \ fixnum/i-fast define-sub-primitive\r
+] \ fixnum/i-fast define-sub-primitive\r
 \r
 [\r
     3 ds-reg 0 LWZ\r
@@ -412,20 +396,20 @@ CONSTANT: rs-reg 30
     5 5 tag-bits get SLWI\r
     5 ds-reg -4 STW\r
     7 ds-reg 0 STW\r
-] f f f \ fixnum/mod-fast define-sub-primitive\r
+] \ fixnum/mod-fast define-sub-primitive\r
 \r
 [\r
     3 ds-reg 0 LWZ\r
     3 3 1 SRAWI\r
     rs-reg 3 3 LWZX\r
     3 ds-reg 0 STW\r
-] f f f \ get-local define-sub-primitive\r
+] \ get-local define-sub-primitive\r
 \r
 [\r
     3 ds-reg 0 LWZ\r
     ds-reg ds-reg 4 SUBI\r
     3 3 1 SRAWI\r
     rs-reg 3 rs-reg SUBF\r
-] f f f \ drop-locals define-sub-primitive\r
+] \ drop-locals define-sub-primitive\r
 \r
 [ "bootstrap.ppc" forget-vocab ] with-compilation-unit\r
index b280afc01e93bfcf152a0133fdaaeda71398fbf0..10cd9c8657e00444f420996efb57401570f18633 100755 (executable)
@@ -309,7 +309,7 @@ FUNCTION: bool check_sse2 ( ) ;
     check_sse2 ;
 
 "-no-sse2" (command-line) member? [
-    optimizing-compiler compiler-impl [ { check_sse2 } compile ] with-variable
+    [ { check_sse2 } compile ] with-optimizer
 
     "Checking if your CPU supports SSE2..." print flush
     sse2? [
index 5d88f699b8ab2270829c853f41b022a614cdb8ce..be21344815ffb97fdeb862219dcf09c614d9e5b3 100644 (file)
@@ -22,13 +22,15 @@ IN: bootstrap.x86
 : rex-length ( -- n ) 0 ;
 
 [
-    temp0 0 [] MOV                              ! load stack_chain
-    temp0 [] stack-reg MOV                      ! save stack pointer
-] rc-absolute-cell rt-stack-chain 2 jit-save-stack jit-define
+    ! load stack_chain
+    temp0 0 [] MOV rc-absolute-cell rt-stack-chain jit-rel
+    ! save stack pointer
+    temp0 [] stack-reg MOV
+] jit-save-stack jit-define
 
 [
-    (JMP) drop
-] rc-relative rt-primitive 1 jit-primitive jit-define
+    (JMP) drop rc-relative rt-primitive jit-rel
+] jit-primitive jit-define
 
 << "vocab:cpu/x86/bootstrap.factor" parse-file parsed >>
 call
index ddf5791009bceab67485523b644f7dfe8694af1d..8d1ed086e70f3bf6b5d913206ab805f88a40e717 100644 (file)
@@ -20,15 +20,19 @@ IN: bootstrap.x86
 : rex-length ( -- n ) 1 ;
 
 [
-    temp0 0 MOV                                 ! load stack_chain
+    ! load stack_chain
+    temp0 0 MOV rc-absolute-cell rt-stack-chain jit-rel
     temp0 temp0 [] MOV
-    temp0 [] stack-reg MOV                      ! save stack pointer
-] rc-absolute-cell rt-stack-chain 1 rex-length + jit-save-stack jit-define
+    ! save stack pointer
+    temp0 [] stack-reg MOV
+] jit-save-stack jit-define
 
 [
-    temp1 0 MOV                                 ! load XT
-    temp1 JMP                                   ! go
-] rc-absolute-cell rt-primitive 1 rex-length + jit-primitive jit-define
+    ! load XT
+    temp1 0 MOV rc-absolute-cell rt-primitive jit-rel
+    ! go
+    temp1 JMP
+] jit-primitive jit-define
 
 << "vocab:cpu/x86/bootstrap.factor" parse-file parsed >>
 call
index 49b0961819437ed60211cdc6d71944d36e668010..203edf956e31297f50922a9b9e2c93d6320ae9e0 100644 (file)
@@ -62,3 +62,5 @@ IN: cpu.x86.assembler.tests
 [ { HEX: 48 HEX: d3 HEX: e1 } ] [ [ RCX CL SHL ] { } make ] unit-test
 [ { HEX: 48 HEX: d3 HEX: e8 } ] [ [ RAX CL SHR ] { } make ] unit-test
 [ { HEX: 48 HEX: d3 HEX: e9 } ] [ [ RCX CL SHR ] { } make ] unit-test
+
+[ { HEX: f7 HEX: c1 HEX: d2 HEX: 04 HEX: 00 HEX: 00 } ] [ [ ECX 1234 TEST ] { } make ] unit-test
index 3a98d474160caefe4b475db8c477953bb2c41524..5560d17a1e45459159b04d38ac8ce85dfe7fe0f1 100644 (file)
@@ -316,15 +316,16 @@ M: operand JMP { BIN: 100 t HEX: ff } 1-operand ;
 GENERIC: CALL ( op -- )
 : (CALL) ( -- rel-class ) HEX: e8 , 0 4, rc-relative ;
 M: f CALL (CALL) 2drop ;
-M: callable CALL (CALL) rel-word ;
+M: callable CALL (CALL) rel-word-direct ;
 M: label CALL (CALL) label-fixup ;
 M: operand CALL { BIN: 010 t HEX: ff } 1-operand ;
 
 GENERIC# JUMPcc 1 ( addr opcode -- )
-: (JUMPcc) ( n -- rel-class ) extended-opcode, 0 4, rc-relative ;
-M: f JUMPcc nip (JUMPcc) drop ;
-M: callable JUMPcc (JUMPcc) rel-word ;
-M: label JUMPcc (JUMPcc) label-fixup ;
+: (JUMPcc) ( addr n -- rel-class ) extended-opcode, 4, rc-relative ;
+M: f JUMPcc [ 0 ] dip (JUMPcc) 2drop ;
+M: integer JUMPcc (JUMPcc) drop ;
+M: callable JUMPcc [ 0 ] dip (JUMPcc) rel-word ;
+M: label JUMPcc [ 0 ] dip (JUMPcc) label-fixup ;
 
 : JO  ( dst -- ) HEX: 80 JUMPcc ;
 : JNO ( dst -- ) HEX: 81 JUMPcc ;
@@ -382,6 +383,10 @@ GENERIC: CMP ( dst src -- )
 M: immediate CMP swap { BIN: 111 t HEX: 80 } immediate-1/4 ;
 M: operand CMP OCT: 070 2-operand ;
 
+GENERIC: TEST ( dst src -- )
+M: immediate TEST swap { BIN: 0 t HEX: f7 } immediate-4 ;
+M: operand TEST OCT: 204 2-operand ;
+
 : XCHG ( dst src -- ) OCT: 207 2-operand ;
 
 : BSR ( dst src -- ) swap { HEX: 0f HEX: bd } (2-operand) ;
index b63d31364b915ca8146bd8b9894a0f04b4632f8e..4fe5e5cd33b2f5fcb1a0381645b3a14f7b27392f 100644 (file)
@@ -1,18 +1,16 @@
-! Copyright (C) 2007, 2008 Slava Pestov.
+! Copyright (C) 2007, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: bootstrap.image.private kernel kernel.private namespaces
 system cpu.x86.assembler layouts compiler.units math
 math.private compiler.constants vocabs slots.private words
-words.private locals.backend ;
+locals.backend make sequences combinators arrays ;
 IN: bootstrap.x86
 
 big-endian off
 
-1 jit-code-format set
-
 [
     ! Load word
-    temp0 0 MOV
+    temp0 0 MOV rc-absolute-cell rt-immediate jit-rel
     ! Bump profiling counter
     temp0 profile-count-offset [+] 1 tag-fixnum ADD
     ! Load word->code
@@ -21,35 +19,35 @@ big-endian off
     temp0 compiled-header-size ADD
     ! Jump to XT
     temp0 JMP
-] rc-absolute-cell rt-immediate 1 rex-length + jit-profiling jit-define
+] jit-profiling jit-define
 
 [
     ! load XT
-    temp0 0 MOV
+    temp0 0 MOV rc-absolute-cell rt-this jit-rel
     ! save stack frame size
     stack-frame-size PUSH
     ! push XT
     temp0 PUSH
     ! alignment
     stack-reg stack-frame-size 3 bootstrap-cells - SUB
-] rc-absolute-cell rt-this 1 rex-length + jit-prolog jit-define
+] jit-prolog jit-define
 
 [
     ! load literal
-    temp0 0 MOV
+    temp0 0 MOV rc-absolute-cell rt-immediate jit-rel
     ! increment datastack pointer
     ds-reg bootstrap-cell ADD
     ! store literal on datastack
     ds-reg [] temp0 MOV
-] rc-absolute-cell rt-immediate 1 rex-length + jit-push-immediate jit-define
+] jit-push-immediate jit-define
 
 [
-    f JMP
-] rc-relative rt-xt 1 jit-word-jump jit-define
+    f JMP rc-relative rt-xt jit-rel
+] jit-word-jump jit-define
 
 [
-    f CALL
-] rc-relative rt-xt 1 jit-word-call jit-define
+    f CALL rc-relative rt-xt-direct jit-rel
+] jit-word-call jit-define
 
 [
     ! load boolean
@@ -59,31 +57,13 @@ big-endian off
     ! compare boolean with f
     temp0 \ f tag-number CMP
     ! jump to true branch if not equal
-    f JNE
-] rc-relative rt-xt 10 rex-length 3 * + jit-if-1 jit-define
+    f JNE rc-relative rt-xt jit-rel
+] jit-if-1 jit-define
 
 [
     ! jump to false branch if equal
-    f JMP
-] rc-relative rt-xt 1 jit-if-2 jit-define
-
-[
-    ! load dispatch table
-    temp1 0 MOV
-    ! load index
-    temp0 ds-reg [] MOV
-    ! turn it into an array offset
-    fixnum>slot@
-    ! pop index
-    ds-reg bootstrap-cell SUB
-    ! compute quotation location
-    temp0 temp1 ADD
-    ! load quotation
-    arg temp0 array-start-offset [+] MOV
-    ! execute branch. the quot must be in arg, since it might
-    ! not be compiled yet
-    arg quot-xt-offset [+] JMP
-] rc-absolute-cell rt-immediate 1 rex-length + jit-dispatch jit-define
+    f JMP rc-relative rt-xt jit-rel
+] jit-if-2 jit-define
 
 : jit->r ( -- )
     rs-reg bootstrap-cell ADD
@@ -135,30 +115,133 @@ big-endian off
 
 [
     jit->r
-    f CALL
+    f CALL rc-relative rt-xt jit-rel
     jit-r>
-] rc-relative rt-xt 11 rex-length 4 * + jit-dip jit-define
+] jit-dip jit-define
 
 [
     jit-2>r
-    f CALL
+    f CALL rc-relative rt-xt jit-rel
     jit-2r>
-] rc-relative rt-xt 17 rex-length 6 * + jit-2dip jit-define
+] jit-2dip jit-define
 
 [
     jit-3>r
-    f CALL
+    f CALL rc-relative rt-xt jit-rel
     jit-3r>
-] rc-relative rt-xt 23 rex-length 8 * + jit-3dip jit-define
+] jit-3dip jit-define
+
+: prepare-(execute) ( -- operand )
+    ! load from stack
+    temp0 ds-reg [] MOV
+    ! pop stack
+    ds-reg bootstrap-cell SUB
+    ! execute word
+    temp0 word-xt-offset [+] ;
+
+[ prepare-(execute) JMP ] jit-execute-jump jit-define
+
+[ prepare-(execute) CALL ] jit-execute-call jit-define
 
 [
     ! unwind stack frame
     stack-reg stack-frame-size bootstrap-cell - ADD
-] f f f jit-epilog jit-define
+] jit-epilog jit-define
+
+[ 0 RET ] jit-return jit-define
 
-[ 0 RET ] f f f jit-return jit-define
+! ! ! Polymorphic inline caches
 
-! Sub-primitives
+! temp0 contains the object being dispatched on
+! temp1 contains its class
+
+! Load a value from a stack position
+[
+    temp1 ds-reg HEX: ffffffff [+] MOV rc-absolute rt-untagged jit-rel
+] pic-load jit-define
+
+! Tag
+: load-tag ( -- )
+    temp1 tag-mask get AND
+    temp1 tag-bits get SHL ;
+
+[ load-tag ] pic-tag jit-define
+
+! The 'make' trick lets us compute the jump distance for the
+! conditional branches there
+
+! Hi-tag
+[
+    temp0 temp1 MOV
+    load-tag
+    temp1 object tag-number tag-fixnum CMP
+    [ temp1 temp0 object tag-number neg [+] MOV ] { } make
+    [ length JNE ] [ % ] bi
+] pic-hi-tag jit-define
+
+! Tuple
+[
+    temp0 temp1 MOV
+    load-tag
+    temp1 tuple tag-number tag-fixnum CMP
+    [ temp1 temp0 tuple tag-number neg bootstrap-cell + [+] MOV ] { } make
+    [ length JNE ] [ % ] bi
+] pic-tuple jit-define
+
+! Hi-tag and tuple
+[
+    temp0 temp1 MOV
+    load-tag
+    ! If bits 2 and 3 are set, the tag is either 6 (object) or 7 (tuple)
+    temp1 BIN: 110 tag-fixnum CMP
+    [
+        ! Untag temp0
+        temp0 tag-mask get bitnot AND
+        ! Set temp1 to 0 for objects, and 8 for tuples
+        temp1 1 tag-fixnum AND
+        bootstrap-cell 4 = [ temp1 1 SHR ] when
+        ! Load header cell or tuple layout cell
+        temp1 temp0 temp1 [+] MOV
+    ] [ ] make [ length JL ] [ % ] bi
+] pic-hi-tag-tuple jit-define
+
+[
+    temp1 HEX: ffffffff CMP rc-absolute rt-immediate jit-rel
+] pic-check-tag jit-define
+
+[
+    temp2 HEX: ffffffff MOV rc-absolute-cell rt-immediate jit-rel
+    temp1 temp2 CMP
+] pic-check jit-define
+
+[ f JE rc-relative rt-xt jit-rel ] pic-hit jit-define
+
+! ! ! Megamorphic caches
+
+[
+    ! cache = ...
+    temp0 0 MOV rc-absolute-cell rt-immediate jit-rel
+    ! key = class
+    temp2 temp1 MOV
+    bootstrap-cell 8 = [ temp2 1 SHL ] when
+    ! key &= cache.length - 1
+    temp2 mega-cache-size get 1- bootstrap-cell * AND
+    ! cache += array-start-offset
+    temp0 array-start-offset ADD
+    ! cache += key
+    temp0 temp2 ADD
+    ! if(get(cache) == class)
+    temp0 [] temp1 CMP
+    ! ... goto get(cache + bootstrap-cell)
+    [
+        temp0 temp0 bootstrap-cell [+] MOV
+        temp0 word-xt-offset [+] JMP
+    ] [ ] make
+    [ length JNE ] [ % ] bi
+    ! fall-through on miss
+] mega-lookup jit-define
+
+! ! ! Sub-primitives
 
 ! Quotations and words
 [
@@ -168,16 +251,7 @@ big-endian off
     ds-reg bootstrap-cell SUB
     ! call quotation
     arg quot-xt-offset [+] JMP
-] f f f \ (call) define-sub-primitive
-
-[
-    ! load from stack
-    temp0 ds-reg [] MOV
-    ! pop stack
-    ds-reg bootstrap-cell SUB
-    ! execute word
-    temp0 word-xt-offset [+] JMP
-] f f f \ (execute) define-sub-primitive
+] \ (call) define-sub-primitive
 
 ! Objects
 [
@@ -189,7 +263,7 @@ big-endian off
     temp0 tag-bits get SHL
     ! push to stack
     ds-reg [] temp0 MOV
-] f f f \ tag define-sub-primitive
+] \ tag define-sub-primitive
 
 [
     ! load slot number
@@ -207,26 +281,26 @@ big-endian off
     temp0 temp1 temp0 [+] MOV
     ! push to stack
     ds-reg [] temp0 MOV
-] f f f \ slot define-sub-primitive
+] \ slot define-sub-primitive
 
 ! Shufflers
 [
     ds-reg bootstrap-cell SUB
-] f f f \ drop define-sub-primitive
+] \ drop define-sub-primitive
 
 [
     ds-reg 2 bootstrap-cells SUB
-] f f f \ 2drop define-sub-primitive
+] \ 2drop define-sub-primitive
 
 [
     ds-reg 3 bootstrap-cells SUB
-] f f f \ 3drop define-sub-primitive
+] \ 3drop define-sub-primitive
 
 [
     temp0 ds-reg [] MOV
     ds-reg bootstrap-cell ADD
     ds-reg [] temp0 MOV
-] f f f \ dup define-sub-primitive
+] \ dup define-sub-primitive
 
 [
     temp0 ds-reg [] MOV
@@ -234,7 +308,7 @@ big-endian off
     ds-reg 2 bootstrap-cells ADD
     ds-reg [] temp0 MOV
     ds-reg bootstrap-cell neg [+] temp1 MOV
-] f f f \ 2dup define-sub-primitive
+] \ 2dup define-sub-primitive
 
 [
     temp0 ds-reg [] MOV
@@ -244,31 +318,31 @@ big-endian off
     ds-reg [] temp0 MOV
     ds-reg -1 bootstrap-cells [+] temp1 MOV
     ds-reg -2 bootstrap-cells [+] temp3 MOV
-] f f f \ 3dup define-sub-primitive
+] \ 3dup define-sub-primitive
 
 [
     temp0 ds-reg [] MOV
     ds-reg bootstrap-cell SUB
     ds-reg [] temp0 MOV
-] f f f \ nip define-sub-primitive
+] \ nip define-sub-primitive
 
 [
     temp0 ds-reg [] MOV
     ds-reg 2 bootstrap-cells SUB
     ds-reg [] temp0 MOV
-] f f f \ 2nip define-sub-primitive
+] \ 2nip define-sub-primitive
 
 [
     temp0 ds-reg -1 bootstrap-cells [+] MOV
     ds-reg bootstrap-cell ADD
     ds-reg [] temp0 MOV
-] f f f \ over define-sub-primitive
+] \ over define-sub-primitive
 
 [
     temp0 ds-reg -2 bootstrap-cells [+] MOV
     ds-reg bootstrap-cell ADD
     ds-reg [] temp0 MOV
-] f f f \ pick define-sub-primitive
+] \ pick define-sub-primitive
 
 [
     temp0 ds-reg [] MOV
@@ -276,7 +350,7 @@ big-endian off
     ds-reg [] temp1 MOV
     ds-reg bootstrap-cell ADD
     ds-reg [] temp0 MOV
-] f f f \ dupd define-sub-primitive
+] \ dupd define-sub-primitive
 
 [
     temp0 ds-reg [] MOV
@@ -285,21 +359,21 @@ big-endian off
     ds-reg [] temp0 MOV
     ds-reg -1 bootstrap-cells [+] temp1 MOV
     ds-reg -2 bootstrap-cells [+] temp0 MOV
-] f f f \ tuck define-sub-primitive
+] \ tuck define-sub-primitive
 
 [
     temp0 ds-reg [] MOV
     temp1 ds-reg bootstrap-cell neg [+] MOV
     ds-reg bootstrap-cell neg [+] temp0 MOV
     ds-reg [] temp1 MOV
-] f f f \ swap define-sub-primitive
+] \ swap define-sub-primitive
 
 [
     temp0 ds-reg -1 bootstrap-cells [+] MOV
     temp1 ds-reg -2 bootstrap-cells [+] MOV
     ds-reg -2 bootstrap-cells [+] temp0 MOV
     ds-reg -1 bootstrap-cells [+] temp1 MOV
-] f f f \ swapd define-sub-primitive
+] \ swapd define-sub-primitive
 
 [
     temp0 ds-reg [] MOV
@@ -308,7 +382,7 @@ big-endian off
     ds-reg -2 bootstrap-cells [+] temp1 MOV
     ds-reg -1 bootstrap-cells [+] temp0 MOV
     ds-reg [] temp3 MOV
-] f f f \ rot define-sub-primitive
+] \ rot define-sub-primitive
 
 [
     temp0 ds-reg [] MOV
@@ -317,14 +391,14 @@ big-endian off
     ds-reg -2 bootstrap-cells [+] temp0 MOV
     ds-reg -1 bootstrap-cells [+] temp3 MOV
     ds-reg [] temp1 MOV
-] f f f \ -rot define-sub-primitive
+] \ -rot define-sub-primitive
 
-[ jit->r ] f f f \ load-local define-sub-primitive
+[ jit->r ] \ load-local define-sub-primitive
 
 ! Comparisons
 : jit-compare ( insn -- )
     ! load t
-    temp3 0 MOV
+    temp3 0 MOV rc-absolute-cell rt-immediate jit-rel
     ! load f
     temp1 \ f tag-number MOV
     ! load first value
@@ -339,8 +413,7 @@ big-endian off
     ds-reg [] temp1 MOV ;
 
 : define-jit-compare ( insn word -- )
-    [ [ jit-compare ] curry rc-absolute-cell rt-immediate 1 rex-length + ] dip
-    define-sub-primitive ;
+    [ [ jit-compare ] curry ] dip define-sub-primitive ;
 
 \ CMOVE \ eq? define-jit-compare
 \ CMOVGE \ fixnum>= define-jit-compare
@@ -357,9 +430,9 @@ big-endian off
     ! compute result
     [ ds-reg [] temp0 ] dip execute( dst src -- ) ;
 
-[ \ ADD jit-math ] f f f \ fixnum+fast define-sub-primitive
+[ \ ADD jit-math ] \ fixnum+fast define-sub-primitive
 
-[ \ SUB jit-math ] f f f \ fixnum-fast define-sub-primitive
+[ \ SUB jit-math ] \ fixnum-fast define-sub-primitive
 
 [
     ! load second input
@@ -374,20 +447,20 @@ big-endian off
     temp0 temp1 IMUL2
     ! push result
     ds-reg [] temp1 MOV
-] f f f \ fixnum*fast define-sub-primitive
+] \ fixnum*fast define-sub-primitive
 
-[ \ AND jit-math ] f f f \ fixnum-bitand define-sub-primitive
+[ \ AND jit-math ] \ fixnum-bitand define-sub-primitive
 
-[ \ OR jit-math ] f f f \ fixnum-bitor define-sub-primitive
+[ \ OR jit-math ] \ fixnum-bitor define-sub-primitive
 
-[ \ XOR jit-math ] f f f \ fixnum-bitxor define-sub-primitive
+[ \ XOR jit-math ] \ fixnum-bitxor define-sub-primitive
 
 [
     ! complement
     ds-reg [] NOT
     ! clear tag bits
     ds-reg [] tag-mask get XOR
-] f f f \ fixnum-bitnot define-sub-primitive
+] \ fixnum-bitnot define-sub-primitive
 
 [
     ! load shift count
@@ -411,7 +484,7 @@ big-endian off
     temp1 temp3 CMOVGE
     ! push to stack
     ds-reg [] temp1 MOV
-] f f f \ fixnum-shift-fast define-sub-primitive
+] \ fixnum-shift-fast define-sub-primitive
 
 : jit-fixnum-/mod ( -- )
     ! load second parameter
@@ -431,7 +504,7 @@ big-endian off
     ds-reg bootstrap-cell SUB
     ! push to stack
     ds-reg [] mod-arg MOV
-] f f f \ fixnum-mod define-sub-primitive
+] \ fixnum-mod define-sub-primitive
 
 [
     jit-fixnum-/mod
@@ -441,7 +514,7 @@ big-endian off
     div-arg tag-bits get SHL
     ! push to stack
     ds-reg [] div-arg MOV
-] f f f \ fixnum/i-fast define-sub-primitive
+] \ fixnum/i-fast define-sub-primitive
 
 [
     jit-fixnum-/mod
@@ -450,7 +523,7 @@ big-endian off
     ! push to stack
     ds-reg [] mod-arg MOV
     ds-reg bootstrap-cell neg [+] div-arg MOV
-] f f f \ fixnum/mod-fast define-sub-primitive
+] \ fixnum/mod-fast define-sub-primitive
 
 [
     temp0 ds-reg [] MOV
@@ -461,7 +534,7 @@ big-endian off
     temp1 1 tag-fixnum MOV
     temp0 temp1 CMOVE
     ds-reg [] temp0 MOV
-] f f f \ both-fixnums? define-sub-primitive
+] \ both-fixnums? define-sub-primitive
 
 [
     ! load local number
@@ -472,7 +545,7 @@ big-endian off
     temp0 rs-reg temp0 [+] MOV
     ! push to stack
     ds-reg [] temp0 MOV
-] f f f \ get-local define-sub-primitive
+] \ get-local define-sub-primitive
 
 [
     ! load local count
@@ -483,6 +556,6 @@ big-endian off
     fixnum>slot@
     ! decrement retain stack pointer
     rs-reg temp0 SUB
-] f f f \ drop-locals define-sub-primitive
+] \ drop-locals define-sub-primitive
 
 [ "bootstrap.x86" forget-vocab ] with-compilation-unit
index ff5869efab5c9634627dc6df81398e6f000f860b..ff9986432c8a332cca9e1d5daa7b5d844d9e87a2 100644 (file)
@@ -1,6 +1,6 @@
 USING: alien arrays generic generic.math help.markup help.syntax
 kernel math memory strings sbufs vectors io io.files classes
-help generic.standard continuations io.files.private listener
+help generic.single continuations io.files.private listener
 alien.libraries ;
 IN: debugger
 
index d8ebd5bbf97cb8c48add612c81cff87fcfa8934d..2091a261330f1704a5e1034e6fdf491be7ba552a 100644 (file)
@@ -6,7 +6,7 @@ sequences assocs sequences.private strings io.styles
 io.pathnames vectors words system splitting math.parser
 classes.mixin classes.tuple continuations continuations.private
 combinators generic.math classes.builtin classes compiler.units
-generic.standard vocabs init kernel.private io.encodings
+generic.standard generic.single vocabs init kernel.private io.encodings
 accessors math.order destructors source-files parser
 classes.tuple.parser effects.parser lexer
 generic.parser strings.parser vocabs.loader vocabs.parser see
index f6a40d8dc82a0d35068e3c7fd759ac66f4d9c711..9f9aca87029a07b2fa7cb994d3e86c4ee7d04213 100644 (file)
@@ -1,6 +1,6 @@
 USING: delegate kernel arrays tools.test words math definitions
 compiler.units parser generic prettyprint io.streams.string
-accessors eval multiline generic.standard delegate.protocols
+accessors eval multiline generic.single delegate.protocols
 delegate.private assocs see ;
 IN: delegate.tests
 
index f485f1bec10a6ceddfa54962753baa3d85d3abab..0776f8f1583dabea37e170842920d022786020d8 100644 (file)
@@ -79,6 +79,13 @@ M: one-word-elt next-elt
     drop
     [ f next-word ] modify-col ;
 
+SINGLETON: word-start-elt
+
+M: word-start-elt prev-elt
+    drop one-word-elt prev-elt ;
+
+M: word-start-elt next-elt 2drop ;
+
 SINGLETON: word-elt
 
 M: word-elt prev-elt
index 14877110d35a87a82a7116ce183a33d1ffb2207e..9d51ba259eec18fe0053d1b0769575aa3759ee06 100644 (file)
@@ -66,7 +66,7 @@ ERROR: ftp-error got expected ;
 : list ( url -- ftp-response )
     utf8 open-passive-client
     ftp-list
-    lines
+    stream-lines
     <ftp-response> swap >>strings
     read-response 226 ftp-assert
     parse-list ;
index d445bf72ad6dfa17d09516a69af2e43b4d5b2443..db04033275c3c279291e244a5fdbd66b0512ea88 100644 (file)
@@ -1,9 +1,9 @@
-! Copyright (C) 2008 Slava Pestov.
+! Copyright (C) 2008, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: parser words definitions kernel sequences assocs arrays
 kernel.private fry combinators accessors vectors strings sbufs
 byte-arrays byte-vectors io.binary io.streams.string splitting math
-math.parser generic generic.standard generic.standard.engines classes
+math.parser generic generic.single generic.standard classes
 hashtables namespaces ;
 IN: hints
 
@@ -42,13 +42,13 @@ SYMBOL: specialize-method?
 
 t specialize-method? set-global
 
+: method-declaration ( method -- quot )
+    [ "method-generic" word-prop dispatch# object <array> ]
+    [ "method-class" word-prop ]
+    bi prefix [ declare ] curry [ ] like ;
+
 : specialize-method ( quot method -- quot' )
-    [
-        specialize-method? get [
-            [ "method-class" word-prop ] [ "method-generic" word-prop ] bi
-            method-declaration prepend
-        ] [ drop ] if
-    ]
+    [ specialize-method? get [ method-declaration prepend ] [ drop ] if ]
     [ "method-generic" word-prop "specializer" word-prop ] bi
     [ specialize-quot ] when* ;
 
@@ -71,7 +71,7 @@ t specialize-method? set-global
 SYNTAX: HINTS:
     scan-object
     [ changed-definition ]
-    [ parse-definition "specializer" set-word-prop ] bi ;
+    [ parse-definition { } like "specializer" set-word-prop ] bi ;
 
 ! Default specializers
 { first first2 first3 first4 }
index 0d7f7851e2cbf80980cc10ec70b46ff55ca949b6..e00f8e22636df0eb207625fc53f7cfad6669c80d 100644 (file)
@@ -1,6 +1,7 @@
 USING: http help.markup help.syntax io.pathnames io.streams.string
 io.encodings.8-bit io.encodings.binary kernel strings urls
-urls.encoding byte-arrays strings assocs sequences destructors ;
+urls.encoding byte-arrays strings assocs sequences destructors
+http.client.post-data.private ;
 IN: http.client
 
 HELP: download-failed
@@ -71,7 +72,7 @@ ARTICLE: "http.client.get" "GET requests with the HTTP client"
 { $subsection with-http-get }
 { $subsection with-http-request } ;
 
-ARTICLE: "http.client.post-data" "HTTP client submission data"
+ARTICLE: "http.client.post-data" "HTTP client post data"
 "HTTP POST and PUT request words take a post data parameter, which can be one of the following:"
 { $list
     { "a " { $link byte-array } ": the data is sent the server without further encoding" }
@@ -85,7 +86,9 @@ ARTICLE: "http.client.post-data" "HTTP client submission data"
 { $code
   "\"my-large-post-request.txt\" ascii <file-reader>"
   "[ URL\" http://www.my-company.com/web-service\" http-post ] with-disposal"
-} ;
+}
+"An internal word used to convert objects to " { $link post-data } " instances:"
+{ $subsection >post-data } ;
 
 ARTICLE: "http.client.post" "POST requests with the HTTP client"
 "Basic usage involves passing post data and a " { $link url } ", and getting a " { $link response } " and data back:"
diff --git a/basis/http/client/post-data/post-data-docs.factor b/basis/http/client/post-data/post-data-docs.factor
new file mode 100644 (file)
index 0000000..24325e9
--- /dev/null
@@ -0,0 +1,6 @@
+IN: http.client.post-data
+USING: http http.client.post-data.private help.markup help.syntax kernel ;
+
+HELP: >post-data
+{ $values { "object" object } { "post-data" { $maybe post-data } } }
+{ $description "Converts an object into a " { $link post-data } " tuple instance." } ;
index 6f283ac1bb9bfdd0b229b5d3706e3b5926b18b02..4dfe02d651e31964dcba5453441b0a58d92e4206 100755 (executable)
@@ -46,7 +46,7 @@ M: winnt add-completion ( win32-handle -- )
             { [ dup integer? ] [ ] }
             { [ dup array? ] [
                 first dup eof?
-                [ drop 0 ] [ (win32-error-string) throw ] if
+                [ drop 0 ] [ n>win32-error-string throw ] if
             ] }
         } cond
     ] with-timeout ;
@@ -105,7 +105,7 @@ M: winnt seek-handle ( n seek-type handle -- )
         GetLastError {
             { [ dup expected-io-error? ] [ drop f ] }
             { [ dup eof? ] [ drop t ] }
-            [ (win32-error-string) throw ]
+            [ n>win32-error-string throw ]
         } cond
     ] [ f ] if ;
 
index 64218f75b00d0a90d398b969211cf1f1c305cbbf..33577a9394087069c06c89ad1a4f9f0cd279c6cb 100755 (executable)
@@ -2,7 +2,7 @@ USING: alien alien.c-types alien.syntax arrays continuations
 destructors generic io.mmap io.ports io.backend.windows io.files.windows\r
 kernel libc math math.bitwise namespaces quotations sequences windows\r
 windows.advapi32 windows.kernel32 io.backend system accessors\r
-io.backend.windows.privileges ;\r
+io.backend.windows.privileges windows.errors ;\r
 IN: io.backend.windows.nt.privileges\r
 \r
 TYPEDEF: TOKEN_PRIVILEGES* PTOKEN_PRIVILEGES\r
index 6ecbc49f2af249a6f701d6f0c0434444bcc013cb..9f5c00cc5f4ace2b91d31555b10747a8a7b633e9 100755 (executable)
@@ -1,10 +1,10 @@
 ! Copyright (C) 2004, 2008 Mackenzie Straight, Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien alien.c-types arrays destructors io io.backend
-io.buffers io.files io.ports io.binary io.timeouts
-windows.errors strings kernel math namespaces sequences windows
-windows.kernel32 windows.shell32 windows.types windows.winsock
-splitting continuations math.bitwise system accessors ;
+io.buffers io.files io.ports io.binary io.timeouts system
+windows.errors strings kernel math namespaces sequences
+windows.errors windows.kernel32 windows.shell32 windows.types
+windows.winsock splitting continuations math.bitwise accessors ;
 IN: io.backend.windows
 
 : set-inherit ( handle ? -- )
@@ -51,4 +51,4 @@ HOOK: add-completion io-backend ( port -- )
 : default-security-attributes ( -- obj )
     "SECURITY_ATTRIBUTES" <c-object>
     "SECURITY_ATTRIBUTES" heap-size
-    over set-SECURITY_ATTRIBUTES-nLength ;
\ No newline at end of file
+    over set-SECURITY_ATTRIBUTES-nLength ;
index 5e57a943a95bb0a2d4fe80b48e17f349fc61f050..3659939fb009f508cf30cb1327f9a764a54254ec 100644 (file)
@@ -4,7 +4,7 @@ USING: io io.streams.byte-array ;
 IN: io.encodings.string
 
 : decode ( byte-array encoding -- string )
-    <byte-reader> contents ;
+    <byte-reader> stream-contents ;
 
 : encode ( string encoding -- byte-array )
     [ write ] with-byte-writer ;
index 8419399c92fdd314f4efe2bd9ae2c84e9cf5a57c..bf1bedaa08c342fac92c00246b5e2e1f64d1ff62 100644 (file)
@@ -5,6 +5,10 @@ HELP: make-link
 { $values { "target" "a path to the symbolic link's target" } { "symlink" "a path to new symbolic link" } }
 { $description "Creates a symbolic link." } ;
 
+HELP: make-hard-link
+{ $values { "target" "a path to the hard link's target" } { "link" "a path to new symbolic link" } }
+{ $description "Creates a hard link." } ;
+
 HELP: read-link
 { $values { "symlink" "a path to an existing symbolic link" } { "path" "the path pointed to by the symbolic link" } }
 { $description "Reads the symbolic link and returns its target path." } ;
index 1212d579dbe13234e11a2b107355dda5f8fd5982..7aec916c72086977809a0e4f6a8a6e97acdd62bf 100644 (file)
@@ -6,6 +6,8 @@ IN: io.files.links
 
 HOOK: make-link os ( target symlink -- )
 
+HOOK: make-hard-link os ( target link -- )
+
 HOOK: read-link os ( symlink -- path )
 
 : copy-link ( target symlink -- )
index 7d2a6ee4f3c31b474388fc6f78589a39e2850ece..c9a651b4844cfa5a004b1bdb4fa927b2651654c9 100644 (file)
@@ -7,6 +7,9 @@ IN: io.files.links.unix
 M: unix make-link ( path1 path2 -- )
     normalize-path symlink io-error ;
 
+M: unix make-hard-link ( path1 path2 -- )
+    normalize-path link io-error ;
+
 M: unix read-link ( path -- path' )
     normalize-path read-symbolic-link ;
 
index afc81c784c70944f6a2ac1da034604fab0a64197..32424a37a3976db4fe8be260787e082c4e617bd9 100755 (executable)
@@ -4,7 +4,8 @@ io.backend.windows io.files.windows io.encodings.utf16n windows
 windows.kernel32 kernel libc math threads system environment
 alien.c-types alien.arrays alien.strings sequences combinators
 combinators.short-circuit ascii splitting alien strings assocs
-namespaces make accessors tr windows.time windows.shell32 ;
+namespaces make accessors tr windows.time windows.shell32
+windows.errors ;
 IN: io.files.windows.nt
 
 M: winnt cwd
index f5809223fcf1525f4217f16ada776d7f9f17b449..838c09c65738ae2061c35a4f95ca67c5ac6be3ac 100755 (executable)
@@ -3,9 +3,9 @@
 USING: system kernel namespaces strings hashtables sequences 
 assocs combinators vocabs.loader init threads continuations
 math accessors concurrency.flags destructors environment
-io io.backend io.timeouts io.pipes io.pipes.private io.encodings
-io.streams.duplex io.ports debugger prettyprint summary
-calendar ;
+io io.encodings.ascii io.backend io.timeouts io.pipes
+io.pipes.private io.encodings io.streams.duplex io.ports
+debugger prettyprint summary calendar ;
 IN: io.launcher
 
 TUPLE: process < identity-tuple
@@ -265,3 +265,5 @@ M: object run-pipeline-element
     { [ os winnt? ] [ "io.launcher.windows.nt" require ] }
     [ ]
 } cond
+
+: run-desc ( desc -- result ) ascii <process-reader> f swap stream-read-until drop ;
index f375bb41e87e05d5bf42b22ed1b3639073454894..99d45e4fd7ca0c80a40eeeef030ddd2de8347c0d 100644 (file)
@@ -33,7 +33,7 @@ concurrency.promises threads unix.process ;
     "cat"
     "launcher-test-1" temp-file
     2array
-    ascii <process-reader> contents
+    ascii <process-reader> stream-contents
 ] unit-test
 
 [ ] [
@@ -52,7 +52,7 @@ concurrency.promises threads unix.process ;
     "cat"
     "launcher-test-1" temp-file
     2array
-    ascii <process-reader> contents
+    ascii <process-reader> stream-contents
 ] unit-test
 
 [ ] [
@@ -70,14 +70,14 @@ concurrency.promises threads unix.process ;
     "cat"
     "launcher-test-1" temp-file
     2array
-    ascii <process-reader> contents
+    ascii <process-reader> stream-contents
 ] unit-test
 
 [ t ] [
     <process>
         "env" >>command
         { { "A" "B" } } >>environment
-    ascii <process-reader> lines
+    ascii <process-reader> stream-lines
     "A=B" swap member?
 ] unit-test
 
@@ -86,7 +86,7 @@ concurrency.promises threads unix.process ;
         "env" >>command
         { { "A" "B" } } >>environment
         +replace-environment+ >>environment-mode
-    ascii <process-reader> lines
+    ascii <process-reader> stream-lines
 ] unit-test
 
 [ "hi\n" ] [
@@ -113,13 +113,13 @@ concurrency.promises threads unix.process ;
     "append-test" temp-file utf8 file-contents
 ] unit-test
 
-[ t ] [ "ls" utf8 <process-stream> contents >boolean ] unit-test
+[ t ] [ "ls" utf8 <process-stream> stream-contents >boolean ] unit-test
 
 [ "Hello world.\n" ] [
     "cat" utf8 <process-stream> [
         "Hello world.\n" write
         output-stream get dispose
-        input-stream get contents
+        input-stream get stream-contents
     ] with-stream
 ] unit-test
 
index ebd8109d14e8c82b90b7f687af385e8a81133551..8fdc7fefd9b89dc7c4ae23809935c2ec052be3ce 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
 kernel libc math math.bitwise namespaces quotations sequences
 windows windows.advapi32 windows.kernel32 io.backend system
-accessors locals ;
+accessors locals windows.errors ;
 IN: io.mmap.windows
 
 : create-file-mapping ( hFile lpAttributes flProtect dwMaximumSizeHigh dwMaximumSizeLow lpName -- HANDLE )
@@ -12,8 +12,8 @@ IN: io.mmap.windows
     MapViewOfFile [ win32-error=0/f ] keep ;
 
 :: mmap-open ( path length access-mode create-mode protect access -- handle handle address )
-    [let | lo [ length HEX: ffffffff bitand ]
-           hi [ length -32 shift HEX: ffffffff bitand ] |
+    [let | lo [ length 32 bits ]
+           hi [ length -32 shift 32 bits ] |
         { "SeCreateGlobalPrivilege" "SeLockMemoryPrivilege" } [
             path access-mode create-mode 0 open-file |dispose
             dup handle>> f protect hi lo f create-file-mapping |dispose
index d2408a3dd1810c92b9f9ad7319ff0f3cc35c2bc0..bec249c04c70bf7adfa9a5b0c1170ff0bf903504 100755 (executable)
@@ -6,7 +6,7 @@ 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.encodings.utf16n io windows windows.kernel32 windows.types
+io.encodings.utf16n io windows.errors windows.kernel32 windows.types
 io.pathnames ;
 IN: io.monitors.windows.nt
 
index ae79290f0a014e3eeb2b0a7e604bd70305965f47..ab99531eb495666e84fa82a2035a17a81537eb39 100644 (file)
@@ -35,4 +35,4 @@ concurrency.promises io.encodings.ascii io threads calendar ;
     dup start-server* sockets>> first addr>> port>> "port" set
 ] unit-test
 
-[ "Hello world." ] [ "localhost" "port" get <inet> ascii <client> drop contents ] unit-test
+[ "Hello world." ] [ "localhost" "port" get <inet> ascii <client> drop stream-contents ] unit-test
index 7c4dcc17d1031879f8df3c30eb75a4539bca8925..f87ad93fbd59e0c1b13615f00fe26e606a2887a2 100644 (file)
@@ -23,7 +23,7 @@ io.sockets.secure.unix.debug ;
 
 : client-test ( -- string )
     <secure-config> [
-        "127.0.0.1" "port" get ?promise <inet4> <secure> ascii <client> drop contents
+        "127.0.0.1" "port" get ?promise <inet4> <secure> ascii <client> drop stream-contents
     ] with-secure-context ;
 
 [ ] [ [ class name>> write ] server-test ] unit-test
index 3cf52c6a78dc472f89aaf163619b6d889f4c776f..0cd35dfa213b11583f61ad91958703ffbe53004a 100644 (file)
@@ -6,7 +6,7 @@ io.encodings.utf8 io kernel arrays strings namespaces ;
 
 [ B{ BIN: 11110101 BIN: 10111111 BIN: 10000000 BIN: 10111111 BIN: 11101111 BIN: 10000000 BIN: 10111111 BIN: 11011111 BIN: 10000000 CHAR: x } ]
 [ { BIN: 101111111000000111111 BIN: 1111000000111111 BIN: 11111000000 CHAR: x } >string utf8 [ write ] with-byte-writer ] unit-test
-[ { BIN: 101111111000000111111 } t ] [ { BIN: 11110101 BIN: 10111111 BIN: 10000000 BIN: 10111111 } utf8 <byte-reader> contents dup >array swap string? ] unit-test
+[ { BIN: 101111111000000111111 } t ] [ { BIN: 11110101 BIN: 10111111 BIN: 10000000 BIN: 10111111 } utf8 <byte-reader> stream-contents dup >array swap string? ] unit-test
 
 [ B{ 121 120 } 0 ] [
     B{ 0 121 120 0 0 0 0 0 0 } binary
@@ -26,4 +26,4 @@ io.encodings.utf8 io kernel arrays strings namespaces ;
         0 seek-end input-stream get stream-seek
         read1
     ] with-byte-reader
-] unit-test
\ No newline at end of file
+] unit-test
old mode 100644 (file)
new mode 100755 (executable)
index 6148394..8fcf12a
@@ -1,17 +1,17 @@
 USING: help.markup help.syntax io.streams.plain io strings
-hashtables kernel quotations colors ;
+hashtables kernel quotations colors assocs ;
 IN: io.styles
 
 HELP: stream-format
-{ $values { "str" string } { "style" "a hashtable" } { "stream" "an output stream" } }
+{ $values { "str" string } { "style" assoc } { "stream" "an output stream" } }
 { $contract "Writes formatted text to the stream. If the stream does buffering, output may not be performed immediately; use " { $link stream-flush } " to force output."
 $nl
-"The " { $snippet "style" } " hashtable holds character style information. See " { $link "character-styles" } "." }
+"The " { $snippet "style" } " assoc holds character style information. See " { $link "character-styles" } "." }
 { $notes "Most code only works on one stream at a time and should instead use " { $link format } "; see " { $link "stdio" } "." }
 $io-error ;
 
 HELP: make-block-stream
-{ $values { "style" "a hashtable" } { "stream" "an output stream" } { "stream'" "an output stream" } }
+{ $values { "style" assoc } { "stream" "an output stream" } { "stream'" "an output stream" } }
 { $contract "Creates an output stream which wraps " { $snippet "stream" } " and adds " { $snippet "style" } " on calls to " { $link stream-write } " and " { $link stream-format } "."
 $nl
 "Unlike " { $link make-span-stream } ", this creates a new paragraph block in the output."
@@ -21,7 +21,7 @@ $nl
 $io-error ;
 
 HELP: stream-write-table
-{ $values { "table-cells" "a sequence of sequences of table cells" } { "style" "a hashtable" } { "stream" "an output stream" } }
+{ $values { "table-cells" "a sequence of sequences of table cells" } { "style" assoc } { "stream" "an output stream" } }
 { $contract "Prints a table of cells produced by " { $link with-cell } "."
 $nl
 "The " { $snippet "style" } " hashtable holds table style information. See " { $link "table-styles" } "." }
@@ -29,13 +29,13 @@ $nl
 $io-error ;
 
 HELP: make-cell-stream
-{ $values { "style" hashtable } { "stream" "an output stream" } { "stream'" object } }
+{ $values { "style" assoc } { "stream" "an output stream" } { "stream'" object } }
 { $contract "Creates an output stream which writes to a table cell object." }
 { $notes "Most code only works on one stream at a time and should instead use " { $link with-cell } "; see " { $link "stdio" } "." }
 $io-error ;
 
 HELP: make-span-stream
-{ $values { "style" "a hashtable" } { "stream" "an output stream" } { "stream'" "an output stream" } }
+{ $values { "style" assoc } { "stream" "an output stream" } { "stream'" "an output stream" } }
 { $contract "Creates an output stream which wraps " { $snippet "stream" } " and adds " { $snippet "style" } " on calls to " { $link stream-write } " and " { $link stream-format } "."
 $nl
 "Unlike " { $link make-block-stream } ", the stream output is inline, and not nested in a paragraph block." }
@@ -43,19 +43,19 @@ $nl
 $io-error ;
 
 HELP: format
-{ $values { "str" string } { "style" "a hashtable" } }
+{ $values { "str" string } { "style" assoc } }
 { $description "Writes formatted text to " { $link output-stream } ". If the stream does buffering, output may not be performed immediately; use " { $link flush } " to force output." }
 { $notes "Details are in the documentation for " { $link stream-format } "." }
 $io-error ;
 
 HELP: with-nesting
-{ $values { "style" "a hashtable" } { "quot" quotation } }
+{ $values { "style" assoc } { "quot" quotation } }
 { $description "Calls the quotation in a new dynamic scope with " { $link output-stream } " rebound to a nested paragraph stream, with formatting information applied." }
 { $notes "Details are in the documentation for " { $link make-block-stream } "." }
 $io-error ;
 
 HELP: tabular-output
-{ $values { "style" "a hashtable" } { "quot" quotation } }
+{ $values { "style" assoc } { "quot" quotation } }
 { $description "Calls a quotation which emits a series of equal-length table rows using " { $link with-row } ". The results are laid out in a tabular fashion on " { $link output-stream } "."
 $nl
 "The " { $snippet "style" } " hashtable holds table style information. See " { $link "table-styles" } "." }
@@ -85,7 +85,7 @@ HELP: write-cell
 $io-error ;
 
 HELP: with-style
-{ $values { "style" "a hashtable" } { "quot" quotation } }
+{ $values { "style" assoc } { "quot" quotation } }
 { $description "Calls the quotation in a new dynamic scope where calls to " { $link write } ", " { $link format } " and other stream output words automatically inherit style settings from " { $snippet "style" } "." }
 { $notes "Details are in the documentation for " { $link make-span-stream } "." }
 $io-error ;
index c3bf5d2f28c9d0b548db71d6ba9d062a1986b2d4..2d25016919cb6ee96971d368590d886593babc29 100644 (file)
@@ -99,7 +99,11 @@ M: plain-writer make-block-stream
     nip <ignore-close-stream> ;
 
 M: plain-writer stream-write-table
-    [ drop format-table [ nl ] [ write ] interleave ] with-output-stream* ;
+    [
+        drop
+        [ [ >string ] map ] map format-table
+        [ nl ] [ write ] interleave
+    ] with-output-stream* ;
 
 M: plain-writer make-cell-stream 2drop <string-writer> ;
 
index 68fa8dbda0362d9018548056ebecfcb88ea6e322..1549a776631bf1252af7a32e28917c2f588f7807 100644 (file)
@@ -585,4 +585,4 @@ M: integer ed's-bug neg ;
 :: ed's-test-case ( a -- b )
    { [ a ed's-bug ] } && ;
 
-[ t ] [ \ ed's-test-case optimized>> ] unit-test
+[ t ] [ \ ed's-test-case optimized? ] unit-test
old mode 100644 (file)
new mode 100755 (executable)
index acd2c33..6a4672b
@@ -49,6 +49,7 @@ $nl
 { $subsection POSTPONE: MACRO: }
 "A slightly lower-level facility, " { $emphasis "compiler transforms" } ", allows an ordinary word definition to co-exist with a version that performs compile-time expansion."
 { $subsection define-transform }
-"An example is the " { $link member? } " word. If the input sequence is a literal, the compile transform kicks in and converts the " { $link member? } " call into a series of conditionals. Otherwise, if the input sequence is not literal, a call to the definition of " { $link member? } " is generated." ;
+"An example is the " { $link member? } " word. If the input sequence is a literal, the compile transform kicks in and converts the " { $link member? } " call into a series of conditionals. Otherwise, if the input sequence is not literal, a call to the definition of " { $link member? } " is generated."
+{ $see-also "generalizations" "fry" } ;
 
 ABOUT: "macros"
index 6b6f5c95bd323cf757b29bf90ea92ce4a7991db4..a51b86ff0b44a8330592d2f5fed8b2b6b112458f 100644 (file)
@@ -25,7 +25,3 @@ HELP: complex
 { $class-description "The class of complex numbers with non-zero imaginary part." } ;
 
 ABOUT: "complex-numbers"
-
-HELP: <complex> ( x y -- z )
-{ $values { "x" "a real number" } { "y" "a real number" } { "z" "a complex number" } }
-{ $description "Low-level complex number constructor. User code should call " { $link rect> } " instead." } ;
index c41faaf5585a1638e298b93638d00d220adb929d..832a9e64baf9db08cf7921f8aaafc1c3661160d2 100644 (file)
@@ -15,14 +15,14 @@ M: complex hashcode* nip >rect [ hashcode ] bi@ bitxor ;
 : complex= ( x y quot -- ? ) componentwise and ; inline
 M: complex equal? over complex? [ [ = ] complex= ] [ 2drop f ] if ;
 M: complex number= [ number= ] complex= ;
-: complex-op ( x y quot -- z ) componentwise (rect>) ; inline
+: complex-op ( x y quot -- z ) componentwise rect> ; inline
 M: complex + [ + ] complex-op ;
 M: complex - [ - ] complex-op ;
 : *re ( x y -- xr*yr xi*yi ) [ >rect ] bi@ [ * ] bi-curry@ bi* ; inline
 : *im ( x y -- xi*yr xr*yi ) swap [ >rect ] bi@ swap [ * ] bi-curry@ bi* ; inline
-M: complex * [ *re - ] [ *im + ] 2bi (rect>) ;
+M: complex * [ *re - ] [ *im + ] 2bi rect> ;
 : (complex/) ( x y -- r i m ) [ [ *re + ] [ *im - ] 2bi ] keep absq ; inline
-: complex/ ( x y quot -- z ) [ (complex/) ] dip curry bi@ (rect>) ; inline
+: complex/ ( x y quot -- z ) [ (complex/) ] dip curry bi@ rect> ; inline
 M: complex / [ / ] complex/ ;
 M: complex /f [ /f ] complex/ ;
 M: complex /i [ /i ] complex/ ;
index f7d0d5a94160ea527f967b853936e945ccd18b68..48da8aa6ec66f73ba63d2d24867a75a6d7760f86 100644 (file)
@@ -100,11 +100,6 @@ ARTICLE: "math-functions" "Mathematical functions"
 
 ABOUT: "math-functions"
 
-HELP: (rect>)
-{ $values { "x" real } { "y" real } { "z" number } }
-{ $description "Creates a complex number from real and imaginary components." }
-{ $warning "This word does not check that the arguments are real numbers, which can have undefined consequences. Use the " { $link rect> } " word instead." } ;
-
 HELP: rect>
 { $values { "x" real } { "y" real } { "z" number } }
 { $description "Creates a complex number from real and imaginary components. If " { $snippet "z" } " is an integer zero, this will simply output " { $snippet "x" } "." } ;
index a6beb87345926b08d2c27bc0f7df28c3b8a9d3c6..c21053317e6d88c984f56b7bacef622bca38d594 100644 (file)
@@ -7,19 +7,8 @@ IN: math.functions
 : >fraction ( a/b -- a b )
     [ numerator ] [ denominator ] bi ; inline
 
-<PRIVATE
-
-: (rect>) ( x y -- z )
-    dup 0 = [ drop ] [ <complex> ] if ; inline
-
-PRIVATE>
-
 : rect> ( x y -- z )
-    2dup [ real? ] both? [
-        (rect>)
-    ] [
-        "Complex number must have real components" throw
-    ] if ; inline
+    dup 0 = [ drop ] [ complex boa ] if ; inline
 
 GENERIC: sqrt ( x -- y ) foldable
 
index 7b6393dabe06f9a1939f48f2d73e4901ee3db6cb..2e51fa1870e003f49255ebe4933a7ddf57b41047 100644 (file)
@@ -47,6 +47,3 @@ HELP: 2>fraction
 { $values { "a/b" rational } { "c/d" rational } { "a" integer } { "c" integer } { "b" "a positive integer" } { "d" "a positive integer" } }
 { $description "Extracts the numerator and denominator of two rational numbers at once." } ;
 
-HELP: <ratio> ( a b -- a/b )
-{ $values { "a" integer } { "b" integer } { "a/b" "a ratio" } }
-{ $description "Primitive ratio constructor. User code should call " { $link / } " to create ratios instead." } ;
index 54e4bee1a85582376d185fd275e3ba81748efdaf..d4f457180edc393a26510cdec3c33c9b656f8821 100644 (file)
@@ -9,7 +9,7 @@ IN: math.ratios
 <PRIVATE
 
 : fraction> ( a b -- a/b )
-    dup 1 number= [ drop ] [ <ratio> ] if ; inline
+    dup 1 number= [ drop ] [ ratio boa ] if ; inline
 
 : scale ( a/b c/d -- a*d b*c )
     2>fraction [ * swap ] dip * swap ; inline
index 683fa328d837273616913634b4a658925d4627b6..cae1e05dc820c37a684a53da5181f2803c5c89f6 100644 (file)
@@ -199,10 +199,10 @@ IN: peg.tests
 
 USE: compiler
 
-[ ] [ disable-compiler ] unit-test
+[ ] [ disable-optimizer ] unit-test
 
 [ ] [ "" epsilon parse drop ] unit-test
 
-[ ] [ enable-compiler ] unit-test
+[ ] [ enable-optimizer ] unit-test
 
 [ [ ] ] [ "" epsilon [ drop [ [ ] ] call ] action parse ] unit-test
index a4cf74e1df1940b18c88d6116b72b5355e84fb3c..488deef41fe71b5e8ece12067d3e779de5df7f4f 100644 (file)
@@ -1,6 +1,6 @@
 USING: accessors alien.c-types byte-arrays continuations
-kernel windows windows.advapi32 init namespaces random
-destructors locals ;
+kernel windows.advapi32 init namespaces random destructors
+locals windows.errors ;
 IN: random.windows
 
 TUPLE: windows-rng provider type ;
old mode 100644 (file)
new mode 100755 (executable)
index 9c10641..9971a1d
@@ -1,14 +1,18 @@
 ! Copyright (C) 2007 Slava Pestov, 2009 Alex Chapman
 ! See http://factorcode.org/license.txt for BSD license.
-USING: boxes help.markup help.syntax kernel math namespaces ;
+USING: boxes help.markup help.syntax kernel math namespaces assocs ;
 IN: refs
 
 ARTICLE: "refs" "References"
-"References provide a uniform way of accessing and changing values. Some examples of referenced values are variables, tuple slots, and keys or values of assocs. References can be read, written, and deleted. References are defined in the " { $vocab-link "refs" } " vocabulary, and new reference types can be made by implementing the " { $link "refs-protocol" } "."
-{ $subsection get-ref }
-{ $subsection set-ref }
-{ $subsection set-ref* }
-{ $subsection delete-ref }
+"References provide a uniform way of accessing and changing values. Some examples of referenced values are variables, tuple slots, and keys or values of assocs. References can be read, written, and deleted. References are defined in the " { $vocab-link "refs" } " vocabulary, and new reference types can be made by implementing a protocol."
+{ $subsection "refs-protocol" }
+{ $subsection "refs-impls" }
+{ $subsection "refs-utils" }
+"References are used by the " { $link "ui-inspector" } "." ;
+
+ABOUT: "refs"
+
+ARTICLE: "refs-impls" "Reference implementations"
 "References to objects:"
 { $subsection obj-ref }
 { $subsection <obj-ref> }
@@ -27,20 +31,24 @@ ARTICLE: "refs" "References"
 { $subsection slot-ref }
 { $subsection <slot-ref> }
 "Using boxes as references:"
-{ $subsection "box-refs" }
-"References are used by the UI inspector." ;
+{ $subsection "box-refs" } ;
 
-ABOUT: "refs"
+ARTICLE: "refs-utils" "Reference utilities"
+{ $subsection ref-on }
+{ $subsection ref-off }
+{ $subsection ref-inc }
+{ $subsection ref-dec }
+{ $subsection set-ref* } ;
 
-ARTICLE: "refs-protocol" "Reference Protocol"
+ARTICLE: "refs-protocol" "Reference protocol"
 "To use a class of objects as references you must implement the reference protocol for that class, and mark your class as an instance of the " { $link ref } " mixin class. All references must implement these two words:"
 { $subsection get-ref }
 { $subsection set-ref }
 "References may also implement:"
 { $subsection delete-ref } ;
 
-ARTICLE: "box-refs" "Using Boxes as References"
-"Boxes are elements of the " { $link ref } " mixin class, so any box may be used as a reference. Bear in mind that boxes will still throw an error if you call " { $link get-ref } " on an empty box." ;
+ARTICLE: "box-refs" "Boxes as references"
+{ $link "boxes" } " are elements of the " { $link ref } " mixin class, so any box may be used as a reference. Bear in mind that boxes will still throw an error if you call " { $link get-ref } " on an empty box." ;
 
 HELP: ref
 { $class-description "A mixin class whose instances encapsulate a value which can be read, written, and deleted. Instantiable members of this class include:" { $link obj-ref } ", " { $link var-ref } ", " { $link global-var-ref } ", " { $link slot-ref } ", " { $link box } ", " { $link key-ref } ", and " { $link value-ref } "." } ;
@@ -89,14 +97,14 @@ HELP: key-ref
 { $class-description "Instances of this class identify a key in an associative structure. New key references are created by calling " { $link <key-ref> } "." } ;
 
 HELP: <key-ref>
-{ $values { "assoc" "an assoc" } { "key" object } { "key-ref" key-ref } }
+{ $values { "assoc" assoc } { "key" object } { "key-ref" key-ref } }
 { $description "Creates a reference to a key stored in an assoc." } ;
 
 HELP: value-ref
 { $class-description "Instances of this class identify a value associated to a key in an associative structure. New value references are created by calling " { $link <value-ref> } "." } ;
 
 HELP: <value-ref>
-{ $values { "assoc" "an assoc" } { "key" object } { "value-ref" value-ref } }
+{ $values { "assoc" assoc } { "key" object } { "value-ref" value-ref } }
 { $description "Creates a reference to the value associated with " { $snippet "key" } " in " { $snippet "assoc" } "." } ;
 
 { get-ref set-ref delete-ref set-ref* } related-words
index 2494c72fa4134b6e12cc8f884e69b19f2ab7dd38..37153b522903cc86fe3a21ab01142ab59fd81e94 100644 (file)
@@ -1,13 +1,13 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors arrays assocs classes classes.builtin
-classes.intersection classes.mixin classes.predicate
-classes.singleton classes.tuple classes.union combinators
-definitions effects generic generic.standard io io.pathnames
+classes.intersection classes.mixin classes.predicate classes.singleton
+classes.tuple classes.union combinators definitions effects generic
+generic.single generic.standard generic.hook io io.pathnames
 io.streams.string io.styles kernel make namespaces prettyprint
 prettyprint.backend prettyprint.config prettyprint.custom
-prettyprint.sections sequences sets sorting strings summary
-words words.symbol words.constant words.alias ;
+prettyprint.sections sequences sets sorting strings summary words
+words.symbol words.constant words.alias ;
 IN: see
 
 GENERIC: synopsis* ( defspec -- )
index 4fb5bab96fcc4329b6e620e8b140db0ab14c64e0..338b052316146c9fbd19d2b44fd8deb0fc2efd08 100755 (executable)
@@ -1,10 +1,9 @@
 ! Copyright (C) 2004, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: fry arrays generic io io.streams.string kernel math
-namespaces parser sequences strings vectors words quotations
-effects classes continuations assocs combinators
-compiler.errors accessors math.order definitions sets
-generic.standard.engines.tuple hints macros stack-checker.state
+USING: fry arrays generic io io.streams.string kernel math namespaces
+parser sequences strings vectors words quotations effects classes
+continuations assocs combinators compiler.errors accessors math.order
+definitions sets hints macros stack-checker.state
 stack-checker.visitor stack-checker.errors stack-checker.values
 stack-checker.recursive-state ;
 IN: stack-checker.backend
index e5c0f23b30f32ddb30160ed56690671aa3357521..b222cbbcf75ce374c6133953f1e6e20199133209 100644 (file)
@@ -1,7 +1,16 @@
-USING: stack-checker.call-effect tools.test math kernel ;
+USING: stack-checker.call-effect tools.test math kernel math effects ;
 IN: stack-checker.call-effect.tests
 
 [ t ] [ \ + (( a b -- c )) execute-effect-unsafe? ] unit-test
 [ t ] [ \ + (( a b c -- d e )) execute-effect-unsafe? ] unit-test
 [ f ] [ \ + (( a b c -- d )) execute-effect-unsafe? ] unit-test
-[ f ] [ \ call (( x -- )) execute-effect-unsafe? ] unit-test
\ No newline at end of file
+[ f ] [ \ call (( x -- )) execute-effect-unsafe? ] unit-test
+
+[ t ] [ [ + ] cached-effect (( a b -- c )) effect= ] unit-test
+[ t ] [ 5 [ + ] curry cached-effect (( a -- c )) effect= ] unit-test
+[ t ] [ 5 [ ] curry cached-effect (( -- c )) effect= ] unit-test
+[ t ] [ [ dup ] [ drop ] compose cached-effect (( a -- b )) effect= ] unit-test
+[ t ] [ [ drop ] [ dup ] compose cached-effect (( a b -- c d )) effect= ] unit-test
+[ t ] [ [ 2drop ] [ dup ] compose cached-effect (( a b c -- d e )) effect= ] unit-test
+[ t ] [ [ 1 2 3 ] [ 2drop ] compose cached-effect (( -- a )) effect= ] unit-test
+[ t ] [ [ 1 2 ] [ 3drop ] compose cached-effect (( a -- )) effect= ] unit-test
\ No newline at end of file
index 100088f17492b0024f5ebaecfd32a216114d1a8d..b3b678d93d91aa42ccaf7bb2f6f6acac07c816b9 100644 (file)
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors combinators combinators.private effects fry
 kernel kernel.private make sequences continuations quotations
-stack-checker stack-checker.transforms words ;
+stack-checker stack-checker.transforms words math ;
 IN: stack-checker.call-effect
 
 ! call( and execute( have complex expansions.
@@ -18,14 +18,36 @@ IN: stack-checker.call-effect
 
 TUPLE: inline-cache value ;
 
-: cache-hit? ( word/quot ic -- ? ) value>> eq? ; inline
+: cache-hit? ( word/quot ic -- ? )
+    [ value>> eq? ] [ value>> ] bi and ; inline
 
-SYMBOL: +unknown+
+SINGLETON: +unknown+
 
 GENERIC: cached-effect ( quot -- effect )
 
 M: object cached-effect drop +unknown+ ;
 
+GENERIC: curry-effect ( effect -- effect' )
+
+M: +unknown+ curry-effect ;
+
+M: effect curry-effect
+    [ in>> length ] [ out>> length ] [ terminated?>> ] tri
+    pick 0 = [ [ 1+ ] dip ] [ [ 1- ] 2dip ] if
+    effect boa ;
+
+M: curry cached-effect
+    quot>> cached-effect curry-effect ;
+
+: compose-effects* ( effect1 effect2 -- effect' )
+    {
+        { [ 2dup [ effect? ] both? ] [ compose-effects ] }
+        { [ 2dup [ +unknown+ eq? ] either? ] [ 2drop +unknown+ ] }
+    } cond ;
+
+M: compose cached-effect
+    [ first>> ] [ second>> ] bi [ cached-effect ] bi@ compose-effects* ;
+
 M: quotation cached-effect
     dup cached-effect>>
     [ ] [
@@ -79,7 +101,7 @@ M: quotation cached-effect
     [ '[ _ execute ] ] dip call-effect-slow ; inline
 
 : execute-effect-unsafe? ( word effect -- ? )
-    over optimized>> [ [ stack-effect ] dip effect<= ] [ 2drop f ] if ; inline
+    over optimized? [ [ stack-effect ] dip effect<= ] [ 2drop f ] if ; inline
 
 : execute-effect-fast ( word effect inline-cache -- )
     2over execute-effect-unsafe?
old mode 100644 (file)
new mode 100755 (executable)
index 7a87ab9..6a67b81
@@ -84,8 +84,11 @@ HELP: inconsistent-recursive-call-error
 } ;
 
 ARTICLE: "inference-errors" "Stack checker errors"
-"These conditions are thrown by " { $link "inference" } ", as well as the " { $link "compiler" } "."
-$nl
+"These " { $link "inference" } " failure conditions are reported in one of two ways:"
+{ $list
+    { { $link "tools.inference" } " throws them as errors" }
+    { "The " { $link "compiler" } " reports them via " { $link "tools.errors" } }
+}
 "Error thrown when insufficient information is available to calculate the stack effect of a combinator call (see " { $link "inference-combinators" } "):"
 { $subsection literal-expected }
 "Error thrown when a word's stack effect declaration does not match the composition of the stack effects of its factors:"
index e036d4d81b5c2012d6be33ce300044f9f024f0cf..b1071df7080d16ab8cc4d45d65c6731ff8635257 100644 (file)
@@ -33,4 +33,6 @@ ERROR: unknown-primitive-error < inference-error ;
 
 ERROR: transform-expansion-error < inference-error word error ;
 
+ERROR: bad-declaration-error < inference-error declaration ;
+
 M: object (literal) "literal value" literal-expected ;
\ No newline at end of file
index eade33e52b008ba29147ee99a6cd3abef812b5cf..4a9ff93179c21247986f0a5f8c3a699b6a325922 100644 (file)
@@ -9,9 +9,10 @@ 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 definitions
-words.private assocs summary compiler.units system.private
-combinators locals locals.backend locals.types words.private
+assocs summary compiler.units system.private
+combinators combinators.short-circuit locals locals.backend locals.types
 quotations.private combinators.private stack-checker.values
+generic.single generic.single.private
 alien.libraries
 stack-checker.alien
 stack-checker.state
@@ -57,8 +58,12 @@ IN: stack-checker.known-words
 : infer-shuffle-word ( word -- )
     "shuffle" word-prop infer-shuffle ;
 
+: check-declaration ( declaration -- declaration )
+    dup { [ array? ] [ [ class? ] all? ] } 1&&
+    [ bad-declaration-error ] unless ;
+
 : infer-declare ( -- )
-    pop-literal nip
+    pop-literal nip check-declaration
     [ length ensure-d ] keep zip
     #declare, ;
 
@@ -142,7 +147,7 @@ M: object infer-call*
     apply-word/effect ;
 
 : infer-execute-effect-unsafe ( -- )
-    \ execute infer-effect-unsafe ;
+    \ (execute) infer-effect-unsafe ;
 
 : infer-call-effect-unsafe ( -- )
     \ call infer-effect-unsafe ;
@@ -227,14 +232,7 @@ M: object infer-call*
 
 ! More words not to compile
 \ call t "no-compile" set-word-prop
-\ call subwords [ t "no-compile" set-word-prop ] each
-
 \ execute t "no-compile" set-word-prop
-\ execute subwords [ t "no-compile" set-word-prop ] each
-
-\ effective-method t "no-compile" set-word-prop
-\ effective-method subwords [ t "no-compile" set-word-prop ] each
-
 \ clear t "no-compile" set-word-prop
 
 : non-inline-word ( word -- )
@@ -292,9 +290,6 @@ M: object infer-call*
 \ bignum>float { bignum } { float } define-primitive
 \ bignum>float make-foldable
 
-\ <ratio> { integer integer } { ratio } define-primitive
-\ <ratio> make-foldable
-
 \ string>float { string } { float } define-primitive
 \ string>float make-foldable
 
@@ -313,9 +308,6 @@ M: object infer-call*
 \ bits>double { integer } { float } define-primitive
 \ bits>double make-foldable
 
-\ <complex> { real real } { complex } define-primitive
-\ <complex> make-foldable
-
 \ both-fixnums? { object object } { object } define-primitive
 
 \ fixnum+ { fixnum fixnum } { integer } define-primitive
@@ -676,3 +668,12 @@ M: object infer-call*
 \ gc-stats { } { array } define-primitive
 
 \ jit-compile { quotation } { } define-primitive
+
+\ lookup-method { object array } { word } define-primitive
+
+\ reset-dispatch-stats { } { } define-primitive
+\ dispatch-stats { } { array } define-primitive
+\ reset-inline-cache-stats { } { } define-primitive
+\ inline-cache-stats { } { array } define-primitive
+
+\ optimized? { word } { object } define-primitive
\ No newline at end of file
index 243221ccf0c943fc60eafa9b55185a52217beb39..7d18482bff8edc07451a51ec3fbc68f10546cf7f 100644 (file)
@@ -102,6 +102,7 @@ ARTICLE: "tools.inference" "Stack effect tools"
 "Comparing effects:"
 { $subsection effect-height }
 { $subsection effect<= }
+{ $subsection effect= }
 "The class of stack effects:"
 { $subsection effect }
 { $subsection effect? } ;
index cd8a57bf2e5a4258031c5cda1ad1b397cc0a65c4..8113a662d6582d7d90c16e2a2cb3688957a01f25 100755 (executable)
@@ -19,7 +19,6 @@ IN: stack-checker.transforms
     rstate recursive-state
     [ word stack quot call-transformer ] with-variable
     [
-        word inlined-dependency depends-on
         values [ length meta-d shorten-by ] [ #drop, ] bi
         rstate infer-quot
     ] [ word infer-word ] if* ;
@@ -108,7 +107,6 @@ IN: stack-checker.transforms
 ] 1 define-transform
 
 \ boa t "no-compile" set-word-prop
-M\ tuple-class boa t "no-compile" set-word-prop
 
 \ new [
     dup tuple-class? [
index a77312897adab0975ca67d4705774ed0ce32fdb5..9429772f4a63fcae526b0d354f442d2bba6dc491 100644 (file)
@@ -2,3 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: tools.test strings.tables ;
 IN: strings.tables.tests
+
+[ { "A  BB" "CC D" } ] [ { { "A" "BB" } { "CC" "D" } } format-table ] unit-test
+
+[ { "A C" "B " "D E" } ] [ { { "A\nB" "C" } { "D" "E" } } format-table ] unit-test
\ No newline at end of file
index c6ccba5a785683983eda531de38fb654cd3a85c8..51032264c7ad4c50aafdf4f50e8b02afcd6334c1 100644 (file)
@@ -1,21 +1,30 @@
 ! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel sequences fry math.order ;
+USING: kernel sequences fry math.order splitting ;
 IN: strings.tables
 
 <PRIVATE
 
+: map-last ( seq quot -- seq )
+    [ dup length <reversed> ] dip '[ 0 = @ ] 2map ; inline
+
+: max-length ( seq -- n )
+    [ length ] [ max ] map-reduce ;
+
+: format-row ( seq ? -- seq )
+    [
+        dup max-length
+        '[ _ "" pad-tail ] map
+    ] unless ;
+
 : format-column ( seq ? -- seq )
     [
-        dup [ length ] [ max ] map-reduce
+        dup max-length
         '[ _ CHAR: \s pad-tail ] map
     ] unless ;
 
-: map-last ( seq quot -- seq )
-    [ dup length <reversed> ] dip '[ 0 = @ ] 2map ; inline
-
 PRIVATE>
 
 : format-table ( table -- seq )
-    flip [ format-column ] map-last
-    flip [ " " join ] map ;
\ No newline at end of file
+    [ [ [ string-lines ] map ] dip format-row flip ] map-last concat
+    flip [ format-column ] map-last flip [ " " join ] map ;
\ No newline at end of file
index 1ac4557ec41c5dbb8a55628e9ac3a89583e7bdd2..8c572f4ae3c7788e92830588af7f3b1a9e5b6b3d 100644 (file)
@@ -4,7 +4,7 @@ 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.standard definitions make sbufs tools.crossref ;
+generic generic.single definitions make sbufs tools.crossref ;
 IN: tools.continuations
 
 <PRIVATE
@@ -53,8 +53,7 @@ M: object add-breakpoint ;
 : (step-into-execute) ( word -- )
     {
         { [ dup "step-into" word-prop ] [ "step-into" word-prop call ] }
-        { [ dup standard-generic? ] [ effective-method (step-into-execute) ] }
-        { [ dup hook-generic? ] [ effective-method (step-into-execute) ] }
+        { [ dup single-generic? ] [ effective-method (step-into-execute) ] }
         { [ dup uses \ suspend swap member? ] [ execute break ] }
         { [ dup primitive? ] [ execute break ] }
         [ def>> (step-into-quot) ]
index c5cd246f2e08bc826baee4d8cdf387ac4f7df3c7..6082933bcb24cd5a6bee606184c04315eaecf47b 100644 (file)
@@ -3,8 +3,7 @@
 USING: words assocs definitions io io.pathnames io.styles kernel
 prettyprint sorting see sets sequences arrays hashtables help.crossref
 help.topics help.markup quotations accessors source-files namespaces
-graphs vocabs generic generic.standard.engines.tuple threads
-compiler.units init ;
+graphs vocabs generic generic.single threads compiler.units init ;
 IN: tools.crossref
 
 SYMBOL: crossref
@@ -82,7 +81,7 @@ M: object irrelevant? drop f ;
 
 M: default-method irrelevant? drop t ;
 
-M: engine-word irrelevant? drop t ;
+M: predicate-engine irrelevant? drop t ;
 
 PRIVATE>
 
index 6ca54ca36b6ca1b7b3c8a4d42ed154ace4b751c5..b74548a65f3346a0478c5e6c18a26206b9bc5e0e 100755 (executable)
@@ -3,12 +3,11 @@
 USING: namespaces make continuations.private kernel.private init
 assocs kernel vocabs words sequences memory io system arrays
 continuations math definitions mirrors splitting parser classes
-summary layouts vocabs.loader prettyprint.config prettyprint
-debugger io.streams.c io.files io.files.temp io.pathnames
-io.directories io.directories.hierarchy io.backend quotations
-io.launcher words.private tools.deploy.config
-tools.deploy.config.editor bootstrap.image io.encodings.utf8
-destructors accessors hashtables ;
+summary layouts vocabs.loader prettyprint.config prettyprint debugger
+io.streams.c io.files io.files.temp io.pathnames io.directories
+io.directories.hierarchy io.backend quotations io.launcher
+tools.deploy.config tools.deploy.config.editor bootstrap.image
+io.encodings.utf8 destructors accessors hashtables ;
 IN: tools.deploy.backend
 
 : copy-vm ( executable bundle-name -- vm )
index e23e1b092da95fd8d4eb8cc00633e8486dbd9450..9b02d3208fe85549efe3b92f028717f63c9f4d35 100755 (executable)
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors io.backend io.streams.c init fry
 namespaces make assocs kernel parser lexer strings.parser vocabs
-sequences words words.private memory kernel.private
+sequences words memory kernel.private
 continuations io vocabs.loader system strings sets
 vectors quotations byte-arrays sorting compiler.units
 definitions generic generic.standard tools.deploy.config ;
@@ -103,6 +103,7 @@ IN: tools.deploy.shaker
                 "compiled-uses"
                 "constraints"
                 "custom-inlining"
+                "decision-tree"
                 "declared-effect"
                 "default"
                 "default-method"
@@ -112,14 +113,12 @@ IN: tools.deploy.shaker
                 "engines"
                 "forgotten"
                 "identities"
-                "if-intrinsics"
-                "infer"
                 "inline"
                 "inlined-block"
                 "input-classes"
                 "instances"
                 "interval"
-                "intrinsics"
+                "intrinsic"
                 "lambda"
                 "loc"
                 "local-reader"
@@ -136,7 +135,7 @@ IN: tools.deploy.shaker
                 "method-generic"
                 "modular-arithmetic"
                 "no-compile"
-                "optimizer-hooks"
+                "owner-generic"
                 "outputs"
                 "participants"
                 "predicate"
@@ -149,17 +148,13 @@ IN: tools.deploy.shaker
                 "register"
                 "register-size"
                 "shuffle"
-                "slot-names"
                 "slots"
                 "special"
                 "specializer"
-                "step-into"
-                "step-into?"
                 ! UI needs this
                 ! "superclass"
                 "transform-n"
                 "transform-quot"
-                "tuple-dispatch-generic"
                 "type"
                 "writer"
                 "writing"
index eb780e40cc57a10306eb7f6d9883ec1a4e2b8c7a..f997a6eb3a949fc659291257be082eeb7ddc337c 100644 (file)
@@ -16,4 +16,5 @@ IN: tools.deploy.test
 : run-temp-image ( -- )
     vm
     "-i=" "test.image" temp-file append
-    2array try-process ;
\ No newline at end of file
+    2array
+    <process> swap >>command +closed+ >>stdin try-process ;
\ No newline at end of file
index 49cfb054a13e03b44240c9379edc0939025f64e7..89ca265bf6ff3ca7d5d4ab930cc5e2cddbbcab1a 100644 (file)
@@ -1,6 +1,4 @@
 IN: tools.disassembler.tests\r
-USING: math classes.tuple prettyprint.custom \r
-tools.disassembler tools.test strings ;\r
+USING: kernel fry vocabs tools.disassembler tools.test sequences ;\r
 \r
-[ ] [ \ + disassemble ] unit-test\r
-[ ] [ M\ string pprint* disassemble ] unit-test\r
+"math" words [ [ [ ] ] dip '[ _ disassemble ] unit-test ] each
\ No newline at end of file
index 51e399c1c3d1d708635515d4544881d9eab55163..cd9dd9cf4b968f3066a3296cf2b77968418a1314 100755 (executable)
@@ -3,7 +3,7 @@
 USING: tools.disassembler namespaces combinators
 alien alien.syntax alien.c-types lexer parser kernel
 sequences layouts math math.order alien.libraries
-math.parser system make fry arrays ;
+math.parser system make fry arrays libc destructors ;
 IN: tools.disassembler.udis
 
 <<
@@ -47,11 +47,14 @@ FUNCTION: uint ud_insn_len ( ud* u ) ;
 FUNCTION: char* ud_lookup_mnemonic ( int c ) ;
 
 : <ud> ( -- ud )
-    "ud" <c-object>
+    "ud" malloc-object &free
     dup ud_init
     dup cell-bits ud_set_mode
     dup UD_SYN_INTEL ud_set_syntax ;
 
+: with-ud ( quot: ( ud -- ) -- )
+    [ [ <ud> ] dip call ] with-destructors ; inline
+
 SINGLETON: udis-disassembler
 
 : buf/len ( from to -- buf len ) [ drop <alien> ] [ swap - ] 2bi ;
@@ -82,10 +85,12 @@ SINGLETON: udis-disassembler
     ] { } make ;
 
 M: udis-disassembler disassemble* ( from to -- buffer )
-    [ <ud> ] 2dip {
+    '[
+        _ _
         [ drop ud_set_pc ]
         [ buf/len ud_set_input_buffer ]
         [ 2drop (disassemble) format-disassembly ]
-    } 3cleave ;
+        3tri
+    ] with-ud ;
 
 udis-disassembler disassembler-backend set-global
index f35da242663caa4e1b48557614c0dc6ab680b9c3..5c8b8684836900c925609b5b3bbf65908c7cf8b3 100755 (executable)
@@ -6,7 +6,7 @@ vocabs.loader io combinators calendar accessors math.parser
 io.streams.string ui.tools.operations quotations strings arrays
 prettyprint words vocabs sorting sets classes math alien urls
 splitting ascii combinators.short-circuit alarms words.symbol
-system ;
+system summary ;
 IN: tools.scaffold
 
 SYMBOL: developer-name
@@ -16,6 +16,10 @@ ERROR: not-a-vocab-root string ;
 ERROR: vocab-name-contains-separator path ;
 ERROR: vocab-name-contains-dot path ;
 ERROR: no-vocab vocab ;
+ERROR: bad-developer-name name ;
+
+M: bad-developer-name summary
+    drop "Developer name must be a string." ;
 
 <PRIVATE
 
@@ -101,10 +105,14 @@ ERROR: no-vocab vocab ;
     ] if ;
 
 : scaffold-authors ( vocab-root vocab -- )
-    "authors.txt" vocab-root/vocab/file>path scaffolding? [
-        [ developer-name get ] dip utf8 set-file-contents
+    developer-name get [
+        "authors.txt" vocab-root/vocab/file>path scaffolding? [
+            developer-name get swap utf8 set-file-contents
+        ] [
+            drop
+        ] if
     ] [
-        drop
+        2drop
     ] if ;
 
 : lookup-type ( string -- object/string ? )
@@ -298,9 +306,12 @@ SYMBOL: examples-flag
         "}" print
     ] with-variable ;
 
+: touch. ( path -- )
+    [ touch-file ]
+    [ "Click to edit: " write <pathname> . ] bi ;
+
 : scaffold-rc ( path -- )
-    [ home ] dip append-path
-    [ touch-file ] [ "Click to edit: " write <pathname> . ] bi ;
+    [ home ] dip append-path touch. ;
 
 : scaffold-factor-boot-rc ( -- )
     os windows? "factor-boot-rc" ".factor-boot-rc" ? scaffold-rc ;
@@ -308,4 +319,7 @@ SYMBOL: examples-flag
 : scaffold-factor-rc ( -- )
     os windows? "factor-rc" ".factor-rc" ? scaffold-rc ;
 
-: scaffold-emacs ( -- ) ".emacs" scaffold-rc ;
+
+HOOK: scaffold-emacs os ( -- )
+
+M: unix scaffold-emacs ( -- ) ".emacs" scaffold-rc ;
diff --git a/basis/tools/scaffold/windows/authors.txt b/basis/tools/scaffold/windows/authors.txt
new file mode 100755 (executable)
index 0000000..7c1b2f2
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
diff --git a/basis/tools/scaffold/windows/tags.txt b/basis/tools/scaffold/windows/tags.txt
new file mode 100644 (file)
index 0000000..6bf6830
--- /dev/null
@@ -0,0 +1 @@
+unportable
diff --git a/basis/tools/scaffold/windows/windows.factor b/basis/tools/scaffold/windows/windows.factor
new file mode 100755 (executable)
index 0000000..fef6121
--- /dev/null
@@ -0,0 +1,7 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: io.pathnames system tools.scaffold windows.shell32 ;
+IN: tools.scaffold.windows
+
+M: windows scaffold-emacs ( -- )
+    application-data ".emacs" append-path touch. ;
index 0d1d9f6fa187e1a04b84ebd106f9defe1ab1a098..65e87f976fc349987bfa7dd090cece07aa7b2d13 100644 (file)
@@ -1,24 +1,27 @@
 ! Copyright (C) 2003, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel math math.vectors memory io io.styles prettyprint
-namespaces system sequences splitting grouping assocs strings ;
+namespaces system sequences splitting grouping assocs strings
+generic.single combinators ;
 IN: tools.time
 
 : benchmark ( quot -- runtime )
     micros [ call micros ] dip - ; inline
 
-: time. ( data -- )
-    unclip
-    "==== RUNNING TIME" print nl 1000000 /f pprint " seconds" print nl
+: time. ( time -- )
+    "== Running time ==" print nl 1000000 /f pprint " seconds" print ;
+
+: gc-stats. ( stats -- )
     5 cut*
-    "==== GARBAGE COLLECTION" print nl
+    "== Garbage collection ==" print nl
+    "Times are in microseconds." print nl
     [
         6 group
         {
             "GC count:"
-            "Cumulative GC time (us):"
-            "Longest GC pause (us):"
-            "Average GC pause (us):"
+            "Total GC time:"
+            "Longest GC pause:"
+            "Average GC pause:"
             "Objects copied:"
             "Bytes copied:"
         } prefix
@@ -29,13 +32,43 @@ IN: tools.time
     [
         nl
         {
-            "Total GC time (us):"
+            "Total GC time:"
             "Cards scanned:"
             "Decks scanned:"
-            "Card scan time (us):"
+            "Card scan time:"
             "Code heap literal scans:"
         } swap zip simple-table.
     ] bi* ;
 
+: dispatch-stats. ( stats -- )
+    "== Megamorphic caches ==" print nl
+    { "Hits" "Misses" } swap zip simple-table. ;
+
+: inline-cache-stats. ( stats -- )
+    nl "== Polymorphic inline caches ==" print nl
+    3 cut
+    [
+        "Transitions:" print
+        { "Cold to monomorphic" "Mono to polymorphic" "Poly to megamorphic" } swap zip
+        simple-table. nl
+    ] [
+        "Type check stubs:" print
+        { "Tag only" "Hi-tag" "Tuple" "Hi-tag and tuple" } swap zip
+        simple-table.
+    ] bi* ;
+
 : time ( quot -- )
-    gc-reset micros [ call gc-stats micros ] dip - prefix time. ; inline
+    gc-reset
+    reset-dispatch-stats
+    reset-inline-cache-stats
+    benchmark gc-stats dispatch-stats inline-cache-stats
+    H{ { table-gap { 20 20 } } } [
+        [
+            [ [ time. ] 3dip ] with-cell
+            [ ] with-cell
+        ] with-row
+        [
+            [ [ gc-stats. ] 2dip ] with-cell
+            [ [ dispatch-stats. ] [ inline-cache-stats. ] bi* ] with-cell
+        ] with-row
+    ] tabular-output nl ; inline
index ba99a41eba02eacc79643a82f15ab95c8a881fbd..4b9a72a4439c7627104fe668d3a7f0850706c6da 100644 (file)
@@ -74,8 +74,6 @@ SYMBOL: failures
 \r
 SYMBOL: changed-vocabs\r
 \r
-[ f changed-vocabs set-global ] "tools.vocabs" add-init-hook\r
-\r
 : changed-vocab ( vocab -- )\r
     dup vocab changed-vocabs get and\r
     [ dup changed-vocabs get set-at ] [ drop ] if ;\r
@@ -287,3 +285,12 @@ MEMO: all-authors ( -- seq )
     \ all-vocabs-seq reset-memoized\r
     \ all-authors reset-memoized\r
     \ all-tags reset-memoized ;\r
+\r
+SINGLETON: cache-observer\r
+\r
+M: cache-observer vocabs-changed drop reset-cache ;\r
+\r
+[\r
+    f changed-vocabs set-global\r
+    cache-observer add-vocab-observer\r
+] "tools.vocabs" add-init-hook
\ No newline at end of file
index 6dabb73e30a0e9d0349259862fede157f168be3e..6f87792faa1e09d022bdfc6a64e06540b203d3ea 100644 (file)
@@ -1,7 +1,7 @@
 USING: tools.walker io io.streams.string kernel math
 math.private namespaces prettyprint sequences tools.test
 continuations math.parser threads arrays tools.walker.debug
-generic.standard sequences.private kernel.private
+generic.single sequences.private kernel.private
 tools.continuations accessors words ;
 IN: tools.walker.tests
 
@@ -118,7 +118,7 @@ IN: tools.walker.tests
 
 \ breakpoint-test don't-step-into
 
-[ f ] [ \ breakpoint-test optimized>> ] unit-test
+[ f ] [ \ breakpoint-test optimized? ] unit-test
 
 [ { 3 } ] [ [ breakpoint-test ] test-walker ] unit-test
 
diff --git a/basis/tuple-arrays/summary.txt b/basis/tuple-arrays/summary.txt
new file mode 100755 (executable)
index 0000000..6f5c8b7
--- /dev/null
@@ -0,0 +1 @@
+Efficient arrays of tuples with value semantics for elements
diff --git a/basis/tuple-arrays/tags.txt b/basis/tuple-arrays/tags.txt
new file mode 100755 (executable)
index 0000000..42d711b
--- /dev/null
@@ -0,0 +1 @@
+collections
index e405efb540d16f21ee39849e804d2c7c2a6690d8..76c0dc4e01fe04aee68ea5c49d0a705b8f403545 100755 (executable)
@@ -6,15 +6,19 @@ ui.gadgets ui.gadgets.private ui.backend ui.clipboards
 ui.gadgets.worlds ui.gestures ui.event-loop io kernel math
 math.vectors namespaces make sequences strings vectors words
 windows.kernel32 windows.gdi32 windows.user32 windows.opengl32
-windows.messages windows.types windows.offscreen windows.nt windows
+windows.messages windows.types windows.offscreen windows.nt
 threads libc combinators fry combinators.short-circuit continuations
 command-line shuffle opengl ui.render ascii math.bitwise locals
 accessors math.rectangles math.order ascii calendar
-io.encodings.utf16n ;
+io.encodings.utf16n windows.errors ;
 IN: ui.backend.windows
 
 SINGLETON: windows-ui-backend
 
+: lo-word ( wparam -- lo ) <short> *short ; inline
+: hi-word ( wparam -- hi ) -16 shift lo-word ; inline
+: >lo-hi ( WORD -- array ) [ lo-word ] [ hi-word ] bi 2array ;
+
 : crlf>lf ( str -- str' )
     CHAR: \r swap remove ;
 
@@ -286,8 +290,6 @@ SYMBOL: nc-buttons
     message>button nc-buttons get
     swap [ push ] [ delete ] if ;
 
-: >lo-hi ( WORD -- array ) [ lo-word ] [ hi-word ] bi 2array ;
-
 : mouse-wheel ( wParam -- array ) >lo-hi [ sgn neg ] map ;
 
 : mouse-event>gesture ( uMsg -- button )
@@ -553,6 +555,54 @@ M: windows-ui-backend (with-ui)
 M: windows-ui-backend beep ( -- )
     0 MessageBeep drop ;
 
+: fullscreen-RECT ( hwnd -- RECT )
+    MONITOR_DEFAULTTONEAREST MonitorFromWindow
+    "MONITORINFOEX" <c-object> dup length over set-MONITORINFOEX-cbSize
+    [ GetMonitorInfo win32-error=0/f ] keep MONITORINFOEX-rcMonitor ;
+
+: hwnd>RECT ( hwnd -- RECT )
+    "RECT" <c-object> [ GetWindowRect win32-error=0/f ] keep ;
+
+: fullscreen-flags ( -- n )
+    { WS_CAPTION WS_BORDER WS_THICKFRAME } flags ; inline
+
+: enter-fullscreen ( world -- )
+    handle>> hWnd>>
+    {
+        [
+            GWL_STYLE GetWindowLong
+            fullscreen-flags unmask
+        ]
+        [ GWL_STYLE rot SetWindowLong win32-error=0/f ]
+        [
+            HWND_TOP
+            over hwnd>RECT get-RECT-dimensions
+            SWP_FRAMECHANGED
+            SetWindowPos win32-error=0/f
+        ]
+        [ SW_MAXIMIZE ShowWindow win32-error=0/f ]
+    } cleave ;
+
+: exit-fullscreen ( world -- )
+    handle>> hWnd>>
+    {
+        [
+            GWL_STYLE GetWindowLong
+            fullscreen-flags bitor
+        ]
+        [ GWL_STYLE rot SetWindowLong win32-error=0/f ]
+        [
+            f
+            over hwnd>RECT get-RECT-dimensions
+            { SWP_NOMOVE SWP_NOSIZE SWP_NOZORDER SWP_FRAMECHANGED } flags
+            SetWindowPos win32-error=0/f
+        ]
+        [ SW_RESTORE ShowWindow win32-error=0/f ]
+    } cleave ;
+
+M: windows-ui-backend set-fullscreen* ( ? world -- )
+    swap [ enter-fullscreen ] [ exit-fullscreen ] if ;
+
 windows-ui-backend ui-backend set-global
 
 [ "ui.tools" ] main-vocab-hook set-global
index 6cfb83a49a87d31f70cc97e133a33fe44345a19a..80829d7b66b57ca8e105936789e2226475815fd3 100644 (file)
@@ -53,8 +53,8 @@ CONSTANT: min-thumb-dim 30
     [ slider-max* 1 max ]
     bi / ;
 
-: slider>screen ( m slider -- n ) slider-scale * elevator-padding + ;
-: screen>slider ( m slider -- n ) [ elevator-padding - ] dip slider-scale / ;
+: slider>screen ( m slider -- n ) slider-scale * ;
+: screen>slider ( m slider -- n ) slider-scale / ;
 
 M: slider model-changed nip elevator>> relayout-1 ;
 
@@ -133,7 +133,7 @@ elevator H{
         swap >>orientation ;
 
 : thumb-loc ( slider -- loc )
-    [ slider-value ] keep slider>screen ;
+    [ slider-value ] keep slider>screen elevator-padding + ;
 
 : layout-thumb-loc ( thumb slider -- )
     [ thumb-loc ] [ orientation>> ] bi n*v
index d390b1e49b097cf7ab1bb7319b5e12460535082c..ba3b5a2f789bba08637e2392e6ad49e02d80df14 100644 (file)
@@ -46,14 +46,16 @@ mouse-index
 { takes-focus? initial: t }
 focused? ;
 
-: <table> ( rows renderer -- table )
-    table new-line-gadget
+: new-table ( rows renderer class -- table )
+    new-line-gadget
         swap >>renderer
         swap >>model
         f <model> >>selected-value
         sans-serif-font >>font
         focus-border-color >>focus-border-color
-        transparent >>column-line-color ;
+        transparent >>column-line-color ; inline
+
+: <table> ( rows renderer -- table ) table new-table ;
 
 <PRIVATE
 
index c7db0839d7b08c0f8f139ffd5c25ccffe4a65b49..7e038ef2e0de6ece498911fc86f68350eaa24350 100644 (file)
@@ -310,16 +310,16 @@ HOOK: keysym>string os ( keysym -- string )
 
 M: macosx keysym>string >upper ;
 
-M: object keysym>string ;
+M: object keysym>string dup length 1 = [ >lower ] when ;
 
 M: key-down gesture>string
     [ mods>> ] [ sym>> ] bi
     {
         { [ dup { [ length 1 = ] [ first LETTER? ] } 1&& ] [ [ S+ prefix ] dip ] }
         { [ dup " " = ] [ drop "SPACE" ] }
-        [ keysym>string ]
+        [ ]
     } cond
-    [ modifiers>string ] dip append ;
+    [ modifiers>string ] [ keysym>string ] bi* append ;
 
 M: button-up gesture>string
     [
index a493d5d7d2d8cadd4f6c511b24e57715849116be..1b8af1dd031311aa9d5cbe26d398b84dc8faecc7 100644 (file)
@@ -25,7 +25,10 @@ M: browser-gadget set-history-value
 
 : show-help ( link browser-gadget -- )
     [ >link ] dip
-    [ [ add-recent ] [ history>> add-history ] bi* ]
+    [
+        2dup model>> value>> =
+        [ 2drop ] [ [ add-recent ] [ history>> add-history ] bi* ] if
+    ]
     [ model>> set-model ]
     2bi ;
 
index e581e72e24856a6cfd468756e6f4ea92e33fdcaf..95af20ec72e0ea519a75e9a708b7676ae036f1be 100644 (file)
@@ -7,7 +7,7 @@ IN: ui.tools.common
 
 SYMBOL: tool-dims
 
-tool-dims global [ H{ } clone or ] change-at
+tool-dims [ H{ } clone ] initialize
 
 TUPLE: tool < track ;
 
index aa23a8ebe18445b9ad4ab4dc0b9f5bcc5e48e006..704ae112e5ad65ffc07e647e18a49118d6ff0683 100644 (file)
@@ -10,7 +10,7 @@ ui.gadgets.tables ui.gadgets.labeled ui.gadgets.tracks ui.gestures
 ui.operations ui.tools.browser ui.tools.common ui.gadgets.scrollers
 ui.tools.inspector ui.gadgets.status-bar ui.operations
 ui.gadgets.buttons ui.gadgets.borders ui.gadgets.packs
-ui.gadgets.labels ui.baseline-alignment ui.images ui.tools.listener
+ui.gadgets.labels ui.baseline-alignment ui.images
 compiler.errors tools.errors tools.errors.model ;
 IN: ui.tools.error-list
 
index ba66121bc223cad84682107ce3e0c10a62527b36..fdba400c3df7e4af3bce116da4dce5073b035181 100644 (file)
@@ -3,11 +3,10 @@
 USING: accessors arrays assocs calendar colors colors.constants
 documents documents.elements fry kernel words sets splitting math
 math.vectors models.delay models.arrow combinators.short-circuit
-parser present sequences tools.completion help.vocabs generic
-generic.standard.engines.tuple fonts definitions.icons ui.images
-ui.commands ui.operations ui.gadgets ui.gadgets.editors
-ui.gadgets.glass ui.gadgets.scrollers ui.gadgets.tables
-ui.gadgets.tracks ui.gadgets.labeled
+parser present sequences tools.completion help.vocabs generic fonts
+definitions.icons ui.images ui.commands ui.operations ui.gadgets
+ui.gadgets.editors ui.gadgets.glass ui.gadgets.scrollers
+ui.gadgets.tables ui.gadgets.tracks ui.gadgets.labeled
 ui.gadgets.worlds ui.gadgets.wrappers ui.gestures ui.pens.solid
 ui.tools.listener.history combinators vocabs ui.tools.listener.popups ;
 IN: ui.tools.listener.completion
@@ -40,7 +39,7 @@ M: history-completion completion-quot drop '[ drop _ history-list ] ;
 
 GENERIC: completion-element ( completion-mode -- element )
 
-M: object completion-element drop one-word-elt ;
+M: object completion-element drop word-start-elt ;
 M: history-completion completion-element drop one-line-elt ;
 
 GENERIC: completion-banner ( completion-mode -- string )
@@ -73,13 +72,13 @@ M: vocab-completion row-color
     drop vocab? COLOR: black COLOR: dark-gray ? ;
 
 : complete-IN:/USE:? ( tokens -- ? )
-    2 short tail* { "IN:" "USE:" } intersects? ;
+    1 short head* 2 short tail* { "IN:" "USE:" } intersects? ;
 
 : chop-; ( seq -- seq' )
     { ";" } split1-last [ ] [ ] ?if ;
 
 : complete-USING:? ( tokens -- ? )
-    chop-; { "USING:" } intersects? ;
+    chop-; 1 short head* { "USING:" } intersects? ;
 
 : complete-CHAR:? ( tokens -- ? )
     2 short tail* "CHAR:" swap member? ;
@@ -120,8 +119,6 @@ M: object completion-string present ;
 
 M: method-body completion-string method-completion-string ;
 
-M: engine-word completion-string method-completion-string ;
-
 GENERIC# accept-completion-hook 1 ( item popup -- )
 
 : insert-completion ( item popup -- )
index 45b94344a6ff3e861d76818654fad1a403744bd8..e06e17374fa99e704e9364e00f9aa2fec8449dad 100644 (file)
@@ -75,7 +75,7 @@ CONSTANT: text "Hello world.\nThis is a test."
 [ ] [
     [
         "interactor" get register-self
-        "interactor" get contents "promise" get fulfill
+        "interactor" get stream-contents "promise" get fulfill
     ] in-thread
 ] unit-test
 
@@ -150,4 +150,4 @@ CONSTANT: text "Hello world.\nThis is a test."
 
 [ ] [ <listener-gadget> "l" set ] unit-test
 [ ] [ "l" get com-scroll-up ] unit-test
-[ ] [ "l" get com-scroll-down ] unit-test
\ No newline at end of file
+[ ] [ "l" get com-scroll-down ] unit-test
index 8be486cb1a32fc646f35aa7183d002dfb0974102..09403cb2d2784b9f619799d4dd711e263a8e7e6f 100644 (file)
@@ -28,7 +28,7 @@ SYMBOL: windows
     [ [ length 1- dup 1- ] keep exchange ] [ drop ] if ;
 
 : unregister-window ( handle -- )
-    windows global [ [ first = not ] with filter ] change-at ;
+    windows [ [ first = not ] with filter ] change-global ;
 
 : raised-window ( world -- )
     windows get-global
index a6a0147504240944bfaed396df148cf0c0ee5133..10fb2ad64fbf9fc8ca5ffc40e13ee3f85df8fc88 100644 (file)
@@ -194,6 +194,7 @@ FUNCTION: int setsockopt ( int s, int level, int optname, void* optval, socklen_
 FUNCTION: int setuid ( uid_t uid ) ;
 FUNCTION: int socket ( int domain, int type, int protocol ) ;
 FUNCTION: int symlink ( char* path1, char* path2 ) ;
+FUNCTION: int link ( char* path1, char* path2 ) ;
 FUNCTION: int system ( char* command ) ;
 
 FUNCTION: int unlink ( char* path ) ;
index 5b62f5479593d782352633acc034b5d322bcb13b..fd037cb2a01091380bfb660af49bdd0bff4983e8 100644 (file)
@@ -350,35 +350,46 @@ CONSTANT: TOKEN_ADJUST_DEFAULT         HEX: 0080
         TOKEN_ADJUST_DEFAULT
     } flags ; foldable
 
-CONSTANT: HKEY_CLASSES_ROOT       1
-CONSTANT: HKEY_CURRENT_CONFIG     2
-CONSTANT: HKEY_CURRENT_USER       3
-CONSTANT: HKEY_LOCAL_MACHINE      4
-CONSTANT: HKEY_USERS              5
-
-CONSTANT: KEY_ALL_ACCESS          HEX: 0001
-CONSTANT: KEY_CREATE_LINK         HEX: 0002
+CONSTANT: HKEY_CLASSES_ROOT        HEX: 80000000
+CONSTANT: HKEY_CURRENT_USER        HEX: 80000001
+CONSTANT: HKEY_LOCAL_MACHINE       HEX: 80000002
+CONSTANT: HKEY_USERS               HEX: 80000003
+CONSTANT: HKEY_PERFORMANCE_DATA    HEX: 80000004
+CONSTANT: HKEY_CURRENT_CONFIG      HEX: 80000005
+CONSTANT: HKEY_DYN_DATA            HEX: 80000006
+CONSTANT: HKEY_PERFORMANCE_TEXT    HEX: 80000050
+CONSTANT: HKEY_PERFORMANCE_NLSTEXT HEX: 80000060
+
+CONSTANT: KEY_QUERY_VALUE         HEX: 0001
+CONSTANT: KEY_SET_VALUE           HEX: 0002
 CONSTANT: KEY_CREATE_SUB_KEY      HEX: 0004
 CONSTANT: KEY_ENUMERATE_SUB_KEYS  HEX: 0008
-CONSTANT: KEY_EXECUTE             HEX: 0010
-CONSTANT: KEY_NOTIFY              HEX: 0020
-CONSTANT: KEY_QUERY_VALUE         HEX: 0040
-CONSTANT: KEY_READ                HEX: 0080
-CONSTANT: KEY_SET_VALUE           HEX: 0100
-CONSTANT: KEY_WOW64_64KEY         HEX: 0200
-CONSTANT: KEY_WOW64_32KEY         HEX: 0400
-CONSTANT: KEY_WRITE               HEX: 0800
-
-CONSTANT: REG_BINARY              1
-CONSTANT: REG_DWORD               2
-CONSTANT: REG_EXPAND_SZ           3
-CONSTANT: REG_MULTI_SZ            4
-CONSTANT: REG_QWORD               5
-CONSTANT: REG_SZ                  6
+CONSTANT: KEY_NOTIFY              HEX: 0010
+CONSTANT: KEY_CREATE_LINK         HEX: 0020
+CONSTANT: KEY_READ                HEX: 20019
+CONSTANT: KEY_WOW64_32KEY         HEX: 0200
+CONSTANT: KEY_WOW64_64KEY         HEX: 0100
+CONSTANT: KEY_WRITE               HEX: 20006
+CONSTANT: KEY_EXECUTE             KEY_READ
+CONSTANT: KEY_ALL_ACCESS          HEX: F003F
+
+CONSTANT: REG_NONE                         0
+CONSTANT: REG_SZ                           1
+CONSTANT: REG_EXPAND_SZ                    2
+CONSTANT: REG_BINARY                       3
+CONSTANT: REG_DWORD                        4
+CONSTANT: REG_DWORD_LITTLE_ENDIAN          4
+CONSTANT: REG_DWORD_BIG_ENDIAN             5
+CONSTANT: REG_LINK                         6
+CONSTANT: REG_MULTI_SZ                     7
+CONSTANT: REG_RESOURCE_LIST                8
+CONSTANT: REG_FULL_RESOURCE_DESCRIPTOR     9
+CONSTANT: REG_RESOURCE_REQUIREMENTS_LIST  10
+CONSTANT: REG_QWORD                       11
+CONSTANT: REG_QWORD_LITTLE_ENDIAN         11
 
 TYPEDEF: DWORD REGSAM
 
-
 ! : I_ScGetCurrentGroupStateW ;
 ! : A_SHAFinal ;
 ! : A_SHAInit ;
@@ -874,7 +885,7 @@ FUNCTION: BOOL OpenThreadToken ( HANDLE ThreadHandle, DWORD DesiredAccess, BOOL
 ! : ReadEncryptedFileRaw ;
 ! : ReadEventLogA ;
 ! : ReadEventLogW ;
-! : RegCloseKey ;
+FUNCTION: LONG RegCloseKey ( HKEY hKey ) ;
 ! : RegConnectRegistryA ;
 ! : RegConnectRegistryW ;
 ! : RegCreateKeyA ;
@@ -883,15 +894,52 @@ FUNCTION: LONG RegCreateKeyExW ( HKEY hKey, LPCTSTR lpSubKey, DWORD Reserved, LP
 ! : RegCreateKeyW
 ! : RegDeleteKeyA ;
 ! : RegDeleteKeyW ;
+
+FUNCTION: LONG RegDeleteKeyExW (
+        HKEY hKey,
+        LPCTSTR lpSubKey,
+        DWORD Reserved,
+        LPTSTR lpClass,
+        DWORD dwOptions,
+        REGSAM samDesired,
+        LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+        PHKEY phkResult,
+        LPDWORD lpdwDisposition
+    ) ;
+
+ALIAS: RegDeleteKeyEx RegDeleteKeyExW
+
 ! : RegDeleteValueA ;
 ! : RegDeleteValueW ;
 ! : RegDisablePredefinedCache ;
 ! : RegEnumKeyA ;
 ! : RegEnumKeyExA ;
-! : RegEnumKeyExW ;
+FUNCTION: LONG RegEnumKeyExW (
+        HKEY hKey,
+        DWORD dwIndex,
+        LPTSTR lpName,
+        LPDWORD lpcName,
+        LPDWORD lpReserved,
+        LPTSTR lpClass,
+        LPDWORD lpcClass,
+        PFILETIME lpftLastWriteTime
+    ) ;
 ! : RegEnumKeyW ;
 ! : RegEnumValueA ;
-! : RegEnumValueW ;
+
+FUNCTION: LONG RegEnumValueW (
+        HKEY hKey,
+        DWORD dwIndex,
+        LPTSTR lpValueName,
+        LPDWORD lpcchValueName,
+        LPDWORD lpReserved,
+        LPDWORD lpType,
+        LPBYTE lpData,
+        LPDWORD lpcbData
+    ) ;
+
+ALIAS: RegEnumValue RegEnumValueW
+
 ! : RegFlushKey ;
 ! : RegGetKeySecurity ;
 ! : RegLoadKeyA ;
@@ -900,17 +948,33 @@ FUNCTION: LONG RegCreateKeyExW ( HKEY hKey, LPCTSTR lpSubKey, DWORD Reserved, LP
 FUNCTION: LONG RegOpenCurrentUser ( REGSAM samDesired, PHKEY phkResult ) ;
 ! : RegOpenKeyA ;
 ! : RegOpenKeyExA ;
-! : RegOpenKeyExW ;
+FUNCTION: LONG RegOpenKeyExW ( HKEY hKey, LPCTSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult ) ;
+ALIAS: RegOpenKeyEx RegOpenKeyExW
 ! : RegOpenKeyW ;
 ! : RegOpenUserClassesRoot ;
 ! : RegOverridePredefKey ;
 ! : RegQueryInfoKeyA ;
-! : RegQueryInfoKeyW ;
+FUNCTION: LONG RegQueryInfoKeyW (
+        HKEY hKey,
+        LPTSTR lpClass,
+        LPDWORD lpcClass,
+        LPDWORD lpReserved,
+        LPDWORD lpcSubKeys,
+        LPDWORD lpcMaxSubKeyLen,
+        LPDWORD lpcMaxClassLen,
+        LPDWORD lpcValues,
+        LPDWORD lpcMaxValueNameLen,
+        LPDWORD lpcMaxValueLen,
+        LPDWORD lpcbSecurityDescriptor,
+        PFILETIME lpftLastWriteTime
+    ) ;
+ALIAS: RegQueryInfoKey RegQueryInfoKeyW
 ! : RegQueryMultipleValuesA ;
 ! : RegQueryMultipleValuesW ;
 ! : RegQueryValueA ;
 ! : RegQueryValueExA ;
-FUNCTION: LONG RegQueryValueExW ( HKEY hKey, LPCTSTR lpValueName, LPWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData ) ;
+FUNCTION: LONG RegQueryValueExW ( HKEY hKey, LPCTSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData ) ;
+ALIAS: RegQueryValueEx RegQueryValueExW
 ! : RegQueryValueW ;
 ! : RegReplaceKeyA ;
 ! : RegReplaceKeyW ;
index 0f95c6d6839560737d9f0d560f86768cfee5d8f7..74238abed2aa7681f0638906447c01c8846a7eae 100755 (executable)
@@ -842,7 +842,7 @@ SYMBOLS:
 [ define-constants ] "windows.dinput.constants" add-init-hook
 
 : uninitialize ( variable quot -- )
-    [ global ] dip '[ _ when* f ] change-at ; inline
+    '[ _ when* f ] change-global ; inline
 
 : free-dinput-constants ( -- )
     {
diff --git a/basis/windows/errors/errors-tests.factor b/basis/windows/errors/errors-tests.factor
new file mode 100755 (executable)
index 0000000..96edb8a
--- /dev/null
@@ -0,0 +1,6 @@
+! Copyright (C) 2009 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: tools.test windows.errors strings ;
+IN: windows.errors.tests
+
+[ t ] [ 0 n>win32-error-string string? ] unit-test
index 56bba768de9e39c8d65f223e7a0722e0148c2f48..e08704d46970102f21a3e48e639834417b1a13ec 100644 (file)
@@ -1,9 +1,752 @@
-IN: windows.errors 
-
-CONSTANT: ERROR_SUCCESS 0
-CONSTANT: ERROR_NO_MORE_FILES 18
-CONSTANT: ERROR_HANDLE_EOF 38
-CONSTANT: ERROR_BROKEN_PIPE 109
-CONSTANT: ERROR_ENVVAR_NOT_FOUND 203
-CONSTANT: ERROR_IO_INCOMPLETE 996
-CONSTANT: ERROR_IO_PENDING 997
+USING: alien.c-types kernel locals math math.bitwise
+windows.kernel32 sequences byte-arrays unicode.categories
+io.encodings.string io.encodings.utf16n alien.strings
+arrays ;
+IN: windows.errors
+
+CONSTANT: ERROR_SUCCESS                               0
+CONSTANT: ERROR_INVALID_FUNCTION                      1
+CONSTANT: ERROR_FILE_NOT_FOUND                        2
+CONSTANT: ERROR_PATH_NOT_FOUND                        3
+CONSTANT: ERROR_TOO_MANY_OPEN_FILES                   4
+CONSTANT: ERROR_ACCESS_DENIED                         5
+CONSTANT: ERROR_INVALID_HANDLE                        6
+CONSTANT: ERROR_ARENA_TRASHED                         7
+CONSTANT: ERROR_NOT_ENOUGH_MEMORY                     8
+CONSTANT: ERROR_INVALID_BLOCK                         9
+CONSTANT: ERROR_BAD_ENVIRONMENT                      10
+CONSTANT: ERROR_BAD_FORMAT                           11
+CONSTANT: ERROR_INVALID_ACCESS                       12
+CONSTANT: ERROR_INVALID_DATA                         13
+CONSTANT: ERROR_OUTOFMEMORY                          14
+CONSTANT: ERROR_INVALID_DRIVE                        15
+CONSTANT: ERROR_CURRENT_DIRECTORY                    16
+CONSTANT: ERROR_NOT_SAME_DEVICE                      17
+CONSTANT: ERROR_NO_MORE_FILES                        18
+CONSTANT: ERROR_WRITE_PROTECT                        19
+CONSTANT: ERROR_BAD_UNIT                             20
+CONSTANT: ERROR_NOT_READY                            21
+CONSTANT: ERROR_BAD_COMMAND                          22
+CONSTANT: ERROR_CRC                                  23
+CONSTANT: ERROR_BAD_LENGTH                           24
+CONSTANT: ERROR_SEEK                                 25
+CONSTANT: ERROR_NOT_DOS_DISK                         26
+CONSTANT: ERROR_SECTOR_NOT_FOUND                     27
+CONSTANT: ERROR_OUT_OF_PAPER                         28
+CONSTANT: ERROR_WRITE_FAULT                          29
+CONSTANT: ERROR_READ_FAULT                           30
+CONSTANT: ERROR_GEN_FAILURE                          31
+CONSTANT: ERROR_SHARING_VIOLATION                    32
+CONSTANT: ERROR_LOCK_VIOLATION                       33
+CONSTANT: ERROR_WRONG_DISK                           34
+CONSTANT: ERROR_SHARING_BUFFER_EXCEEDED              36
+CONSTANT: ERROR_HANDLE_EOF                           38
+CONSTANT: ERROR_HANDLE_DISK_FULL                     39
+CONSTANT: ERROR_NOT_SUPPORTED                        50
+CONSTANT: ERROR_REM_NOT_LIST                         51
+CONSTANT: ERROR_DUP_NAME                             52
+CONSTANT: ERROR_BAD_NETPATH                          53
+CONSTANT: ERROR_NETWORK_BUSY                         54
+CONSTANT: ERROR_DEV_NOT_EXIST                        55
+CONSTANT: ERROR_TOO_MANY_CMDS                        56
+CONSTANT: ERROR_ADAP_HDW_ERR                         57
+CONSTANT: ERROR_BAD_NET_RESP                         58
+CONSTANT: ERROR_UNEXP_NET_ERR                        59
+CONSTANT: ERROR_BAD_REM_ADAP                         60
+CONSTANT: ERROR_PRINTQ_FULL                          61
+CONSTANT: ERROR_NO_SPOOL_SPACE                       62
+CONSTANT: ERROR_PRINT_CANCELLED                      63
+CONSTANT: ERROR_NETNAME_DELETED                      64
+CONSTANT: ERROR_NETWORK_ACCESS_DENIED                65
+CONSTANT: ERROR_BAD_DEV_TYPE                         66
+CONSTANT: ERROR_BAD_NET_NAME                         67
+CONSTANT: ERROR_TOO_MANY_NAMES                       68
+CONSTANT: ERROR_TOO_MANY_SESS                        69
+CONSTANT: ERROR_SHARING_PAUSED                       70
+CONSTANT: ERROR_REQ_NOT_ACCEP                        71
+CONSTANT: ERROR_REDIR_PAUSED                         72
+CONSTANT: ERROR_FILE_EXISTS                          80
+CONSTANT: ERROR_CANNOT_MAKE                          82
+CONSTANT: ERROR_FAIL_I24                             83
+CONSTANT: ERROR_OUT_OF_STRUCTURES                    84
+CONSTANT: ERROR_ALREADY_ASSIGNED                     85
+CONSTANT: ERROR_INVALID_PASSWORD                     86
+CONSTANT: ERROR_INVALID_PARAMETER                    87
+CONSTANT: ERROR_NET_WRITE_FAULT                      88
+CONSTANT: ERROR_NO_PROC_SLOTS                        89
+CONSTANT: ERROR_TOO_MANY_SEMAPHORES                 100
+CONSTANT: ERROR_EXCL_SEM_ALREADY_OWNED              101
+CONSTANT: ERROR_SEM_IS_SET                          102
+CONSTANT: ERROR_TOO_MANY_SEM_REQUESTS               103
+CONSTANT: ERROR_INVALID_AT_INTERRUPT_TIME           104
+CONSTANT: ERROR_SEM_OWNER_DIED                      105
+CONSTANT: ERROR_SEM_USER_LIMIT                      106
+CONSTANT: ERROR_DISK_CHANGE                         107
+CONSTANT: ERROR_DRIVE_LOCKED                        108
+CONSTANT: ERROR_BROKEN_PIPE                         109
+CONSTANT: ERROR_OPEN_FAILED                         110
+CONSTANT: ERROR_BUFFER_OVERFLOW                     111
+CONSTANT: ERROR_DISK_FULL                           112
+CONSTANT: ERROR_NO_MORE_SEARCH_HANDLES              113
+CONSTANT: ERROR_INVALID_TARGET_HANDLE               114
+CONSTANT: ERROR_INVALID_CATEGORY                    117
+CONSTANT: ERROR_INVALID_VERIFY_SWITCH               118
+CONSTANT: ERROR_BAD_DRIVER_LEVEL                    119
+CONSTANT: ERROR_CALL_NOT_IMPLEMENTED                120
+CONSTANT: ERROR_SEM_TIMEOUT                         121
+CONSTANT: ERROR_INSUFFICIENT_BUFFER                 122
+CONSTANT: ERROR_INVALID_NAME                        123
+CONSTANT: ERROR_INVALID_LEVEL                       124
+CONSTANT: ERROR_NO_VOLUME_LABEL                     125
+CONSTANT: ERROR_MOD_NOT_FOUND                       126
+CONSTANT: ERROR_PROC_NOT_FOUND                      127
+CONSTANT: ERROR_WAIT_NO_CHILDREN                    128
+CONSTANT: ERROR_CHILD_NOT_COMPLETE                  129
+CONSTANT: ERROR_DIRECT_ACCESS_HANDLE                130
+CONSTANT: ERROR_NEGATIVE_SEEK                       131
+CONSTANT: ERROR_SEEK_ON_DEVICE                      132
+CONSTANT: ERROR_IS_JOIN_TARGET                      133
+CONSTANT: ERROR_IS_JOINED                           134
+CONSTANT: ERROR_IS_SUBSTED                          135
+CONSTANT: ERROR_NOT_JOINED                          136
+CONSTANT: ERROR_NOT_SUBSTED                         137
+CONSTANT: ERROR_JOIN_TO_JOIN                        138
+CONSTANT: ERROR_SUBST_TO_SUBST                      139
+CONSTANT: ERROR_JOIN_TO_SUBST                       140
+CONSTANT: ERROR_SUBST_TO_JOIN                       141
+CONSTANT: ERROR_BUSY_DRIVE                          142
+CONSTANT: ERROR_SAME_DRIVE                          143
+CONSTANT: ERROR_DIR_NOT_ROOT                        144
+CONSTANT: ERROR_DIR_NOT_EMPTY                       145
+CONSTANT: ERROR_IS_SUBST_PATH                       146
+CONSTANT: ERROR_IS_JOIN_PATH                        147
+CONSTANT: ERROR_PATH_BUSY                           148
+CONSTANT: ERROR_IS_SUBST_TARGET                     149
+CONSTANT: ERROR_SYSTEM_TRACE                        150
+CONSTANT: ERROR_INVALID_EVENT_COUNT                 151
+CONSTANT: ERROR_TOO_MANY_MUXWAITERS                 152
+CONSTANT: ERROR_INVALID_LIST_FORMAT                 153
+CONSTANT: ERROR_LABEL_TOO_LONG                      154
+CONSTANT: ERROR_TOO_MANY_TCBS                       155
+CONSTANT: ERROR_SIGNAL_REFUSED                      156
+CONSTANT: ERROR_DISCARDED                           157
+CONSTANT: ERROR_NOT_LOCKED                          158
+CONSTANT: ERROR_BAD_THREADID_ADDR                   159
+CONSTANT: ERROR_BAD_ARGUMENTS                       160
+CONSTANT: ERROR_BAD_PATHNAME                        161
+CONSTANT: ERROR_SIGNAL_PENDING                      162
+CONSTANT: ERROR_MAX_THRDS_REACHED                   164
+CONSTANT: ERROR_LOCK_FAILED                         167
+CONSTANT: ERROR_BUSY                                170
+CONSTANT: ERROR_CANCEL_VIOLATION                    173
+CONSTANT: ERROR_ATOMIC_LOCKS_NOT_SUPPORTED          174
+CONSTANT: ERROR_INVALID_SEGMENT_NUMBER              180
+CONSTANT: ERROR_INVALID_ORDINAL                     182
+CONSTANT: ERROR_ALREADY_EXISTS                      183
+CONSTANT: ERROR_INVALID_FLAG_NUMBER                 186
+CONSTANT: ERROR_SEM_NOT_FOUND                       187
+CONSTANT: ERROR_INVALID_STARTING_CODESEG            188
+CONSTANT: ERROR_INVALID_STACKSEG                    189
+CONSTANT: ERROR_INVALID_MODULETYPE                  190
+CONSTANT: ERROR_INVALID_EXE_SIGNATURE               191
+CONSTANT: ERROR_EXE_MARKED_INVALID                  192
+CONSTANT: ERROR_BAD_EXE_FORMAT                      193
+CONSTANT: ERROR_ITERATED_DATA_EXCEEDS_64k           194
+CONSTANT: ERROR_INVALID_MINALLOCSIZE                195
+CONSTANT: ERROR_DYNLINK_FROM_INVALID_RING           196
+CONSTANT: ERROR_IOPL_NOT_ENABLED                    197
+CONSTANT: ERROR_INVALID_SEGDPL                      198
+CONSTANT: ERROR_AUTODATASEG_EXCEEDS_64k             199
+CONSTANT: ERROR_RING2SEG_MUST_BE_MOVABLE            200
+CONSTANT: ERROR_RELOC_CHAIN_XEEDS_SEGLIM            201
+CONSTANT: ERROR_INFLOOP_IN_RELOC_CHAIN              202
+CONSTANT: ERROR_ENVVAR_NOT_FOUND                    203
+CONSTANT: ERROR_NO_SIGNAL_SENT                      205
+CONSTANT: ERROR_FILENAME_EXCED_RANGE                206
+CONSTANT: ERROR_RING2_STACK_IN_USE                  207
+CONSTANT: ERROR_META_EXPANSION_TOO_LONG             208
+CONSTANT: ERROR_INVALID_SIGNAL_NUMBER               209
+CONSTANT: ERROR_THREAD_1_INACTIVE                   210
+CONSTANT: ERROR_LOCKED                              212
+CONSTANT: ERROR_TOO_MANY_MODULES                    214
+CONSTANT: ERROR_NESTING_NOT_ALLOWED                 215
+CONSTANT: ERROR_EXE_MACHINE_TYPE_MISMATCH           216
+CONSTANT: ERROR_BAD_PIPE                            230
+CONSTANT: ERROR_PIPE_BUSY                           231
+CONSTANT: ERROR_NO_DATA                             232
+CONSTANT: ERROR_PIPE_NOT_CONNECTED                  233
+CONSTANT: ERROR_MORE_DATA                           234
+CONSTANT: ERROR_VC_DISCONNECTED                     240
+CONSTANT: ERROR_INVALID_EA_NAME                     254
+CONSTANT: ERROR_EA_LIST_INCONSISTENT                255
+CONSTANT: ERROR_NO_MORE_ITEMS                       259
+CONSTANT: ERROR_CANNOT_COPY                         266
+CONSTANT: ERROR_DIRECTORY                           267
+CONSTANT: ERROR_EAS_DIDNT_FIT                       275
+CONSTANT: ERROR_EA_FILE_CORRUPT                     276
+CONSTANT: ERROR_EA_TABLE_FULL                       277
+CONSTANT: ERROR_INVALID_EA_HANDLE                   278
+CONSTANT: ERROR_EAS_NOT_SUPPORTED                   282
+CONSTANT: ERROR_NOT_OWNER                           288
+CONSTANT: ERROR_TOO_MANY_POSTS                      298
+CONSTANT: ERROR_PARTIAL_COPY                        299
+CONSTANT: ERROR_MR_MID_NOT_FOUND                    317
+CONSTANT: ERROR_INVALID_ADDRESS                     487
+CONSTANT: ERROR_ARITHMETIC_OVERFLOW                 534
+CONSTANT: ERROR_PIPE_CONNECTED                      535
+CONSTANT: ERROR_PIPE_LISTENING                      536
+CONSTANT: ERROR_EA_ACCESS_DENIED                    994
+CONSTANT: ERROR_OPERATION_ABORTED                   995
+CONSTANT: ERROR_IO_INCOMPLETE                       996
+CONSTANT: ERROR_IO_PENDING                          997
+CONSTANT: ERROR_NOACCESS                            998
+CONSTANT: ERROR_SWAPERROR                           999
+CONSTANT: ERROR_STACK_OVERFLOW                     1001
+CONSTANT: ERROR_INVALID_MESSAGE                    1002
+CONSTANT: ERROR_CAN_NOT_COMPLETE                   1003
+CONSTANT: ERROR_INVALID_FLAGS                      1004
+CONSTANT: ERROR_UNRECOGNIZED_VOLUME                1005
+CONSTANT: ERROR_FILE_INVALID                       1006
+CONSTANT: ERROR_FULLSCREEN_MODE                    1007
+CONSTANT: ERROR_NO_TOKEN                           1008
+CONSTANT: ERROR_BADDB                              1009
+CONSTANT: ERROR_BADKEY                             1010
+CONSTANT: ERROR_CANTOPEN                           1011
+CONSTANT: ERROR_CANTREAD                           1012
+CONSTANT: ERROR_CANTWRITE                          1013
+CONSTANT: ERROR_REGISTRY_RECOVERED                 1014
+CONSTANT: ERROR_REGISTRY_CORRUPT                   1015
+CONSTANT: ERROR_REGISTRY_IO_FAILED                 1016
+CONSTANT: ERROR_NOT_REGISTRY_FILE                  1017
+CONSTANT: ERROR_KEY_DELETED                        1018
+CONSTANT: ERROR_NO_LOG_SPACE                       1019
+CONSTANT: ERROR_KEY_HAS_CHILDREN                   1020
+CONSTANT: ERROR_CHILD_MUST_BE_VOLATILE             1021
+CONSTANT: ERROR_NOTIFY_ENUM_DIR                    1022
+CONSTANT: ERROR_DEPENDENT_SERVICES_RUNNING         1051
+CONSTANT: ERROR_INVALID_SERVICE_CONTROL            1052
+CONSTANT: ERROR_SERVICE_REQUEST_TIMEOUT            1053
+CONSTANT: ERROR_SERVICE_NO_THREAD                  1054
+CONSTANT: ERROR_SERVICE_DATABASE_LOCKED            1055
+CONSTANT: ERROR_SERVICE_ALREADY_RUNNING            1056
+CONSTANT: ERROR_INVALID_SERVICE_ACCOUNT            1057
+CONSTANT: ERROR_SERVICE_DISABLED                   1058
+CONSTANT: ERROR_CIRCULAR_DEPENDENCY                1059
+CONSTANT: ERROR_SERVICE_DOES_NOT_EXIST             1060
+CONSTANT: ERROR_SERVICE_CANNOT_ACCEPT_CTRL         1061
+CONSTANT: ERROR_SERVICE_NOT_ACTIVE                 1062
+CONSTANT: ERROR_FAILED_SERVICE_CONTROLLER_CONNECT  1063
+CONSTANT: ERROR_EXCEPTION_IN_SERVICE               1064
+CONSTANT: ERROR_DATABASE_DOES_NOT_EXIST            1065
+CONSTANT: ERROR_SERVICE_SPECIFIC_ERROR             1066
+CONSTANT: ERROR_PROCESS_ABORTED                    1067
+CONSTANT: ERROR_SERVICE_DEPENDENCY_FAIL            1068
+CONSTANT: ERROR_SERVICE_LOGON_FAILED               1069
+CONSTANT: ERROR_SERVICE_START_HANG                 1070
+CONSTANT: ERROR_INVALID_SERVICE_LOCK               1071
+CONSTANT: ERROR_SERVICE_MARKED_FOR_DELETE          1072
+CONSTANT: ERROR_SERVICE_EXISTS                     1073
+CONSTANT: ERROR_ALREADY_RUNNING_LKG                1074
+CONSTANT: ERROR_SERVICE_DEPENDENCY_DELETED         1075
+CONSTANT: ERROR_BOOT_ALREADY_ACCEPTED              1076
+CONSTANT: ERROR_SERVICE_NEVER_STARTED              1077
+CONSTANT: ERROR_DUPLICATE_SERVICE_NAME             1078
+CONSTANT: ERROR_DIFFERENT_SERVICE_ACCOUNT          1079
+CONSTANT: ERROR_END_OF_MEDIA                       1100
+CONSTANT: ERROR_FILEMARK_DETECTED                  1101
+CONSTANT: ERROR_BEGINNING_OF_MEDIA                 1102
+CONSTANT: ERROR_SETMARK_DETECTED                   1103
+CONSTANT: ERROR_NO_DATA_DETECTED                   1104
+CONSTANT: ERROR_PARTITION_FAILURE                  1105
+CONSTANT: ERROR_INVALID_BLOCK_LENGTH               1106
+CONSTANT: ERROR_DEVICE_NOT_PARTITIONED             1107
+CONSTANT: ERROR_UNABLE_TO_LOCK_MEDIA               1108
+CONSTANT: ERROR_UNABLE_TO_UNLOAD_MEDIA             1109
+CONSTANT: ERROR_MEDIA_CHANGED                      1110
+CONSTANT: ERROR_BUS_RESET                          1111
+CONSTANT: ERROR_NO_MEDIA_IN_DRIVE                  1112
+CONSTANT: ERROR_NO_UNICODE_TRANSLATION             1113
+CONSTANT: ERROR_DLL_INIT_FAILED                    1114
+CONSTANT: ERROR_SHUTDOWN_IN_PROGRESS               1115
+CONSTANT: ERROR_NO_SHUTDOWN_IN_PROGRESS            1116
+CONSTANT: ERROR_IO_DEVICE                          1117
+CONSTANT: ERROR_SERIAL_NO_DEVICE                   1118
+CONSTANT: ERROR_IRQ_BUSY                           1119
+CONSTANT: ERROR_MORE_WRITES                        1120
+CONSTANT: ERROR_COUNTER_TIMEOUT                    1121
+CONSTANT: ERROR_FLOPPY_ID_MARK_NOT_FOUND           1122
+CONSTANT: ERROR_FLOPPY_WRONG_CYLINDER              1123
+CONSTANT: ERROR_FLOPPY_UNKNOWN_ERROR               1124
+CONSTANT: ERROR_FLOPPY_BAD_REGISTERS               1125
+CONSTANT: ERROR_DISK_RECALIBRATE_FAILED            1126
+CONSTANT: ERROR_DISK_OPERATION_FAILED              1127
+CONSTANT: ERROR_DISK_RESET_FAILED                  1128
+CONSTANT: ERROR_EOM_OVERFLOW                       1129
+CONSTANT: ERROR_NOT_ENOUGH_SERVER_MEMORY           1130
+CONSTANT: ERROR_POSSIBLE_DEADLOCK                  1131
+CONSTANT: ERROR_MAPPED_ALIGNMENT                   1132
+CONSTANT: ERROR_SET_POWER_STATE_VETOED             1140
+CONSTANT: ERROR_SET_POWER_STATE_FAILED             1141
+CONSTANT: ERROR_TOO_MANY_LINKS                     1142
+CONSTANT: ERROR_OLD_WIN_VERSION                    1150
+CONSTANT: ERROR_APP_WRONG_OS                       1151
+CONSTANT: ERROR_SINGLE_INSTANCE_APP                1152
+CONSTANT: ERROR_RMODE_APP                          1153
+CONSTANT: ERROR_INVALID_DLL                        1154
+CONSTANT: ERROR_NO_ASSOCIATION                     1155
+CONSTANT: ERROR_DDE_FAIL                           1156
+CONSTANT: ERROR_DLL_NOT_FOUND                      1157
+CONSTANT: ERROR_BAD_DEVICE                         1200
+CONSTANT: ERROR_CONNECTION_UNAVAIL                 1201
+CONSTANT: ERROR_DEVICE_ALREADY_REMEMBERED          1202
+CONSTANT: ERROR_NO_NET_OR_BAD_PATH                 1203
+CONSTANT: ERROR_BAD_PROVIDER                       1204
+CONSTANT: ERROR_CANNOT_OPEN_PROFILE                1205
+CONSTANT: ERROR_BAD_PROFILE                        1206
+CONSTANT: ERROR_NOT_CONTAINER                      1207
+CONSTANT: ERROR_EXTENDED_ERROR                     1208
+CONSTANT: ERROR_INVALID_GROUPNAME                  1209
+CONSTANT: ERROR_INVALID_COMPUTERNAME               1210
+CONSTANT: ERROR_INVALID_EVENTNAME                  1211
+CONSTANT: ERROR_INVALID_DOMAINNAME                 1212
+CONSTANT: ERROR_INVALID_SERVICENAME                1213
+CONSTANT: ERROR_INVALID_NETNAME                    1214
+CONSTANT: ERROR_INVALID_SHARENAME                  1215
+CONSTANT: ERROR_INVALID_PASSWORDNAME               1216
+CONSTANT: ERROR_INVALID_MESSAGENAME                1217
+CONSTANT: ERROR_INVALID_MESSAGEDEST                1218
+CONSTANT: ERROR_SESSION_CREDENTIAL_CONFLICT        1219
+CONSTANT: ERROR_REMOTE_SESSION_LIMIT_EXCEEDED      1220
+CONSTANT: ERROR_DUP_DOMAINNAME                     1221
+CONSTANT: ERROR_NO_NETWORK                         1222
+CONSTANT: ERROR_CANCELLED                          1223
+CONSTANT: ERROR_USER_MAPPED_FILE                   1224
+CONSTANT: ERROR_CONNECTION_REFUSED                 1225
+CONSTANT: ERROR_GRACEFUL_DISCONNECT                1226
+CONSTANT: ERROR_ADDRESS_ALREADY_ASSOCIATED         1227
+CONSTANT: ERROR_ADDRESS_NOT_ASSOCIATED             1228
+CONSTANT: ERROR_CONNECTION_INVALID                 1229
+CONSTANT: ERROR_CONNECTION_ACTIVE                  1230
+CONSTANT: ERROR_NETWORK_UNREACHABLE                1231
+CONSTANT: ERROR_HOST_UNREACHABLE                   1232
+CONSTANT: ERROR_PROTOCOL_UNREACHABLE               1233
+CONSTANT: ERROR_PORT_UNREACHABLE                   1234
+CONSTANT: ERROR_REQUEST_ABORTED                    1235
+CONSTANT: ERROR_CONNECTION_ABORTED                 1236
+CONSTANT: ERROR_RETRY                              1237
+CONSTANT: ERROR_CONNECTION_COUNT_LIMIT             1238
+CONSTANT: ERROR_LOGIN_TIME_RESTRICTION             1239
+CONSTANT: ERROR_LOGIN_WKSTA_RESTRICTION            1240
+CONSTANT: ERROR_INCORRECT_ADDRESS                  1241
+CONSTANT: ERROR_ALREADY_REGISTERED                 1242
+CONSTANT: ERROR_SERVICE_NOT_FOUND                  1243
+CONSTANT: ERROR_NOT_AUTHENTICATED                  1244
+CONSTANT: ERROR_NOT_LOGGED_ON                      1245
+CONSTANT: ERROR_CONTINUE                           1246
+CONSTANT: ERROR_ALREADY_INITIALIZED                1247
+CONSTANT: ERROR_NO_MORE_DEVICES                    1248
+CONSTANT: ERROR_NOT_ALL_ASSIGNED                   1300
+CONSTANT: ERROR_SOME_NOT_MAPPED                    1301
+CONSTANT: ERROR_NO_QUOTAS_FOR_ACCOUNT              1302
+CONSTANT: ERROR_LOCAL_USER_SESSION_KEY             1303
+CONSTANT: ERROR_NULL_LM_PASSWORD                   1304
+CONSTANT: ERROR_UNKNOWN_REVISION                   1305
+CONSTANT: ERROR_REVISION_MISMATCH                  1306
+CONSTANT: ERROR_INVALID_OWNER                      1307
+CONSTANT: ERROR_INVALID_PRIMARY_GROUP              1308
+CONSTANT: ERROR_NO_IMPERSONATION_TOKEN             1309
+CONSTANT: ERROR_CANT_DISABLE_MANDATORY             1310
+CONSTANT: ERROR_NO_LOGON_SERVERS                   1311
+CONSTANT: ERROR_NO_SUCH_LOGON_SESSION              1312
+CONSTANT: ERROR_NO_SUCH_PRIVILEGE                  1313
+CONSTANT: ERROR_PRIVILEGE_NOT_HELD                 1314
+CONSTANT: ERROR_INVALID_ACCOUNT_NAME               1315
+CONSTANT: ERROR_USER_EXISTS                        1316
+CONSTANT: ERROR_NO_SUCH_USER                       1317
+CONSTANT: ERROR_GROUP_EXISTS                       1318
+CONSTANT: ERROR_NO_SUCH_GROUP                      1319
+CONSTANT: ERROR_MEMBER_IN_GROUP                    1320
+CONSTANT: ERROR_MEMBER_NOT_IN_GROUP                1321
+CONSTANT: ERROR_LAST_ADMIN                         1322
+CONSTANT: ERROR_WRONG_PASSWORD                     1323
+CONSTANT: ERROR_ILL_FORMED_PASSWORD                1324
+CONSTANT: ERROR_PASSWORD_RESTRICTION               1325
+CONSTANT: ERROR_LOGON_FAILURE                      1326
+CONSTANT: ERROR_ACCOUNT_RESTRICTION                1327
+CONSTANT: ERROR_INVALID_LOGON_HOURS                1328
+CONSTANT: ERROR_INVALID_WORKSTATION                1329
+CONSTANT: ERROR_PASSWORD_EXPIRED                   1330
+CONSTANT: ERROR_ACCOUNT_DISABLED                   1331
+CONSTANT: ERROR_NONE_MAPPED                        1332
+CONSTANT: ERROR_TOO_MANY_LUIDS_REQUESTED           1333
+CONSTANT: ERROR_LUIDS_EXHAUSTED                    1334
+CONSTANT: ERROR_INVALID_SUB_AUTHORITY              1335
+CONSTANT: ERROR_INVALID_ACL                        1336
+CONSTANT: ERROR_INVALID_SID                        1337
+CONSTANT: ERROR_INVALID_SECURITY_DESCR             1338
+CONSTANT: ERROR_BAD_INHERITANCE_ACL                1340
+CONSTANT: ERROR_SERVER_DISABLED                    1341
+CONSTANT: ERROR_SERVER_NOT_DISABLED                1342
+CONSTANT: ERROR_INVALID_ID_AUTHORITY               1343
+CONSTANT: ERROR_ALLOTTED_SPACE_EXCEEDED            1344
+CONSTANT: ERROR_INVALID_GROUP_ATTRIBUTES           1345
+CONSTANT: ERROR_BAD_IMPERSONATION_LEVEL            1346
+CONSTANT: ERROR_CANT_OPEN_ANONYMOUS                1347
+CONSTANT: ERROR_BAD_VALIDATION_CLASS               1348
+CONSTANT: ERROR_BAD_TOKEN_TYPE                     1349
+CONSTANT: ERROR_NO_SECURITY_ON_OBJECT              1350
+CONSTANT: ERROR_CANT_ACCESS_DOMAIN_INFO            1351
+CONSTANT: ERROR_INVALID_SERVER_STATE               1352
+CONSTANT: ERROR_INVALID_DOMAIN_STATE               1353
+CONSTANT: ERROR_INVALID_DOMAIN_ROLE                1354
+CONSTANT: ERROR_NO_SUCH_DOMAIN                     1355
+CONSTANT: ERROR_DOMAIN_EXISTS                      1356
+CONSTANT: ERROR_DOMAIN_LIMIT_EXCEEDED              1357
+CONSTANT: ERROR_INTERNAL_DB_CORRUPTION             1358
+CONSTANT: ERROR_INTERNAL_ERROR                     1359
+CONSTANT: ERROR_GENERIC_NOT_MAPPED                 1360
+CONSTANT: ERROR_BAD_DESCRIPTOR_FORMAT              1361
+CONSTANT: ERROR_NOT_LOGON_PROCESS                  1362
+CONSTANT: ERROR_LOGON_SESSION_EXISTS               1363
+CONSTANT: ERROR_NO_SUCH_PACKAGE                    1364
+CONSTANT: ERROR_BAD_LOGON_SESSION_STATE            1365
+CONSTANT: ERROR_LOGON_SESSION_COLLISION            1366
+CONSTANT: ERROR_INVALID_LOGON_TYPE                 1367
+CONSTANT: ERROR_CANNOT_IMPERSONATE                 1368
+CONSTANT: ERROR_RXACT_INVALID_STATE                1369
+CONSTANT: ERROR_RXACT_COMMIT_FAILURE               1370
+CONSTANT: ERROR_SPECIAL_ACCOUNT                    1371
+CONSTANT: ERROR_SPECIAL_GROUP                      1372
+CONSTANT: ERROR_SPECIAL_USER                       1373
+CONSTANT: ERROR_MEMBERS_PRIMARY_GROUP              1374
+CONSTANT: ERROR_TOKEN_ALREADY_IN_USE               1375
+CONSTANT: ERROR_NO_SUCH_ALIAS                      1376
+CONSTANT: ERROR_MEMBER_NOT_IN_ALIAS                1377
+CONSTANT: ERROR_MEMBER_IN_ALIAS                    1378
+CONSTANT: ERROR_ALIAS_EXISTS                       1379
+CONSTANT: ERROR_LOGON_NOT_GRANTED                  1380
+CONSTANT: ERROR_TOO_MANY_SECRETS                   1381
+CONSTANT: ERROR_SECRET_TOO_LONG                    1382
+CONSTANT: ERROR_INTERNAL_DB_ERROR                  1383
+CONSTANT: ERROR_TOO_MANY_CONTEXT_IDS               1384
+CONSTANT: ERROR_LOGON_TYPE_NOT_GRANTED             1385
+CONSTANT: ERROR_NT_CROSS_ENCRYPTION_REQUIRED       1386
+CONSTANT: ERROR_NO_SUCH_MEMBER                     1387
+CONSTANT: ERROR_INVALID_MEMBER                     1388
+CONSTANT: ERROR_TOO_MANY_SIDS                      1389
+CONSTANT: ERROR_LM_CROSS_ENCRYPTION_REQUIRED       1390
+CONSTANT: ERROR_NO_INHERITANCE                     1391
+CONSTANT: ERROR_FILE_CORRUPT                       1392
+CONSTANT: ERROR_DISK_CORRUPT                       1393
+CONSTANT: ERROR_NO_USER_SESSION_KEY                1394
+CONSTANT: ERROR_LICENSE_QUOTA_EXCEEDED             1395
+CONSTANT: ERROR_INVALID_WINDOW_HANDLE              1400
+CONSTANT: ERROR_INVALID_MENU_HANDLE                1401
+CONSTANT: ERROR_INVALID_CURSOR_HANDLE              1402
+CONSTANT: ERROR_INVALID_ACCEL_HANDLE               1403
+CONSTANT: ERROR_INVALID_HOOK_HANDLE                1404
+CONSTANT: ERROR_INVALID_DWP_HANDLE                 1405
+CONSTANT: ERROR_TLW_WITH_WSCHILD                   1406
+CONSTANT: ERROR_CANNOT_FIND_WND_CLASS              1407
+CONSTANT: ERROR_WINDOW_OF_OTHER_THREAD             1408
+CONSTANT: ERROR_HOTKEY_ALREADY_REGISTERED          1409
+CONSTANT: ERROR_CLASS_ALREADY_EXISTS               1410
+CONSTANT: ERROR_CLASS_DOES_NOT_EXIST               1411
+CONSTANT: ERROR_CLASS_HAS_WINDOWS                  1412
+CONSTANT: ERROR_INVALID_INDEX                      1413
+CONSTANT: ERROR_INVALID_ICON_HANDLE                1414
+CONSTANT: ERROR_PRIVATE_DIALOG_INDEX               1415
+CONSTANT: ERROR_LISTBOX_ID_NOT_FOUND               1416
+CONSTANT: ERROR_NO_WILDCARD_CHARACTERS             1417
+CONSTANT: ERROR_CLIPBOARD_NOT_OPEN                 1418
+CONSTANT: ERROR_HOTKEY_NOT_REGISTERED              1419
+CONSTANT: ERROR_WINDOW_NOT_DIALOG                  1420
+CONSTANT: ERROR_CONTROL_ID_NOT_FOUND               1421
+CONSTANT: ERROR_INVALID_COMBOBOX_MESSAGE           1422
+CONSTANT: ERROR_WINDOW_NOT_COMBOBOX                1423
+CONSTANT: ERROR_INVALID_EDIT_HEIGHT                1424
+CONSTANT: ERROR_DC_NOT_FOUND                       1425
+CONSTANT: ERROR_INVALID_HOOK_FILTER                1426
+CONSTANT: ERROR_INVALID_FILTER_PROC                1427
+CONSTANT: ERROR_HOOK_NEEDS_HMOD                    1428
+CONSTANT: ERROR_GLOBAL_ONLY_HOOK                   1429
+CONSTANT: ERROR_JOURNAL_HOOK_SET                   1430
+CONSTANT: ERROR_HOOK_NOT_INSTALLED                 1431
+CONSTANT: ERROR_INVALID_LB_MESSAGE                 1432
+CONSTANT: ERROR_LB_WITHOUT_TABSTOPS                1434
+CONSTANT: ERROR_DESTROY_OBJECT_OF_OTHER_THREAD     1435
+CONSTANT: ERROR_CHILD_WINDOW_MENU                  1436
+CONSTANT: ERROR_NO_SYSTEM_MENU                     1437
+CONSTANT: ERROR_INVALID_MSGBOX_STYLE               1438
+CONSTANT: ERROR_INVALID_SPI_VALUE                  1439
+CONSTANT: ERROR_SCREEN_ALREADY_LOCKED              1440
+CONSTANT: ERROR_HWNDS_HAVE_DIFF_PARENT             1441
+CONSTANT: ERROR_NOT_CHILD_WINDOW                   1442
+CONSTANT: ERROR_INVALID_GW_COMMAND                 1443
+CONSTANT: ERROR_INVALID_THREAD_ID                  1444
+CONSTANT: ERROR_NON_MDICHILD_WINDOW                1445
+CONSTANT: ERROR_POPUP_ALREADY_ACTIVE               1446
+CONSTANT: ERROR_NO_SCROLLBARS                      1447
+CONSTANT: ERROR_INVALID_SCROLLBAR_RANGE            1448
+CONSTANT: ERROR_INVALID_SHOWWIN_COMMAND            1449
+CONSTANT: ERROR_NO_SYSTEM_RESOURCES                1450
+CONSTANT: ERROR_NONPAGED_SYSTEM_RESOURCES          1451
+CONSTANT: ERROR_PAGED_SYSTEM_RESOURCES             1452
+CONSTANT: ERROR_WORKING_SET_QUOTA                  1453
+CONSTANT: ERROR_PAGEFILE_QUOTA                     1454
+CONSTANT: ERROR_COMMITMENT_LIMIT                   1455
+CONSTANT: ERROR_MENU_ITEM_NOT_FOUND                1456
+CONSTANT: ERROR_INVALID_KEYBOARD_HANDLE            1457
+CONSTANT: ERROR_HOOK_TYPE_NOT_ALLOWED              1458
+CONSTANT: ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION 1459
+CONSTANT: ERROR_TIMEOUT                            1460
+CONSTANT: ERROR_EVENTLOG_FILE_CORRUPT              1500
+CONSTANT: ERROR_EVENTLOG_CANT_START                1501
+CONSTANT: ERROR_LOG_FILE_FULL                      1502
+CONSTANT: ERROR_EVENTLOG_FILE_CHANGED              1503
+CONSTANT: RPC_S_INVALID_STRING_BINDING             1700
+CONSTANT: RPC_S_WRONG_KIND_OF_BINDING              1701
+CONSTANT: RPC_S_INVALID_BINDING                    1702
+CONSTANT: RPC_S_PROTSEQ_NOT_SUPPORTED              1703
+CONSTANT: RPC_S_INVALID_RPC_PROTSEQ                1704
+CONSTANT: RPC_S_INVALID_STRING_UUID                1705
+CONSTANT: RPC_S_INVALID_ENDPOINT_FORMAT            1706
+CONSTANT: RPC_S_INVALID_NET_ADDR                   1707
+CONSTANT: RPC_S_NO_ENDPOINT_FOUND                  1708
+CONSTANT: RPC_S_INVALID_TIMEOUT                    1709
+CONSTANT: RPC_S_OBJECT_NOT_FOUND                   1710
+CONSTANT: RPC_S_ALREADY_REGISTERED                 1711
+CONSTANT: RPC_S_TYPE_ALREADY_REGISTERED            1712
+CONSTANT: RPC_S_ALREADY_LISTENING                  1713
+CONSTANT: RPC_S_NO_PROTSEQS_REGISTERED             1714
+CONSTANT: RPC_S_NOT_LISTENING                      1715
+CONSTANT: RPC_S_UNKNOWN_MGR_TYPE                   1716
+CONSTANT: RPC_S_UNKNOWN_IF                         1717
+CONSTANT: RPC_S_NO_BINDINGS                        1718
+CONSTANT: RPC_S_NO_PROTSEQS                        1719
+CONSTANT: RPC_S_CANT_CREATE_ENDPOINT               1720
+CONSTANT: RPC_S_OUT_OF_RESOURCES                   1721
+CONSTANT: RPC_S_SERVER_UNAVAILABLE                 1722
+CONSTANT: RPC_S_SERVER_TOO_BUSY                    1723
+CONSTANT: RPC_S_INVALID_NETWORK_OPTIONS            1724
+CONSTANT: RPC_S_NO_CALL_ACTIVE                     1725
+CONSTANT: RPC_S_CALL_FAILED                        1726
+CONSTANT: RPC_S_CALL_FAILED_DNE                    1727
+CONSTANT: RPC_S_PROTOCOL_ERROR                     1728
+CONSTANT: RPC_S_UNSUPPORTED_TRANS_SYN              1730
+CONSTANT: RPC_S_UNSUPPORTED_TYPE                   1732
+CONSTANT: RPC_S_INVALID_TAG                        1733
+CONSTANT: RPC_S_INVALID_BOUND                      1734
+CONSTANT: RPC_S_NO_ENTRY_NAME                      1735
+CONSTANT: RPC_S_INVALID_NAME_SYNTAX                1736
+CONSTANT: RPC_S_UNSUPPORTED_NAME_SYNTAX            1737
+CONSTANT: RPC_S_UUID_NO_ADDRESS                    1739
+CONSTANT: RPC_S_DUPLICATE_ENDPOINT                 1740
+CONSTANT: RPC_S_UNKNOWN_AUTHN_TYPE                 1741
+CONSTANT: RPC_S_MAX_CALLS_TOO_SMALL                1742
+CONSTANT: RPC_S_STRING_TOO_LONG                    1743
+CONSTANT: RPC_S_PROTSEQ_NOT_FOUND                  1744
+CONSTANT: RPC_S_PROCNUM_OUT_OF_RANGE               1745
+CONSTANT: RPC_S_BINDING_HAS_NO_AUTH                1746
+CONSTANT: RPC_S_UNKNOWN_AUTHN_SERVICE              1747
+CONSTANT: RPC_S_UNKNOWN_AUTHN_LEVEL                1748
+CONSTANT: RPC_S_INVALID_AUTH_IDENTITY              1749
+CONSTANT: RPC_S_UNKNOWN_AUTHZ_SERVICE              1750
+CONSTANT: EPT_S_INVALID_ENTRY                      1751
+CONSTANT: EPT_S_CANT_PERFORM_OP                    1752
+CONSTANT: EPT_S_NOT_REGISTERED                     1753
+CONSTANT: RPC_S_NOTHING_TO_EXPORT                  1754
+CONSTANT: RPC_S_INCOMPLETE_NAME                    1755
+CONSTANT: RPC_S_INVALID_VERS_OPTION                1756
+CONSTANT: RPC_S_NO_MORE_MEMBERS                    1757
+CONSTANT: RPC_S_NOT_ALL_OBJS_UNEXPORTED            1758
+CONSTANT: RPC_S_INTERFACE_NOT_FOUND                1759
+CONSTANT: RPC_S_ENTRY_ALREADY_EXISTS               1760
+CONSTANT: RPC_S_ENTRY_NOT_FOUND                    1761
+CONSTANT: RPC_S_NAME_SERVICE_UNAVAILABLE           1762
+CONSTANT: RPC_S_INVALID_NAF_ID                     1763
+CONSTANT: RPC_S_CANNOT_SUPPORT                     1764
+CONSTANT: RPC_S_NO_CONTEXT_AVAILABLE               1765
+CONSTANT: RPC_S_INTERNAL_ERROR                     1766
+CONSTANT: RPC_S_ZERO_DIVIDE                        1767
+CONSTANT: RPC_S_ADDRESS_ERROR                      1768
+CONSTANT: RPC_S_FP_DIV_ZERO                        1769
+CONSTANT: RPC_S_FP_UNDERFLOW                       1770
+CONSTANT: RPC_S_FP_OVERFLOW                        1771
+CONSTANT: RPC_X_NO_MORE_ENTRIES                    1772
+CONSTANT: RPC_X_SS_CHAR_TRANS_OPEN_FAIL            1773
+CONSTANT: RPC_X_SS_CHAR_TRANS_SHORT_FILE           1774
+CONSTANT: RPC_X_SS_IN_NULL_CONTEXT                 1775
+CONSTANT: RPC_X_SS_CONTEXT_DAMAGED                 1777
+CONSTANT: RPC_X_SS_HANDLES_MISMATCH                1778
+CONSTANT: RPC_X_SS_CANNOT_GET_CALL_HANDLE          1779
+CONSTANT: RPC_X_NULL_REF_POINTER                   1780
+CONSTANT: RPC_X_ENUM_VALUE_OUT_OF_RANGE            1781
+CONSTANT: RPC_X_BYTE_COUNT_TOO_SMALL               1782
+CONSTANT: RPC_X_BAD_STUB_DATA                      1783
+CONSTANT: ERROR_INVALID_USER_BUFFER                1784
+CONSTANT: ERROR_UNRECOGNIZED_MEDIA                 1785
+CONSTANT: ERROR_NO_TRUST_LSA_SECRET                1786
+CONSTANT: ERROR_NO_TRUST_SAM_ACCOUNT               1787
+CONSTANT: ERROR_TRUSTED_DOMAIN_FAILURE             1788
+CONSTANT: ERROR_TRUSTED_RELATIONSHIP_FAILURE       1789
+CONSTANT: ERROR_TRUST_FAILURE                      1790
+CONSTANT: RPC_S_CALL_IN_PROGRESS                   1791
+CONSTANT: ERROR_NETLOGON_NOT_STARTED               1792
+CONSTANT: ERROR_ACCOUNT_EXPIRED                    1793
+CONSTANT: ERROR_REDIRECTOR_HAS_OPEN_HANDLES        1794
+CONSTANT: ERROR_PRINTER_DRIVER_ALREADY_INSTALLED   1795
+CONSTANT: ERROR_UNKNOWN_PORT                       1796
+CONSTANT: ERROR_UNKNOWN_PRINTER_DRIVER             1797
+CONSTANT: ERROR_UNKNOWN_PRINTPROCESSOR             1798
+CONSTANT: ERROR_INVALID_SEPARATOR_FILE             1799
+CONSTANT: ERROR_INVALID_PRIORITY                   1800
+CONSTANT: ERROR_INVALID_PRINTER_NAME               1801
+CONSTANT: ERROR_PRINTER_ALREADY_EXISTS             1802
+CONSTANT: ERROR_INVALID_PRINTER_COMMAND            1803
+CONSTANT: ERROR_INVALID_DATATYPE                   1804
+CONSTANT: ERROR_INVALID_ENVIRONMENT                1805
+CONSTANT: RPC_S_NO_MORE_BINDINGS                   1806
+CONSTANT: ERROR_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT  1807
+CONSTANT: ERROR_NOLOGON_WORKSTATION_TRUST_ACCOUNT  1808
+CONSTANT: ERROR_NOLOGON_SERVER_TRUST_ACCOUNT       1809
+CONSTANT: ERROR_DOMAIN_TRUST_INCONSISTENT          1810
+CONSTANT: ERROR_SERVER_HAS_OPEN_HANDLES            1811
+CONSTANT: ERROR_RESOURCE_DATA_NOT_FOUND            1812
+CONSTANT: ERROR_RESOURCE_TYPE_NOT_FOUND            1813
+CONSTANT: ERROR_RESOURCE_NAME_NOT_FOUND            1814
+CONSTANT: ERROR_RESOURCE_LANG_NOT_FOUND            1815
+CONSTANT: ERROR_NOT_ENOUGH_QUOTA                   1816
+CONSTANT: RPC_S_NO_INTERFACES                      1817
+CONSTANT: RPC_S_CALL_CANCELLED                     1818
+CONSTANT: RPC_S_BINDING_INCOMPLETE                 1819
+CONSTANT: RPC_S_COMM_FAILURE                       1820
+CONSTANT: RPC_S_UNSUPPORTED_AUTHN_LEVEL            1821
+CONSTANT: RPC_S_NO_PRINC_NAME                      1822
+CONSTANT: RPC_S_NOT_RPC_ERROR                      1823
+CONSTANT: RPC_S_UUID_LOCAL_ONLY                    1824
+CONSTANT: RPC_S_SEC_PKG_ERROR                      1825
+CONSTANT: RPC_S_NOT_CANCELLED                      1826
+CONSTANT: RPC_X_INVALID_ES_ACTION                  1827
+CONSTANT: RPC_X_WRONG_ES_VERSION                   1828
+CONSTANT: RPC_X_WRONG_STUB_VERSION                 1829
+CONSTANT: RPC_X_INVALID_PIPE_OBJECT                1830
+CONSTANT: RPC_X_INVALID_PIPE_OPERATION             1831
+CONSTANT: RPC_X_WRONG_PIPE_VERSION                 1832
+CONSTANT: RPC_S_GROUP_MEMBER_NOT_FOUND             1898
+CONSTANT: EPT_S_CANT_CREATE                        1899
+CONSTANT: RPC_S_INVALID_OBJECT                     1900
+CONSTANT: ERROR_INVALID_TIME                       1901
+CONSTANT: ERROR_INVALID_FORM_NAME                  1902
+CONSTANT: ERROR_INVALID_FORM_SIZE                  1903
+CONSTANT: ERROR_ALREADY_WAITING                    1904
+CONSTANT: ERROR_PRINTER_DELETED                    1905
+CONSTANT: ERROR_INVALID_PRINTER_STATE              1906
+CONSTANT: ERROR_PASSWORD_MUST_CHANGE               1907
+CONSTANT: ERROR_DOMAIN_CONTROLLER_NOT_FOUND        1908
+CONSTANT: ERROR_ACCOUNT_LOCKED_OUT                 1909
+CONSTANT: OR_INVALID_OXID                          1910
+CONSTANT: OR_INVALID_OID                           1911
+CONSTANT: OR_INVALID_SET                           1912
+CONSTANT: RPC_S_SEND_INCOMPLETE                    1913
+CONSTANT: ERROR_INVALID_PIXEL_FORMAT               2000
+CONSTANT: ERROR_BAD_DRIVER                         2001
+CONSTANT: ERROR_INVALID_WINDOW_STYLE               2002
+CONSTANT: ERROR_METAFILE_NOT_SUPPORTED             2003
+CONSTANT: ERROR_TRANSFORM_NOT_SUPPORTED            2004
+CONSTANT: ERROR_CLIPPING_NOT_SUPPORTED             2005
+CONSTANT: ERROR_BAD_USERNAME                       2202
+CONSTANT: ERROR_NOT_CONNECTED                      2250
+CONSTANT: ERROR_OPEN_FILES                         2401
+CONSTANT: ERROR_ACTIVE_CONNECTIONS                 2402
+CONSTANT: ERROR_DEVICE_IN_USE                      2404
+CONSTANT: ERROR_UNKNOWN_PRINT_MONITOR              3000
+CONSTANT: ERROR_PRINTER_DRIVER_IN_USE              3001
+CONSTANT: ERROR_SPOOL_FILE_NOT_FOUND               3002
+CONSTANT: ERROR_SPL_NO_STARTDOC                    3003
+CONSTANT: ERROR_SPL_NO_ADDJOB                      3004
+CONSTANT: ERROR_PRINT_PROCESSOR_ALREADY_INSTALLED  3005
+CONSTANT: ERROR_PRINT_MONITOR_ALREADY_INSTALLED    3006
+CONSTANT: ERROR_INVALID_PRINT_MONITOR              3007
+CONSTANT: ERROR_PRINT_MONITOR_IN_USE               3008
+CONSTANT: ERROR_PRINTER_HAS_JOBS_QUEUED            3009
+CONSTANT: ERROR_SUCCESS_REBOOT_REQUIRED            3010
+CONSTANT: ERROR_SUCCESS_RESTART_REQUIRED           3011
+CONSTANT: ERROR_WINS_INTERNAL                      4000
+CONSTANT: ERROR_CAN_NOT_DEL_LOCAL_WINS             4001
+CONSTANT: ERROR_STATIC_INIT                        4002
+CONSTANT: ERROR_INC_BACKUP                         4003
+CONSTANT: ERROR_FULL_BACKUP                        4004
+CONSTANT: ERROR_REC_NON_EXISTENT                   4005
+CONSTANT: ERROR_RPL_NOT_ALLOWED                    4006
+CONSTANT: ERROR_NO_BROWSER_SERVERS_FOUND           6118
+
+CONSTANT: SUBLANG_NEUTRAL 0
+CONSTANT: LANG_NEUTRAL 0
+CONSTANT: SUBLANG_DEFAULT 1
+
+CONSTANT: FORMAT_MESSAGE_ALLOCATE_BUFFER  HEX: 00000100
+CONSTANT: FORMAT_MESSAGE_IGNORE_INSERTS   HEX: 00000200
+CONSTANT: FORMAT_MESSAGE_FROM_STRING      HEX: 00000400
+CONSTANT: FORMAT_MESSAGE_FROM_HMODULE     HEX: 00000800
+CONSTANT: FORMAT_MESSAGE_FROM_SYSTEM      HEX: 00001000
+CONSTANT: FORMAT_MESSAGE_ARGUMENT_ARRAY   HEX: 00002000
+CONSTANT: FORMAT_MESSAGE_MAX_WIDTH_MASK   HEX: 000000FF
+
+: make-lang-id ( lang1 lang2 -- n )
+    10 shift bitor ; inline
+
+ERROR: error-message-failed id ;
+:: n>win32-error-string ( id -- string )
+    {
+        FORMAT_MESSAGE_FROM_SYSTEM
+        FORMAT_MESSAGE_ARGUMENT_ARRAY
+    } flags
+    f
+    id
+    LANG_NEUTRAL SUBLANG_DEFAULT make-lang-id
+    32768 [ "TCHAR" <c-array> ] keep 
+    f pick [ FormatMessage 0 = [ id error-message-failed ] when ] dip
+    utf16n alien>string [ blank? ] trim ;
+
+: win32-error-string ( -- str )
+    GetLastError n>win32-error-string ;
+
+: (win32-error) ( n -- )
+    dup zero? [
+        drop
+    ] [
+        win32-error-string throw
+    ] if ;
+
+: win32-error ( -- )
+    GetLastError (win32-error) ;
+
+: win32-error=0/f ( n -- ) { 0 f } member? [ win32-error ] when ;
+: win32-error>0 ( n -- ) 0 > [ win32-error ] when ;
+: win32-error<0 ( n -- ) 0 < [ win32-error ] when ;
+: win32-error<>0 ( n -- ) zero? [ win32-error ] unless ;
+
+: invalid-handle? ( handle -- )
+    INVALID_HANDLE_VALUE = [
+        win32-error-string throw
+    ] when ;
+
+: expected-io-errors ( -- seq )
+    ERROR_SUCCESS
+    ERROR_IO_INCOMPLETE
+    ERROR_IO_PENDING
+    WAIT_TIMEOUT 4array ; foldable
+
+: expected-io-error? ( error-code -- ? )
+    expected-io-errors member? ;
+
+: expected-io-error ( error-code -- )
+    dup expected-io-error? [
+        drop
+    ] [
+        win32-error-string throw
+    ] if ;
+
+: io-error ( return-value -- )
+    { 0 f } member? [ GetLastError expected-io-error ] when ;
index a034856b34a1dcc49f05b4c34e798bc3278cda5a..1753ff1ce1f13f656573b0a4ca385d9bfdeca95a 100755 (executable)
@@ -1,5 +1,5 @@
 USING: assocs memoize locals kernel accessors init fonts math\r
-combinators windows windows.types windows.gdi32 ;\r
+combinators windows.errors windows.types windows.gdi32 ;\r
 IN: windows.fonts\r
 \r
 : windows-font-name ( string -- string' )\r
diff --git a/basis/windows/fonts/tags.txt b/basis/windows/fonts/tags.txt
new file mode 100644 (file)
index 0000000..6bf6830
--- /dev/null
@@ -0,0 +1 @@
+unportable
index 1a513df1867728bba1d738437a5776606c576b7c..e654b68bdc034f33a3cd9dfe3795c27324e9cad7 100755 (executable)
@@ -1110,7 +1110,19 @@ FUNCTION: BOOL FindVolumeMountPointClose ( HANDLE hFindVolumeMountPoint ) ;
 ! FUNCTION: FoldStringA
 ! FUNCTION: FoldStringW
 ! FUNCTION: FormatMessageA
-! FUNCTION: FormatMessageW
+FUNCTION: DWORD FormatMessageW (
+        DWORD dwFlags,
+        LPCVOID lpSource,
+        DWORD dwMessageId,
+        DWORD dwLanguageId,
+        LPTSTR lpBuffer,
+        DWORD nSize,
+        void* Arguments
+    ) ;
+
+ALIAS: FormatMessage FormatMessageW
+
+
 FUNCTION: BOOL FreeConsole ( ) ;
 ! FUNCTION: FreeEnvironmentStringsA
 FUNCTION: BOOL FreeEnvironmentStringsW ( LPTCH lpszEnvironmentBlock ) ;
index e69a9213b0622b67c07de9acd5a3ffd6142b0afd..864700cb0fa6afe362c6490daac0bd45550b8f00 100755 (executable)
@@ -1,6 +1,6 @@
 USING: alien alien.syntax alien.c-types alien.strings math
-kernel sequences windows windows.types debugger io accessors
-math.order namespaces make math.parser windows.kernel32
+kernel sequences windows.errors windows.types debugger io
+accessors math.order namespaces make math.parser windows.kernel32
 combinators locals specialized-arrays.direct.uchar ;
 IN: windows.ole32
 
@@ -120,7 +120,7 @@ TUPLE: ole32-error error-code ;
 C: <ole32-error> ole32-error
 
 M: ole32-error error.
-    "COM method failed: " print error-code>> (win32-error-string) print ;
+    "COM method failed: " print error-code>> n>win32-error-string print ;
 
 : ole32-error ( hresult -- )
     dup succeeded? [ drop ] [ <ole32-error> throw ] if ;
index 7802ceb297c27b8b0dcba804494707fb570a9d54..016f5ab149dc2a5cb0fe810423969f5c440600cb 100644 (file)
@@ -2,8 +2,8 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien alien.c-types alien.strings alien.syntax
 combinators io.encodings.utf16n io.files io.pathnames kernel
-windows windows.com windows.com.syntax windows.user32
-windows.ole32 ;
+windows.errors windows.com windows.com.syntax windows.user32
+windows.ole32 windows ;
 IN: windows.shell32
 
 CONSTANT: CSIDL_DESKTOP HEX: 00
index e63834d3695801278f3a78f6234cf6ec564c59ab..71726a554a8fadb123bc988239e2fbf275a4ca84 100644 (file)
@@ -1,11 +1,11 @@
 ! Copyright (C) 2007 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien alien.c-types kernel math windows windows.kernel32
-namespaces calendar math.bitwise ;
+USING: alien alien.c-types kernel math windows.errors
+windows.kernel32 namespaces calendar math.bitwise ;
 IN: windows.time
 
 : >64bit ( lo hi -- n )
-    32 shift bitor ;
+    32 shift bitor ; inline
 
 : windows-1601 ( -- timestamp )
     1601 1 1 0 0 0 instant <timestamp> ;
index 20bae06f30d82fb872b9291c1ae81659bc6c2bf3..062196c3f88183d72f01d3a34f57986717c4bad9 100755 (executable)
@@ -100,7 +100,7 @@ TYPEDEF: HANDLE              HGDIOBJ
 TYPEDEF: HANDLE              HGLOBAL
 TYPEDEF: HANDLE              HHOOK
 TYPEDEF: HANDLE              HINSTANCE
-TYPEDEF: HANDLE              HKEY
+TYPEDEF: DWORD               HKEY
 TYPEDEF: HANDLE              HKL
 TYPEDEF: HANDLE              HLOCAL
 TYPEDEF: HANDLE              HMENU
index fb0c134b9a88bb5db99bf949e8a752420ad21224..feb0bef7a8ab7dd06c204a058107992f93250fd2 100755 (executable)
@@ -2,9 +2,9 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel assocs math sequences fry io.encodings.string
 io.encodings.utf16n accessors arrays combinators destructors
-cache namespaces init fonts alien.c-types windows windows.usp10
+cache namespaces init fonts alien.c-types windows.usp10
 windows.offscreen windows.gdi32 windows.ole32 windows.types
-windows.fonts opengl.textures locals ;
+windows.fonts opengl.textures locals windows.errors ;
 IN: windows.uniscribe
 
 TUPLE: script-string font string metrics ssa size image disposed ;
index f3bc1becb2e483603c8eae5830222d5c3713d93c..1e694bcbe4320a44b235ec9a4db7c1bf42eea292 100644 (file)
@@ -542,12 +542,46 @@ C-STRUCT: DEV_BROADCAST_HDR
     { "DWORD" "dbch_size" }
     { "DWORD" "dbch_devicetype" }
     { "DWORD" "dbch_reserved" } ;
+
 C-STRUCT: DEV_BROADCAST_DEVICEW
     { "DWORD" "dbcc_size" }
     { "DWORD" "dbcc_devicetype" }
     { "DWORD" "dbcc_reserved" }
     { "GUID"  "dbcc_classguid" }
-    { "WCHAR[1]" "dbcc_name" } ;
+    { { "WCHAR" 1 } "dbcc_name" } ;
+
+CONSTANT: CCHDEVICENAME 32
+
+C-STRUCT: MONITORINFOEX
+    { "DWORD" "cbSize" }
+    { "RECT"  "rcMonitor" }
+    { "RECT"  "rcWork" }
+    { "DWORD" "dwFlags" }
+    { { "TCHAR" CCHDEVICENAME } "szDevice" } ;
+
+TYPEDEF: MONITORINFOEX* LPMONITORINFOEX
+TYPEDEF: MONITORINFOEX* LPMONITORINFO
+
+CONSTANT: MONITOR_DEFAULTTONULL 0
+CONSTANT: MONITOR_DEFAULTTOPRIMARY 1
+CONSTANT: MONITOR_DEFAULTTONEAREST 2
+CONSTANT: MONITORINFOF_PRIMARY 1
+CONSTANT: SWP_NOSIZE 1
+CONSTANT: SWP_NOMOVE 2
+CONSTANT: SWP_NOZORDER 4
+CONSTANT: SWP_NOREDRAW 8
+CONSTANT: SWP_NOACTIVATE 16
+CONSTANT: SWP_FRAMECHANGED 32
+CONSTANT: SWP_SHOWWINDOW 64
+CONSTANT: SWP_HIDEWINDOW 128
+CONSTANT: SWP_NOCOPYBITS 256
+CONSTANT: SWP_NOOWNERZORDER 512
+CONSTANT: SWP_NOSENDCHANGING 1024
+CONSTANT: SWP_DRAWFRAME SWP_FRAMECHANGED
+CONSTANT: SWP_NOREPOSITION SWP_NOOWNERZORDER
+CONSTANT: SWP_DEFERERASE 8192
+CONSTANT: SWP_ASYNCWINDOWPOS 16384
+
 
 LIBRARY: user32
 
@@ -910,7 +944,10 @@ ALIAS: GetMessage GetMessageW
 ! FUNCTION: GetMessagePos
 ! FUNCTION: GetMessageTime
 ! FUNCTION: GetMonitorInfoA
-! FUNCTION: GetMonitorInfoW
+
+FUNCTION: BOOL GetMonitorInfoW ( HMONITOR hMonitor, LPMONITORINFO lpmi ) ;
+ALIAS: GetMonitorInfo GetMonitorInfoW
+
 ! FUNCTION: GetMouseMovePointsEx
 ! FUNCTION: GetNextDlgGroupItem
 ! FUNCTION: GetNextDlgTabItem
@@ -961,6 +998,8 @@ FUNCTION: HWND GetWindow ( HWND hWnd, UINT uCmd ) ;
 ! FUNCTION: GetWindowInfo
 ! FUNCTION: GetWindowLongA
 ! FUNCTION: GetWindowLongW
+FUNCTION: LONG_PTR GetWindowLongW ( HANDLE hWnd, int index ) ;
+ALIAS: GetWindowLong GetWindowLongW
 ! FUNCTION: GetWindowModuleFileName
 ! FUNCTION: GetWindowModuleFileNameA
 ! FUNCTION: GetWindowModuleFileNameW
@@ -1127,7 +1166,7 @@ ALIAS: MessageBoxEx MessageBoxExW
 ! FUNCTION: ModifyMenuW
 ! FUNCTION: MonitorFromPoint
 ! FUNCTION: MonitorFromRect
-! FUNCTION: MonitorFromWindow
+FUNCTION: HMONITOR MonitorFromWindow ( HWND hWnd, DWORD dwFlags ) ;
 ! FUNCTION: mouse_event
 
 
@@ -1303,12 +1342,14 @@ FUNCTION: void SetLastErrorEx ( DWORD dwErrCode, DWORD dwType ) ;
 ! FUNCTION: SetWindowContextHelpId
 ! FUNCTION: SetWindowLongA
 ! FUNCTION: SetWindowLongW
+FUNCTION: LONG_PTR SetWindowLongW ( HANDLE hWnd, int index, LONG_PTR dwNewLong ) ;
+ALIAS: SetWindowLong SetWindowLongW
 ! FUNCTION: SetWindowPlacement
 FUNCTION: BOOL SetWindowPos ( HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags ) ;
 
 : HWND_BOTTOM ( -- alien ) 1 <alien> ;
 : HWND_NOTOPMOST ( -- alien ) -2 <alien> ;
-: HWND_TOP ( -- alien ) 0 <alien> ;
+CONSTANT: HWND_TOP f
 : HWND_TOPMOST ( -- alien ) -1 <alien> ;
 
 ! FUNCTION: SetWindowRgn
index 902b1bec8ddf0275a8424939f38e09a674998269..92ba8b638a4366af029cb25e0e2d0d4fff16da7e 100755 (executable)
@@ -1,61 +1,5 @@
 ! Copyright (C) 2005, 2006 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien alien.syntax alien.c-types alien.strings arrays
-combinators kernel math namespaces parser sequences
-windows.errors windows.types windows.kernel32 words
-io.encodings.utf16n ;
 IN: windows
 
-: lo-word ( wparam -- lo ) <short> *short ; inline
-: hi-word ( wparam -- hi ) -16 shift lo-word ; inline
 CONSTANT: MAX_UNICODE_PATH 32768
-
-! You must LocalFree the return value!
-FUNCTION: void* error_message ( DWORD id ) ;
-
-: (win32-error-string) ( n -- string )
-    error_message
-    dup utf16n alien>string
-    swap LocalFree drop ;
-
-: win32-error-string ( -- str )
-    GetLastError (win32-error-string) ;
-
-: (win32-error) ( n -- )
-    dup zero? [
-        drop
-    ] [
-        win32-error-string throw
-    ] if ;
-
-: win32-error ( -- )
-    GetLastError (win32-error) ;
-
-: win32-error=0/f ( n -- ) { 0 f } member? [ win32-error ] when ;
-: win32-error>0 ( n -- ) 0 > [ win32-error ] when ;
-: win32-error<0 ( n -- ) 0 < [ win32-error ] when ;
-: win32-error<>0 ( n -- ) zero? [ win32-error ] unless ;
-
-: invalid-handle? ( handle -- )
-    INVALID_HANDLE_VALUE = [
-        win32-error-string throw
-    ] when ;
-
-: expected-io-errors ( -- seq )
-    ERROR_SUCCESS
-    ERROR_IO_INCOMPLETE
-    ERROR_IO_PENDING
-    WAIT_TIMEOUT 4array ; foldable
-
-: expected-io-error? ( error-code -- ? )
-    expected-io-errors member? ;
-
-: expected-io-error ( error-code -- )
-    dup expected-io-error? [
-        drop
-    ] [
-        (win32-error-string) throw
-    ] if ;
-
-: io-error ( return-value -- )
-    { 0 f } member? [ GetLastError expected-io-error ] when ;
index 06df74cd4cff8ad768b686adb13e78cfb784758b..f0d32588f5d7278ed9c155bb58dcacd88a37fe6f 100755 (executable)
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien alien.c-types alien.strings alien.syntax arrays
 byte-arrays kernel math sequences windows.types windows.kernel32
-windows.errors windows math.bitwise io.encodings.utf16n ;
+windows.errors math.bitwise io.encodings.utf16n ;
 IN: windows.winsock
 
 USE: libc
@@ -403,7 +403,7 @@ CONSTANT: SIO_GET_EXTENSION_FUNCTION_POINTER -939524090
 : (winsock-error-string) ( n -- str )
     ! #! WSAStartup returns the error code 'n' directly
     dup winsock-expected-error?
-    [ drop f ] [ error_message utf16n alien>string ] if ;
+    [ drop f ] [ n>win32-error-string ] if ;
 
 : winsock-error-string ( -- string/f )
     WSAGetLastError (winsock-error-string) ;
index 3fb5a532c9f8ec71e6fbb9bef468a84b0d0379f0..b5141f6cc4bbe0959fd881f7dd7a3ff390c9e9d0 100644 (file)
@@ -24,7 +24,7 @@ IN: xmode.code2html
     [XML <style><-></style> XML] ;
 
 :: htmlize-stream ( path stream -- xml )
-    stream lines
+    stream stream-lines
     [ "" ] [ path over first find-mode htmlize-lines ]
     if-empty :> input
     default-stylesheet :> stylesheet
index 3ece72306ad15ebd6d26621e96d6c117e2284ed5..ba5815cfc180eb90e3cbbe23964924af7f8ae2c4 100755 (executable)
@@ -205,7 +205,7 @@ find_architecture() {
 
 write_test_program() {
     echo "#include <stdio.h>" > $C_WORD.c
-    echo "int main(){printf(\"%ld\", 8*sizeof(void*)); return 0; }" >> $C_WORD.c
+    echo "int main(){printf(\"%ld\", (long)(8*sizeof(void*))); return 0; }" >> $C_WORD.c
 }
 
 c_find_word_size() {
index 26100277a8433c69ec039110428e5126f8f17684..5ed92b7776984daad06677ee4f5a9e2e5724619a 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2007, 2008 Slava Pestov.
+! Copyright (C) 2007, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: namespaces math words kernel alien byte-arrays
 hashtables vectors strings sbufs arrays
@@ -9,28 +9,28 @@ BIN: 111 tag-mask set
 8 num-tags set
 3 tag-bits set
 
-17 num-types set
+15 num-types set
+
+32 mega-cache-size set
 
 H{
     { fixnum      BIN: 000 }
     { bignum      BIN: 001 }
-    { tuple       BIN: 010 }
-    { object      BIN: 011 }
-    { hi-tag      BIN: 011 }
-    { ratio       BIN: 100 }
-    { float       BIN: 101 }
-    { complex     BIN: 110 }
-    { POSTPONE: f BIN: 111 }
+    { array       BIN: 010 }
+    { float       BIN: 011 }
+    { quotation   BIN: 100 }
+    { POSTPONE: f BIN: 101 }
+    { object      BIN: 110 }
+    { hi-tag      BIN: 110 }
+    { tuple       BIN: 111 }
 } tag-numbers set
 
 tag-numbers get H{
-    { array 8 }
-    { wrapper 9 }
-    { byte-array 10 }
-    { callstack 11 }
-    { string 12 }
-    { word 13 }
-    { quotation 14 }
-    { dll 15 }
-    { alien 16 }
+    { wrapper 8 }
+    { byte-array 9 }
+    { callstack 10 }
+    { string 11 }
+    { word 12 }
+    { dll 13 }
+    { alien 14 }
 } assoc-union type-numbers set
index 1258da8a4daad4767e3287be47b7a71a9f8ae59d..c0d51477cab06f56891e8d7e2390fdfd326375af 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2004, 2008 Slava Pestov.
+! Copyright (C) 2004, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien arrays byte-arrays generic hashtables
 hashtables.private io kernel math math.private math.order
@@ -69,6 +69,8 @@ bootstrapping? on
     "classes.predicate"
     "compiler.units"
     "continuations.private"
+    "generic.single"
+    "generic.single.private"
     "growable"
     "hashtables"
     "hashtables.private"
@@ -97,7 +99,6 @@ bootstrapping? on
     "threads.private"
     "tools.profiler.private"
     "words"
-    "words.private"
     "vectors"
     "vectors.private"
 } [ create-vocab drop ] each
@@ -125,9 +126,7 @@ bootstrapping? on
 "fixnum" "math" create register-builtin
 "bignum" "math" create register-builtin
 "tuple" "kernel" create register-builtin
-"ratio" "math" create register-builtin
 "float" "math" create register-builtin
-"complex" "math" create register-builtin
 "f" "syntax" lookup register-builtin
 "array" "arrays" create register-builtin
 "wrapper" "kernel" create register-builtin
@@ -146,24 +145,6 @@ bootstrapping? on
 "f?" "syntax" vocab-words delete-at
 
 ! Some unions
-"integer" "math" create
-"fixnum" "math" lookup
-"bignum" "math" lookup
-2array
-define-union-class
-
-"rational" "math" create
-"integer" "math" lookup
-"ratio" "math" lookup
-2array
-define-union-class
-
-"real" "math" create
-"rational" "math" lookup
-"float" "math" lookup
-2array
-define-union-class
-
 "c-ptr" "alien" create [
     "alien" "alien" lookup ,
     "f" "syntax" lookup ,
@@ -210,19 +191,9 @@ bi
 "bignum" "math" create { } define-builtin
 "bignum" "math" create ">bignum" "math" create 1quotation "coercer" set-word-prop
 
-"ratio" "math" create {
-    { "numerator" { "integer" "math" } read-only }
-    { "denominator" { "integer" "math" } read-only }
-} define-builtin
-
 "float" "math" create { } define-builtin
 "float" "math" create ">float" "math" create 1quotation "coercer" set-word-prop
 
-"complex" "math" create {
-    { "real" { "real" "math" } read-only }
-    { "imaginary" { "real" "math" } read-only }
-} define-builtin
-
 "array" "arrays" create {
     { "length" { "array-capacity" "sequences.private" } read-only }
 } define-builtin
@@ -258,7 +229,7 @@ bi
     "vocabulary"
     { "def" { "quotation" "quotations" } initial: [ ] }
     "props"
-    { "optimized" read-only }
+    { "direct-entry-def" }
     { "counter" { "fixnum" "math" } }
     { "sub-primitive" read-only }
 } define-builtin
@@ -338,7 +309,7 @@ tuple
     [ create dup 1quotation ] dip define-declared ;
 
 {
-    { "(execute)" "words.private" (( word -- )) }
+    { "(execute)" "kernel.private" (( word -- )) }
     { "(call)" "kernel.private" (( quot -- )) }
     { "both-fixnums?" "math.private" (( x y -- ? )) }
     { "fixnum+fast" "math.private" (( x y -- z )) }
@@ -378,6 +349,7 @@ tuple
     { "get-local" "locals.backend" (( n -- obj )) }
     { "load-local" "locals.backend" (( obj -- )) }
     { "drop-locals" "locals.backend" (( n -- )) }
+    { "mega-cache-lookup" "generic.single.private" (( methods index cache -- )) }
 } [ first3 make-sub-primitive ] each
 
 ! Primitive words
@@ -394,14 +366,12 @@ tuple
     { "float>bignum" "math.private" (( x -- y )) }
     { "fixnum>float" "math.private" (( x -- y )) }
     { "bignum>float" "math.private" (( x -- y )) }
-    { "<ratio>" "math.private" (( a b -- a/b )) }
     { "string>float" "math.private" (( str -- n/f )) }
     { "float>string" "math.private" (( n -- str )) }
     { "float>bits" "math" (( x -- n )) }
     { "double>bits" "math" (( x -- n )) }
     { "bits>float" "math" (( n -- x )) }
     { "bits>double" "math" (( n -- x )) }
-    { "<complex>" "math.private" (( x y -- z )) }
     { "fixnum+" "math.private" (( x y -- z )) }
     { "fixnum-" "math.private" (( x y -- z )) }
     { "fixnum*" "math.private" (( x y -- z )) }
@@ -532,6 +502,14 @@ tuple
     { "jit-compile" "quotations" (( quot -- )) }
     { "load-locals" "locals.backend" (( ... n -- )) }
     { "check-datastack" "kernel.private" (( array in# out# -- ? )) }
+    { "inline-cache-miss" "generic.single.private" (( generic methods index cache -- )) }
+    { "mega-cache-miss" "generic.single.private" (( methods index cache -- method )) }
+    { "lookup-method" "generic.single.private" (( object methods -- method )) }
+    { "reset-dispatch-stats" "generic.single" (( -- )) }
+    { "dispatch-stats" "generic.single" (( -- stats )) }
+    { "reset-inline-cache-stats" "generic.single" (( -- )) }
+    { "inline-cache-stats" "generic.single" (( -- stats )) }
+    { "optimized?" "words" (( word -- ? )) }
 } [ [ first3 ] dip swap make-primitive ] each-index
 
 ! Bump build number
index 98d36b21c33d89dcdccd55cc9210c7b8068fa0ae..82918b6f816890558bf7bb8a1909d4b0005cdd83 100644 (file)
@@ -13,7 +13,7 @@ GENERIC: checksum-stream ( stream checksum -- value )
 GENERIC: checksum-lines ( lines checksum -- value )
 
 M: checksum checksum-stream
-    [ contents ] dip checksum-bytes ;
+    [ stream-contents ] dip checksum-bytes ;
 
 M: checksum checksum-lines
     [ B{ CHAR: \n } join ] dip checksum-bytes ;
index f95d66fd05c02731d556752b4df57611cd72d3bb..32f7af8113faaa900d749dcb98bb1625c374a1dd 100644 (file)
@@ -33,13 +33,13 @@ M: lo-tag-class define-builtin-predicate
 
 M: hi-tag-class define-builtin-predicate
     dup class>type [ eq? ] curry [ hi-tag ] prepend 1quotation
-    [ dup tag 3 eq? ] [ [ drop f ] if ] surround
+    [ dup tag 6 eq? ] [ [ drop f ] if ] surround
     define-predicate ;
 
 M: lo-tag-class instance? [ tag ] [ class>type ] bi* eq? ;
 
 M: hi-tag-class instance?
-    over tag 3 eq? [ [ hi-tag ] [ class>type ] bi* eq? ] [ 2drop f ] if ;
+    over tag 6 eq? [ [ hi-tag ] [ class>type ] bi* eq? ] [ 2drop f ] if ;
 
 M: builtin-class (flatten-class) dup set ;
 
index cd11591d6c3de001587fea2bbac35d62b83feb90..f44642fdd5eaf7588d83ecaba07cf651fa2bc52a 100644 (file)
@@ -119,3 +119,13 @@ MIXIN: move-instance-declaration-mixin
 [ ] [ "IN: classes.mixin.tests.a" <string-reader> "move-mixin-test-1" parse-stream drop ] unit-test
 
 [ { string } ] [ move-instance-declaration-mixin members ] unit-test
+
+MIXIN: silly-mixin
+SYMBOL: not-a-class
+
+[ [ \ not-a-class \ silly-mixin add-mixin-instance ] with-compilation-unit ] must-fail
+
+SYMBOL: not-a-mixin
+TUPLE: a-class ;
+
+[ [ \ a-class \ not-a-mixin add-mixin-instance ] with-compilation-unit ] must-fail
index 4bdb893d9adfcc920cfbd27e29419c5be83cab6c..6cf95716beb711ecde1e7feacb5444c9d2ca212c 100644 (file)
@@ -50,7 +50,9 @@ TUPLE: check-mixin-class class ;
     [ [ f ] 2dip "instances" word-prop set-at ]
     2bi ;
 
-: add-mixin-instance ( class mixin -- )
+GENERIC# add-mixin-instance 1 ( class mixin -- )
+
+M: class add-mixin-instance
     #! Note: we call update-classes on the new member, not the
     #! mixin. This ensures that we only have to update the
     #! methods whose specializer intersects the new member, not
index c180807b0cae11d505a913c611db5462911e3d3d..466b221877569b55eba738610fa87ba4a269524f 100644 (file)
@@ -1,11 +1,11 @@
-USING: definitions generic kernel kernel.private math
-math.constants parser sequences tools.test words assocs
-namespaces quotations sequences.private classes continuations
-generic.standard effects classes.tuple classes.tuple.private
-arrays vectors strings compiler.units accessors classes.algebra
-calendar prettyprint io.streams.string splitting summary
-columns math.order classes.private slots slots.private eval see
-words.symbol compiler.errors ;
+USING: definitions generic kernel kernel.private math math.constants
+parser sequences tools.test words assocs namespaces quotations
+sequences.private classes continuations generic.single
+generic.standard effects classes.tuple classes.tuple.private arrays
+vectors strings compiler.units accessors classes.algebra calendar
+prettyprint io.streams.string splitting summary columns math.order
+classes.private slots slots.private eval see words.symbol
+compiler.errors ;
 IN: classes.tuple.tests
 
 TUPLE: rect x y w h ;
old mode 100644 (file)
new mode 100755 (executable)
index cbef25a..8b301af
@@ -290,7 +290,6 @@ $nl
 "The above are syntax sugar. The underlying words are a bit more verbose but allow non-constant effects to be passed in:"
 { $subsection call-effect }
 { $subsection execute-effect }
-{ $subsection "call-unsafe" }
 "The combinator variants that do not take an effect declaration can only be used if the compiler is able to infer the stack effect by other means. See " { $link "inference-combinators" } "."
 { $subsection "call-unsafe" }
 { $see-also "effects" "inference" } ;
@@ -306,6 +305,7 @@ ARTICLE: "combinators" "Combinators"
 { $subsection "combinators.smart" }
 "More combinators are defined for working on data structures, such as " { $link "sequences-combinators" } " and " { $link "assocs-combinators" } "."
 { $subsection "combinators-quot" }
+{ $subsection "generalizations" }
 { $see-also "quotations" } ;
 
 ABOUT: "combinators"
old mode 100644 (file)
new mode 100755 (executable)
index dd5fa06..aae6618
@@ -16,12 +16,12 @@ IN: combinators.tests
 
 : compile-execute(-test-1 ( a b -- c ) \ + execute( a b -- c ) ;
 
-[ t ] [ \ compile-execute(-test-1 optimized>> ] unit-test
+[ t ] [ \ compile-execute(-test-1 optimized? ] unit-test
 [ 4 ] [ 1 3 compile-execute(-test-1 ] unit-test
 
 : compile-execute(-test-2 ( a b w -- c ) execute( a b -- c ) ;
 
-[ t ] [ \ compile-execute(-test-2 optimized>> ] unit-test
+[ t ] [ \ compile-execute(-test-2 optimized? ] unit-test
 [ 4 ] [ 1 3 \ + compile-execute(-test-2 ] unit-test
 [ 5 ] [ 1 4 \ + compile-execute(-test-2 ] unit-test
 [ -3 ] [ 1 4 \ - compile-execute(-test-2 ] unit-test
@@ -29,7 +29,7 @@ IN: combinators.tests
 
 : compile-call(-test-1 ( a b q -- c ) call( a b -- c ) ;
 
-[ t ] [ \ compile-call(-test-1 optimized>> ] unit-test
+[ t ] [ \ compile-call(-test-1 optimized? ] unit-test
 [ 4 ] [ 1 3 [ + ] compile-call(-test-1 ] unit-test
 [ 7 ] [ 1 3 2 [ * + ] curry compile-call(-test-1 ] unit-test
 [ 7 ] [ 1 3 [ 2 * ] [ + ] compose compile-call(-test-1 ] unit-test
@@ -352,7 +352,7 @@ DEFER: corner-case-1
 
 << \ corner-case-1 2 [ + ] curry 1array [ case ] curry (( a -- b )) define-declared >>
 
-[ t ] [ \ corner-case-1 optimized>> ] unit-test
+[ t ] [ \ corner-case-1 optimized? ] unit-test
 [ 4 ] [ 2 corner-case-1 ] unit-test
 
 [ 4 ] [ 2 2 [ + ] curry 1array case ] unit-test
index da2dce128fd6024956bdc55369c222aa74ef5ffa..8dce12f4114b5042df7ec93aa059cc3de0b0b5fb 100644 (file)
@@ -19,7 +19,7 @@ IN: compiler.units.tests
 ] unit-test
 
 [ "A" "B" ] [
-    disable-compiler
+    disable-optimizer
 
     gensym "a" set
     gensym "b" set
@@ -33,7 +33,7 @@ IN: compiler.units.tests
     ] with-compilation-unit
     "b" get execute
 
-    enable-compiler
+    enable-optimizer
 ] unit-test
 
 ! Check that we notify observers
index c4a137b2ba89b34bc7859ae64de1d81bf7d986b3..f1f9131f088ec2193d3527629c4037fb5eccafc9 100644 (file)
@@ -43,6 +43,9 @@ HOOK: recompile compiler-impl ( words -- alist )
 ! Non-optimizing compiler
 M: f recompile [ dup def>> ] { } map>assoc ;
 
+: without-optimizer ( quot -- )
+    [ f compiler-impl ] dip with-variable ; inline
+
 ! Trivial compiler. We don't want to touch the code heap
 ! during stage1 bootstrap, it would just waste time.
 SINGLETON: dummy-compiler
@@ -58,6 +61,10 @@ GENERIC: definitions-changed ( assoc obj -- )
 [ V{ } clone definition-observers set-global ]
 "compiler.units" add-init-hook
 
+! This goes here because vocabs cannot depend on init
+[ V{ } clone vocab-observers set-global ]
+"vocabs" add-init-hook
+
 : add-definition-observer ( obj -- )
     definition-observers get push ;
 
index 495aeb39c141d1a601e3b7b36f97f63a5eda27a5..38b8ab4dad2986985777795cdb52f4dc9891e200 100644 (file)
@@ -42,8 +42,15 @@ HELP: effect-height
 { $description "Outputs the number of objects added to the data stack by the stack effect. This will be negative if the stack effect only removes objects from the stack." } ;
 
 HELP: effect<=
-{ $values { "eff1" effect } { "eff2" effect } { "?" "a boolean" } }
-{ $description "Tests if " { $snippet "eff1" } " is substitutable for " { $snippet "eff2" } ". What this means is that both stack effects change the stack height by the same amount, the first takes a smaller or equal number of inputs as the second, and either both or neither one terminate execution by throwing an error." } ;
+{ $values { "effect1" effect } { "effect2" effect } { "?" "a boolean" } }
+{ $description "Tests if " { $snippet "effect1" } " is substitutable for " { $snippet "effect2" } ". What this means is that both stack effects change the stack height by the same amount, the first takes a smaller or equal number of inputs as the second, and either both or neither one terminate execution by throwing an error." } ;
+
+HELP: effect=
+{ $values { "effect1" effect } { "effect2" effect } { "?" "a boolean" } }
+{ $description "Tests if " { $snippet "effect1" } " and " { $snippet "effect2" } " represent the same stack transformation, without looking parameter names." }
+{ $examples
+  { $example "USING: effects prettyprint ;" "(( a -- b )) (( x -- y )) effect= ." "t" }
+} ;
 
 HELP: effect>string
 { $values { "obj" object } { "str" string } }
index 316add54c0bf4b37912bd933becf9f77ea6f9de9..3eb92738595188d03b661e890ee1829df316e6b8 100644 (file)
@@ -18,4 +18,8 @@ USING: effects tools.test prettyprint accessors sequences ;
 
 [ { "x" "y" } ] [ { "y" "x" } (( a b -- b a )) shuffle ] unit-test
 [ { "y" "x" "y" } ] [ { "y" "x" } (( a b -- a b a )) shuffle ] unit-test
-[ { } ] [ { "y" "x" } (( a b -- )) shuffle ] unit-test
\ No newline at end of file
+[ { } ] [ { "y" "x" } (( a b -- )) shuffle ] unit-test
+
+[ t ] [ (( -- )) (( -- )) compose-effects (( -- )) effect= ] unit-test
+[ t ] [ (( -- * )) (( -- )) compose-effects (( -- * )) effect= ] unit-test
+[ t ] [ (( -- )) (( -- * )) compose-effects (( -- * )) effect= ] unit-test
\ No newline at end of file
index 142b9120a8d5c3692846013348dac3641b6c7904..cab1e531b796200781c3757fa57cc9fafacdadf2 100644 (file)
@@ -1,6 +1,6 @@
 ! Copyright (C) 2006, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel math math.parser namespaces make sequences strings
+USING: kernel math math.parser math.order namespaces make sequences strings
 words assocs combinators accessors arrays ;
 IN: effects
 
@@ -13,7 +13,7 @@ TUPLE: effect { in read-only } { out read-only } { terminated? read-only } ;
 : effect-height ( effect -- n )
     [ out>> length ] [ in>> length ] bi - ; inline
 
-: effect<= ( eff1 eff2 -- ? )
+: effect<= ( effect1 effect2 -- ? )
     {
         { [ over terminated?>> ] [ t ] }
         { [ dup terminated?>> ] [ f ] }
@@ -22,6 +22,12 @@ TUPLE: effect { in read-only } { out read-only } { terminated? read-only } ;
         [ t ]
     } cond 2nip ; inline
 
+: effect= ( effect1 effect2 -- ? )
+    [ [ in>> length ] bi@ = ]
+    [ [ out>> length ] bi@ = ]
+    [ [ terminated?>> ] bi@ = ]
+    2tri and and ;
+
 GENERIC: effect>string ( obj -- str )
 M: string effect>string ;
 M: object effect>string drop "object" ;
@@ -66,3 +72,13 @@ M: effect clone
 
 : add-effect-input ( effect -- effect' )
     [ in>> "obj" suffix ] [ out>> ] [ terminated?>> ] tri effect boa ;
+
+: compose-effects ( effect1 effect2 -- effect' )
+    over terminated?>> [
+        drop
+    ] [
+        [ [ [ in>> length ] [ out>> length ] bi ] [ in>> length ] bi* swap [-] + ]
+        [ [ out>> length ] [ [ in>> length ] [ out>> length ] bi ] bi* [ [-] ] dip + ]
+        [ nip terminated?>> ] 2tri
+        effect boa
+    ] if ; inline
index e8b5e6d69c746443c7549c5bebb15b90981809c2..73002a5d89b3acceabc06d0a278b3e9c48f0d400 100644 (file)
@@ -1,6 +1,7 @@
 USING: help.markup help.syntax words classes classes.algebra
 definitions kernel alien sequences math quotations
-generic.standard generic.math combinators prettyprint effects ;
+generic.single generic.standard generic.hook generic.math
+combinators prettyprint effects ;
 IN: generic
 
 ARTICLE: "method-order" "Method precedence"
index e7ae583aa6436cc6e90c5e8dc68eb42484bb118e..a63cab1c5c230c387b99add5b23e2aa14d20f3bf 100755 (executable)
@@ -96,15 +96,6 @@ M: shit big-generic-test "shit" ;
 
 [ t ] [ \ + math-generic? ] unit-test
 
-! Test math-combination
-[ [ [ >float ] dip ] ] [ \ real \ float math-upgrade ] unit-test
-[ [ >float ] ] [ \ float \ real math-upgrade ] unit-test
-[ [ [ >bignum ] dip ] ] [ \ fixnum \ bignum math-upgrade ] unit-test
-[ [ >float ] ] [ \ float \ integer math-upgrade ] unit-test
-[ number ] [ \ number \ float math-class-max ] unit-test
-[ float ] [ \ real \ float math-class-max ] unit-test
-[ fixnum ] [ \ fixnum \ null math-class-max ] unit-test
-
 ! Regression
 TUPLE: first-one ;
 TUPLE: second-one ;
index 965be91642446f0d0d939678b2a38a9c259fb6a0..4b398f6532a9ccb0eb31fcbd8bcad0c2a63fe98e 100644 (file)
@@ -164,8 +164,8 @@ M: sequence update-methods ( class seq -- )
         drop
         2dup [ "combination" word-prop ] dip = [ 2drop ] [
             {
+                [ drop reset-generic ]
                 [ "combination" set-word-prop ]
-                [ drop "methods" word-prop values forget-all ]
                 [ drop H{ } clone "methods" set-word-prop ]
                 [ define-default-method ]
             }
diff --git a/core/generic/hook/authors.txt b/core/generic/hook/authors.txt
new file mode 100644 (file)
index 0000000..d4f5d6b
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
\ No newline at end of file
diff --git a/core/generic/hook/hook-docs.factor b/core/generic/hook/hook-docs.factor
new file mode 100644 (file)
index 0000000..9b57d94
--- /dev/null
@@ -0,0 +1,10 @@
+USING: generic generic.single generic.standard help.markup help.syntax sequences math
+math.parser effects ;
+IN: generic.hook
+
+HELP: hook-combination
+{ $class-description
+    "Performs hook method combination . See " { $link POSTPONE: HOOK: } "."
+} ;
+
+{ standard-combination hook-combination } related-words
\ No newline at end of file
diff --git a/core/generic/hook/hook.factor b/core/generic/hook/hook.factor
new file mode 100644 (file)
index 0000000..fe5b62f
--- /dev/null
@@ -0,0 +1,28 @@
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors definitions generic generic.single
+generic.single.private kernel namespaces words kernel.private
+quotations sequences ;
+IN: generic.hook
+
+TUPLE: hook-combination < single-combination var ;
+
+C: <hook-combination> hook-combination
+
+PREDICATE: hook-generic < generic
+    "combination" word-prop hook-combination? ;
+
+M: hook-combination picker
+    combination get var>> [ get ] curry ;
+
+M: hook-combination dispatch# drop 0 ;
+
+M: hook-combination inline-cache-quot 2drop f ;
+
+M: hook-combination mega-cache-quot
+    1quotation picker [ lookup-method (execute) ] surround ;
+
+M: hook-generic definer drop \ HOOK: f ;
+
+M: hook-generic effective-method
+    [ "combination" word-prop var>> get ] keep (effective-method) ;
\ No newline at end of file
index 60fa7453394f53b43a00e0f2ab7a8eae796d9295..7d7d6e725b2ed1cb891a5e599160c7e085c54774 100644 (file)
@@ -1,5 +1,5 @@
 USING: kernel generic help.markup help.syntax math classes
-sequences quotations ;
+sequences quotations generic.math.private ;
 IN: generic.math
 
 HELP: math-upgrade
diff --git a/core/generic/math/math-tests.factor b/core/generic/math/math-tests.factor
new file mode 100644 (file)
index 0000000..51e1224
--- /dev/null
@@ -0,0 +1,21 @@
+IN: generic.math.tests
+USING: generic.math math tools.test kernel ;
+
+! Test math-combination
+[ [ [ >float ] dip ] ] [ \ real \ float math-upgrade ] unit-test
+[ [ >float ] ] [ \ float \ real math-upgrade ] unit-test
+[ [ [ >bignum ] dip ] ] [ \ fixnum \ bignum math-upgrade ] unit-test
+[ [ >float ] ] [ \ float \ integer math-upgrade ] unit-test
+
+[ number ] [ number float math-class-max ] unit-test
+[ number ] [ float number math-class-max ] unit-test
+[ float ] [ real float math-class-max ] unit-test
+[ float ] [ float real math-class-max ] unit-test
+[ fixnum ] [ fixnum null math-class-max ] unit-test
+[ fixnum ] [ null fixnum math-class-max ] unit-test
+[ bignum ] [ fixnum bignum math-class-max ] unit-test
+[ bignum ] [ bignum fixnum math-class-max ] unit-test
+[ number ] [ fixnum number math-class-max ] unit-test
+[ number ] [ number fixnum math-class-max ] unit-test
+
+
index 8d4610dabed96986dd781ea81fbd507431b752a5..c96050ad03dc38af22f083130127ea37b5ffb377 100644 (file)
@@ -1,9 +1,9 @@
-! Copyright (C) 2005, 2008 Slava Pestov.
+! Copyright (C) 2005, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays generic hashtables kernel kernel.private math
-namespaces make sequences words quotations layouts combinators
+namespaces sequences words quotations layouts combinators
 sequences.private classes classes.builtin classes.algebra
-definitions math.order math.private ;
+definitions math.order math.private assocs ;
 IN: generic.math
 
 PREDICATE: math-class < class
@@ -13,24 +13,30 @@ PREDICATE: math-class < class
         number bootstrap-word class<=
     ] if ;
 
+<PRIVATE
+
 : last/first ( seq -- pair ) [ peek ] [ first ] bi 2array ;
 
-: math-precedence ( class -- pair )
-    {
-        { [ dup null class<= ] [ drop { -1 -1 } ] }
-        { [ dup math-class? ] [ class-types last/first ] }
-        [ drop { 100 100 } ]
-    } cond ;
-    
-: math-class<=> ( class1 class2 -- class )
-    [ math-precedence ] compare +gt+ eq? ;
+: bootstrap-words ( classes -- classes' )
+    [ bootstrap-word ] map ;
 
-: math-class-max ( class1 class2 -- class )
-    [ math-class<=> ] most ;
+: math-precedence ( class -- pair )
+    [
+        { fixnum integer rational real number object } bootstrap-words
+        swap [ swap class<= ] curry find drop -1 or
+    ] [
+        { fixnum bignum ratio float complex object } bootstrap-words
+        swap [ class<= ] curry find drop -1 or
+    ] bi 2array ;
 
 : (math-upgrade) ( max class -- quot )
     dupd = [ drop [ ] ] [ "coercer" word-prop [ ] or ] if ;
 
+PRIVATE>
+
+: math-class-max ( class1 class2 -- class )
+    [ [ math-precedence ] bi@ after? ] most ;
+
 : math-upgrade ( class1 class2 -- quot )
     [ math-class-max ] 2keep
     [
@@ -44,33 +50,57 @@ ERROR: no-math-method left right generic ;
 : default-math-method ( generic -- quot )
     [ no-math-method ] curry [ ] like ;
 
+<PRIVATE
+
 : applicable-method ( generic class -- quot )
     over method
     [ 1quotation ]
     [ default-math-method ] ?if ;
 
+PRIVATE>
+
 : object-method ( generic -- quot )
     object bootstrap-word applicable-method ;
 
 : math-method ( word class1 class2 -- quot )
     2dup and [
-        [
-            2dup 2array , \ declare ,
-            2dup math-upgrade %
-            math-class-max over order min-class applicable-method %
-        ] [ ] make
+        [ 2array [ declare ] curry nip ]
+        [ math-upgrade nip ]
+        [ math-class-max over order min-class applicable-method ]
+        3tri 3append
     ] [
         2drop object-method
     ] if ;
 
-SYMBOL: picker
+<PRIVATE
 
-: math-vtable ( picker quot -- quot )
-    [
-        [ , \ tag , ]
-        [ num-tags get swap [ bootstrap-type>class ] prepose map , ] bi*
-        \ dispatch ,
-    ] [ ] make ; inline
+SYMBOL: generic-word
+
+: make-math-method-table ( classes quot: ( class -- quot ) -- alist )
+    [ bootstrap-words ] dip
+    [ [ drop ] [ call ] 2bi ] curry { } map>assoc ; inline
+
+: math-alist>quot ( alist -- quot )
+    [ generic-word get object-method ] dip alist>quot ;
+
+: tag-dispatch-entry ( tag picker -- quot )
+    [ "type" word-prop 1quotation [ tag ] [ eq? ] surround ] dip prepend ;
+
+: tag-dispatch ( picker alist -- alist' )
+    swap [ [ tag-dispatch-entry ] curry dip ] curry assoc-map math-alist>quot ;
+
+: tuple-dispatch-entry ( class picker -- quot )
+    [ 1quotation [ { tuple } declare class ] [ eq? ] surround ] dip prepend ;
+
+: tuple-dispatch ( picker alist -- alist' )
+    swap [ [ tuple-dispatch-entry ] curry dip ] curry assoc-map math-alist>quot ;
+
+: math-dispatch-step ( picker quot: ( class -- quot ) -- quot )
+    [ [ { bignum float fixnum } ] dip make-math-method-table ]
+    [ [ { ratio complex } ] dip make-math-method-table tuple-dispatch ] 2bi
+    tuple swap 2array prefix tag-dispatch ; inline
+
+PRIVATE>
 
 SINGLETON: math-combination
 
@@ -78,20 +108,21 @@ M: math-combination make-default-method
     drop default-math-method ;
 
 M: math-combination perform-combination
-    drop
-    dup
-    [
-        [ 2dup both-fixnums? ] %
-        dup fixnum bootstrap-word dup math-method ,
-        \ over [
-            dup math-class? [
-                \ dup [ [ 2dup ] dip math-method ] math-vtable
-            ] [
-                over object-method
-            ] if nip
-        ] math-vtable nip ,
-        \ if ,
-    ] [ ] make define ;
+    drop dup generic-word [
+        dup
+        [ fixnum bootstrap-word dup math-method ]
+        [
+            [ over ] [
+                dup math-class? [
+                    [ dup ] [ math-method ] with with math-dispatch-step
+                ] [
+                    drop object-method
+                ] if
+            ] with math-dispatch-step
+        ] bi
+        [ if ] 2curry [ 2dup both-fixnums? ] prepend
+        define
+    ] with-variable ;
 
 PREDICATE: math-generic < generic ( word -- ? )
     "combination" word-prop math-combination? ;
diff --git a/core/generic/single/authors.txt b/core/generic/single/authors.txt
new file mode 100644 (file)
index 0000000..d4f5d6b
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
\ No newline at end of file
diff --git a/core/generic/single/single-docs.factor b/core/generic/single/single-docs.factor
new file mode 100644 (file)
index 0000000..8f81be7
--- /dev/null
@@ -0,0 +1,27 @@
+USING: generic help.markup help.syntax sequences math
+math.parser effects ;
+IN: generic.single
+
+HELP: no-method
+{ $values { "object" "an object" } { "generic" "a generic word" } }
+{ $description "Throws a " { $link no-method } " error." }
+{ $error-description "Thrown by the " { $snippet "generic" } " word to indicate it does not have a method for the class of " { $snippet "object" } "." } ;
+
+HELP: inconsistent-next-method
+{ $error-description "Thrown by " { $link POSTPONE: call-next-method } " if the values on the stack are not compatible with the current method." }
+{ $examples
+    "The following code throws this error:"
+    { $code
+        "GENERIC: error-test ( object -- )"
+        ""
+        "M: string error-test print ;"
+        ""
+        "M: integer error-test number>string call-next-method ;"
+        ""
+        "123 error-test"
+    }
+    "This results in the method on " { $link integer } " being called, which then passes a string to " { $link POSTPONE: call-next-method } ". However, this fails because the string is not compatible with the current method."
+    $nl
+    "This usually indicates programmer error; if the intention above was to call the string method on the result of " { $link number>string } ", the code should be rewritten as follows:"
+    { $code "M: integer error-test number>string error-test ;" }
+} ;
\ No newline at end of file
diff --git a/core/generic/single/single-tests.factor b/core/generic/single/single-tests.factor
new file mode 100644 (file)
index 0000000..c8cab97
--- /dev/null
@@ -0,0 +1,277 @@
+IN: generic.single.tests
+USING: tools.test math math.functions math.constants generic.standard
+generic.single strings sequences arrays kernel accessors words
+specialized-arrays.double byte-arrays bit-arrays parser namespaces
+make quotations stack-checker vectors growable hashtables sbufs
+prettyprint byte-vectors bit-vectors specialized-vectors.double
+definitions generic sets graphs assocs grouping see eval ;
+
+GENERIC: lo-tag-test ( obj -- obj' )
+
+M: integer lo-tag-test 3 + ;
+
+M: float lo-tag-test 4 - ;
+
+M: rational lo-tag-test 2 - ;
+
+M: complex lo-tag-test sq ;
+
+[ 8 ] [ 5 >bignum lo-tag-test ] unit-test
+[ 0.0 ] [ 4.0 lo-tag-test ] unit-test
+[ -1/2 ] [ 1+1/2 lo-tag-test ] unit-test
+[ -16 ] [ C{ 0 4 } lo-tag-test ] unit-test
+
+GENERIC: hi-tag-test ( obj -- obj' )
+
+M: string hi-tag-test ", in bed" append ;
+
+M: integer hi-tag-test 3 + ;
+
+M: array hi-tag-test [ hi-tag-test ] map ;
+
+M: sequence hi-tag-test reverse ;
+
+[ B{ 3 2 1 } ] [ B{ 1 2 3 } hi-tag-test ] unit-test
+
+[ { 6 9 12 } ] [ { 3 6 9 } hi-tag-test ] unit-test
+
+[ "i like monkeys, in bed" ] [ "i like monkeys" hi-tag-test ] unit-test
+
+TUPLE: shape ;
+
+TUPLE: abstract-rectangle < shape width height ;
+
+TUPLE: rectangle < abstract-rectangle ;
+
+C: <rectangle> rectangle
+
+TUPLE: parallelogram < abstract-rectangle skew ;
+
+C: <parallelogram> parallelogram
+
+TUPLE: circle < shape radius ;
+
+C: <circle> circle
+
+GENERIC: area ( shape -- n )
+
+M: abstract-rectangle area [ width>> ] [ height>> ] bi * ;
+
+M: circle area radius>> sq pi * ;
+
+[ 12 ] [ 4 3 <rectangle> area ] unit-test
+[ 12 ] [ 4 3 2 <parallelogram> area ] unit-test
+[ t ] [ 2 <circle> area 4 pi * = ] unit-test
+
+GENERIC: perimiter ( shape -- n )
+
+: rectangle-perimiter ( l w -- n ) + 2 * ;
+
+M: rectangle perimiter
+    [ width>> ] [ height>> ] bi
+    rectangle-perimiter ;
+
+: hypotenuse ( a b -- c ) [ sq ] bi@ + sqrt ;
+
+M: parallelogram perimiter
+    [ width>> ]
+    [ [ height>> ] [ skew>> ] bi hypotenuse ] bi
+    rectangle-perimiter ;
+
+M: circle perimiter 2 * pi * ;
+
+[ 14 ] [ 4 3 <rectangle> perimiter ] unit-test
+[ 30.0 ] [ 10 4 3 <parallelogram> perimiter ] unit-test
+
+GENERIC: big-mix-test ( obj -- obj' )
+
+M: object big-mix-test drop "object" ;
+
+M: tuple big-mix-test drop "tuple" ;
+
+M: integer big-mix-test drop "integer" ;
+
+M: float big-mix-test drop "float" ;
+
+M: complex big-mix-test drop "complex" ;
+
+M: string big-mix-test drop "string" ;
+
+M: array big-mix-test drop "array" ;
+
+M: sequence big-mix-test drop "sequence" ;
+
+M: rectangle big-mix-test drop "rectangle" ;
+
+M: parallelogram big-mix-test drop "parallelogram" ;
+
+M: circle big-mix-test drop "circle" ;
+
+[ "integer" ] [ 3 big-mix-test ] unit-test
+[ "float" ] [ 5.0 big-mix-test ] unit-test
+[ "complex" ] [ -1 sqrt big-mix-test ] unit-test
+[ "sequence" ] [ double-array{ 1.0 2.0 3.0 } big-mix-test ] unit-test
+[ "sequence" ] [ B{ 1 2 3 } big-mix-test ] unit-test
+[ "sequence" ] [ ?{ t f t } big-mix-test ] unit-test
+[ "sequence" ] [ SBUF" hello world" big-mix-test ] unit-test
+[ "sequence" ] [ V{ "a" "b" } big-mix-test ] unit-test
+[ "sequence" ] [ BV{ 1 2 } big-mix-test ] unit-test
+[ "sequence" ] [ ?V{ t t f f } big-mix-test ] unit-test
+[ "sequence" ] [ double-vector{ -0.3 4.6 } big-mix-test ] unit-test
+[ "string" ] [ "hello" big-mix-test ] unit-test
+[ "rectangle" ] [ 1 2 <rectangle> big-mix-test ] unit-test
+[ "parallelogram" ] [ 10 4 3 <parallelogram> big-mix-test ] unit-test
+[ "circle" ] [ 100 <circle> big-mix-test ] unit-test
+[ "tuple" ] [ H{ } big-mix-test ] unit-test
+[ "object" ] [ \ + big-mix-test ] unit-test
+
+GENERIC: small-lo-tag ( obj -- obj )
+
+M: fixnum small-lo-tag drop "fixnum" ;
+
+M: string small-lo-tag drop "string" ;
+
+M: array small-lo-tag drop "array" ;
+
+M: double-array small-lo-tag drop "double-array" ;
+
+M: byte-array small-lo-tag drop "byte-array" ;
+
+[ "fixnum" ] [ 3 small-lo-tag ] unit-test
+
+[ "double-array" ] [ double-array{ 1.0 } small-lo-tag ] unit-test
+
+! Testing next-method
+TUPLE: person ;
+
+TUPLE: intern < person ;
+
+TUPLE: employee < person ;
+
+TUPLE: tape-monkey < employee ;
+
+TUPLE: manager < employee ;
+
+TUPLE: junior-manager < manager ;
+
+TUPLE: middle-manager < manager ;
+
+TUPLE: senior-manager < manager ;
+
+TUPLE: executive < senior-manager ;
+
+TUPLE: ceo < executive ;
+
+GENERIC: salary ( person -- n )
+
+M: intern salary
+    #! Intentional mistake.
+    call-next-method ;
+
+M: employee salary drop 24000 ;
+
+M: manager salary call-next-method 12000 + ;
+
+M: middle-manager salary call-next-method 5000 + ;
+
+M: senior-manager salary call-next-method 15000 + ;
+
+M: executive salary call-next-method 2 * ;
+
+M: ceo salary
+    #! Intentional error.
+    drop 5 call-next-method 3 * ;
+
+[ salary ] must-infer
+
+[ 24000 ] [ employee boa salary ] unit-test
+
+[ 24000 ] [ tape-monkey boa salary ] unit-test
+
+[ 36000 ] [ junior-manager boa salary ] unit-test
+
+[ 41000 ] [ middle-manager boa salary ] unit-test
+
+[ 51000 ] [ senior-manager boa salary ] unit-test
+
+[ 102000 ] [ executive boa salary ] unit-test
+
+[ ceo boa salary ]
+[ T{ inconsistent-next-method f ceo salary } = ] must-fail-with
+
+[ intern boa salary ]
+[ no-next-method? ] must-fail-with
+
+! Weird shit
+TUPLE: a ;
+TUPLE: b ;
+TUPLE: c ;
+
+UNION: x a b ;
+UNION: y a c ;
+
+UNION: z x y ;
+
+GENERIC: funky* ( obj -- )
+
+M: z funky* "z" , drop ;
+
+M: x funky* "x" , call-next-method ;
+
+M: y funky* "y" , call-next-method ;
+
+M: a funky* "a" , call-next-method ;
+
+M: b funky* "b" , call-next-method ;
+
+M: c funky* "c" , call-next-method ;
+
+: funky ( obj -- seq ) [ funky* ] { } make ;
+
+[ { "b" "x" "z" } ] [ T{ b } funky ] unit-test
+
+[ { "c" "y" "z" } ] [ T{ c } funky ] unit-test
+
+[ t ] [
+    T{ a } funky
+    { { "a" "x" "z" } { "a" "y" "z" } } member?
+] unit-test
+
+! Hooks
+SYMBOL: my-var
+HOOK: my-hook my-var ( -- x )
+
+M: integer my-hook "an integer" ;
+M: string my-hook "a string" ;
+
+[ "an integer" ] [ 3 my-var set my-hook ] unit-test
+[ "a string" ] [ my-hook my-var set my-hook ] unit-test
+[ 1.0 my-var set my-hook ] [ T{ no-method f 1.0 my-hook } = ] must-fail-with
+
+HOOK: call-next-hooker my-var ( -- x )
+
+M: sequence call-next-hooker "sequence" ;
+
+M: array call-next-hooker call-next-method "array " prepend ;
+
+M: vector call-next-hooker call-next-method "vector " prepend ;
+
+M: growable call-next-hooker call-next-method "growable " prepend ;
+
+[ "vector growable sequence" ] [
+    V{ } my-var [ call-next-hooker ] with-variable
+] unit-test
+
+[ t ] [
+    { } \ nth effective-method nip M\ sequence nth eq?
+] unit-test
+
+[ t ] [
+    \ + \ nth effective-method nip dup \ nth "default-method" word-prop eq? and
+] unit-test
+
+[ ] [ "IN: generic.single.tests GENERIC: xyz ( a -- b )" eval( -- ) ] unit-test
+[ ] [ "IN: generic.single.tests MATH: xyz ( a b -- c )" eval( -- ) ] unit-test
+
+[ f ] [ "xyz" "generic.single.tests" lookup direct-entry-def>> ] unit-test
+[ f ] [ "xyz" "generic.single.tests" lookup "decision-tree" word-prop ] unit-test
\ No newline at end of file
diff --git a/core/generic/single/single.factor b/core/generic/single/single.factor
new file mode 100644 (file)
index 0000000..4fe9ce5
--- /dev/null
@@ -0,0 +1,256 @@
+! Copyright (C) 2009 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors arrays assocs classes classes.algebra
+combinators definitions generic hashtables kernel
+kernel.private layouts math namespaces quotations
+sequences words generic.single.private effects make ;
+IN: generic.single
+
+ERROR: no-method object generic ;
+
+ERROR: inconsistent-next-method class generic ;
+
+TUPLE: single-combination ;
+
+PREDICATE: single-generic < generic
+    "combination" word-prop single-combination? ;
+
+GENERIC: dispatch# ( word -- n )
+
+M: generic dispatch# "combination" word-prop dispatch# ;
+
+SYMBOL: assumed
+SYMBOL: default
+SYMBOL: generic-word
+SYMBOL: combination
+
+: with-combination ( combination quot -- )
+    [ combination ] dip with-variable ; inline
+
+HOOK: picker combination ( -- quot )
+
+M: single-combination next-method-quot* ( class generic combination -- quot )
+    [
+        2dup next-method dup [
+            [
+                pick "predicate" word-prop %
+                1quotation ,
+                [ inconsistent-next-method ] 2curry ,
+                \ if ,
+            ] [ ] make picker prepend
+        ] [ 3drop f ] if
+    ] with-combination ;
+
+: (effective-method) ( obj word -- method )
+    [ [ order [ instance? ] with find-last nip ] keep method ]
+    [ "default-method" word-prop ]
+    bi or ;
+
+M: single-combination make-default-method
+    [ [ picker ] dip [ no-method ] curry append ] with-combination ;
+
+! ! ! Build an engine ! ! !
+
+: find-default ( methods -- default )
+    #! Side-effects methods.
+    [ object bootstrap-word ] dip delete-at* [
+        drop generic-word get "default-method" word-prop
+    ] unless ;
+
+! 1. Flatten methods
+TUPLE: predicate-engine methods ;
+
+: <predicate-engine> ( methods -- engine ) predicate-engine boa ;
+
+: push-method ( method specializer atomic assoc -- )
+    [
+        [ H{ } clone <predicate-engine> ] unless*
+        [ methods>> set-at ] keep
+    ] change-at ;
+
+: flatten-method ( class method assoc -- )
+    [ [ flatten-class keys ] keep ] 2dip [
+        [ spin ] dip push-method
+    ] 3curry each ;
+
+: flatten-methods ( assoc -- assoc' )
+    H{ } clone [ [ flatten-method ] curry assoc-each ] keep ;
+
+! 2. Convert methods
+: split-methods ( assoc class -- first second )
+    [ [ nip class<= not ] curry assoc-filter ]
+    [ [ nip class<=     ] curry assoc-filter ] 2bi ;
+
+: convert-methods ( assoc class word -- assoc' )
+    over [ split-methods ] 2dip pick assoc-empty?
+    [ 3drop ] [ [ execute ] dip pick set-at ] if ; inline
+
+! 2.1 Convert tuple methods
+TUPLE: echelon-dispatch-engine n methods ;
+
+C: <echelon-dispatch-engine> echelon-dispatch-engine
+
+TUPLE: tuple-dispatch-engine echelons ;
+
+: push-echelon ( class method assoc -- )
+    [ swap dup "layout" word-prop third ] dip
+    [ ?set-at ] change-at ;
+
+: echelon-sort ( assoc -- assoc' )
+    #! Convert an assoc mapping classes to methods into an
+    #! assoc mapping echelons to assocs. The first echelon
+    #! is always there
+    H{ { 0 f } } clone [ [ push-echelon ] curry assoc-each ] keep ;
+
+: <tuple-dispatch-engine> ( methods -- engine )
+    echelon-sort
+    [ dupd <echelon-dispatch-engine> ] assoc-map
+    \ tuple-dispatch-engine boa ;
+
+: convert-tuple-methods ( assoc -- assoc' )
+    tuple bootstrap-word
+    \ <tuple-dispatch-engine> convert-methods ;
+
+! 2.2 Convert hi-tag methods
+TUPLE: hi-tag-dispatch-engine methods ;
+
+C: <hi-tag-dispatch-engine> hi-tag-dispatch-engine
+
+: convert-hi-tag-methods ( assoc -- assoc' )
+    \ hi-tag bootstrap-word
+    \ <hi-tag-dispatch-engine> convert-methods ;
+
+! 3 Tag methods
+TUPLE: tag-dispatch-engine methods ;
+
+C: <tag-dispatch-engine> tag-dispatch-engine
+
+: <engine> ( assoc -- engine )
+    flatten-methods
+    convert-tuple-methods
+    convert-hi-tag-methods
+    <tag-dispatch-engine> ;
+
+! ! ! Compile engine ! ! !
+GENERIC: compile-engine ( engine -- obj )
+
+: compile-engines ( assoc -- assoc' )
+    [ compile-engine ] assoc-map ;
+
+: compile-engines* ( assoc -- assoc' )
+    [ over assumed [ compile-engine ] with-variable ] assoc-map ;
+
+: direct-dispatch-table ( assoc n -- table )
+    default get <array> [ <enum> swap update ] keep ;
+
+: lo-tag-number ( class -- n )
+    "type" word-prop dup num-tags get member?
+    [ drop object tag-number ] unless ;
+
+M: tag-dispatch-engine compile-engine
+    methods>> compile-engines*
+    [ [ lo-tag-number ] dip ] assoc-map
+    num-tags get direct-dispatch-table ;
+
+: num-hi-tags ( -- n ) num-types get num-tags get - ;
+
+: hi-tag-number ( class -- n ) "type" word-prop ;
+
+M: hi-tag-dispatch-engine compile-engine
+    methods>> compile-engines*
+    [ [ hi-tag-number num-tags get - ] dip ] assoc-map
+    num-hi-tags direct-dispatch-table ;
+
+: build-fast-hash ( methods -- buckets )
+    >alist V{ } clone [ hashcode 1array ] distribute-buckets
+    [ compile-engines* >alist >array ] map ;
+
+M: echelon-dispatch-engine compile-engine
+    dup n>> 0 = [
+        methods>> dup assoc-size {
+            { 0 [ drop default get ] }
+            { 1 [ >alist first second compile-engine ] }
+        } case
+    ] [
+        methods>> compile-engines* build-fast-hash
+    ] if ;
+
+M: tuple-dispatch-engine compile-engine
+    tuple assumed [
+        echelons>> compile-engines
+        dup keys supremum 1+ f <array>
+        [ <enum> swap update ] keep
+    ] with-variable ;
+
+: sort-methods ( assoc -- assoc' )
+    >alist [ keys sort-classes ] keep extract-keys ;
+
+: quote-methods ( assoc -- assoc' )
+    [ 1quotation \ drop prefix ] assoc-map ;
+
+: methods-with-default ( engine -- assoc )
+    methods>> clone default get object bootstrap-word pick set-at ;
+
+: keep-going? ( assoc -- ? )
+    assumed get swap second first class<= ;
+
+: prune-redundant-predicates ( assoc -- default assoc' )
+    {
+        { [ dup empty? ] [ drop [ "Unreachable" throw ] { } ] }
+        { [ dup length 1 = ] [ first second { } ] }
+        { [ dup keep-going? ] [ rest-slice prune-redundant-predicates ] }
+        [ [ first second ] [ rest-slice ] bi ]
+    } cond ;
+
+: class-predicates ( assoc -- assoc )
+    [ [ "predicate" word-prop [ dup ] prepend ] dip ] assoc-map ;
+
+PREDICATE: predicate-engine-word < word "owner-generic" word-prop ;
+
+: <predicate-engine-word> ( -- word )
+    generic-word get name>> "/predicate-engine" append f <word>
+    dup generic-word get "owner-generic" set-word-prop ;
+
+M: predicate-engine-word stack-effect "owner-generic" word-prop stack-effect ;
+
+: define-predicate-engine ( alist -- word )
+    [ <predicate-engine-word> ] dip
+    [ define ] [ drop generic-word get "engines" word-prop push ] [ drop ] 2tri ;
+
+M: predicate-engine compile-engine
+    methods-with-default
+    sort-methods
+    quote-methods
+    prune-redundant-predicates
+    class-predicates
+    [ peek ] [ alist>quot picker prepend define-predicate-engine ] if-empty ;
+
+M: word compile-engine ;
+
+M: f compile-engine ;
+
+: build-decision-tree ( generic -- methods )
+    [ "engines" word-prop forget-all ]
+    [ V{ } clone "engines" set-word-prop ]
+    [
+        "methods" word-prop clone
+        [ find-default default set ]
+        [ <engine> compile-engine ] bi
+    ] tri ;
+
+HOOK: inline-cache-quot combination ( word methods -- quot/f )
+
+: define-inline-cache-quot ( word methods -- )
+    [ drop ] [ inline-cache-quot ] 2bi >>direct-entry-def drop ;
+
+HOOK: mega-cache-quot combination ( methods -- quot/f )
+
+M: single-combination perform-combination
+    [
+        dup generic-word set
+        dup build-decision-tree
+        [ "decision-tree" set-word-prop ]
+        [ mega-cache-quot define ]
+        [ define-inline-cache-quot ]
+        2tri
+    ] with-combination ;
\ No newline at end of file
index 1901f27a24507e2512d93a1f956aaaa0d2f05714..d4f5d6b3aeb70f66356d80c70755fbb63ef584df 100644 (file)
@@ -1 +1 @@
-Slava Pestov
+Slava Pestov
\ No newline at end of file
diff --git a/core/generic/standard/engines/engines.factor b/core/generic/standard/engines/engines.factor
deleted file mode 100644 (file)
index b6cb9fc..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-! Copyright (C) 2008 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: assocs kernel kernel.private namespaces quotations
-generic math sequences combinators words classes.algebra arrays
-;
-IN: generic.standard.engines
-
-SYMBOL: default
-SYMBOL: assumed
-SYMBOL: (dispatch#)
-
-GENERIC: engine>quot ( engine -- quot )
-
-: engines>quots ( assoc -- assoc' )
-    [ engine>quot ] assoc-map ;
-
-: engines>quots* ( assoc -- assoc' )
-    [ over assumed [ engine>quot ] with-variable ] assoc-map ;
-
-: if-small? ( assoc true false -- )
-    [ dup assoc-size 4 <= ] 2dip if ; inline
-
-: linear-dispatch-quot ( alist -- quot )
-    default get [ drop ] prepend swap
-    [
-        [ [ dup ] swap [ eq? ] curry compose ]
-        [ [ drop ] prepose ]
-        bi* [ ] like
-    ] assoc-map
-    alist>quot ;
-
-: split-methods ( assoc class -- first second )
-    [ [ nip class<= not ] curry assoc-filter ]
-    [ [ nip class<=     ] curry assoc-filter ] 2bi ;
-
-: convert-methods ( assoc class word -- assoc' )
-    over [ split-methods ] 2dip pick assoc-empty? [
-        3drop
-    ] [
-        [ execute ] dip pick set-at
-    ] if ; inline
-
-: (picker) ( n -- quot )
-    {
-        { 0 [ [ dup ] ] }
-        { 1 [ [ over ] ] }
-        { 2 [ [ pick ] ] }
-        [ 1- (picker) [ dip swap ] curry ]
-    } case ;
-
-: picker ( -- quot ) \ (dispatch#) get (picker) ;
-
-GENERIC: extra-values ( generic -- n )
diff --git a/core/generic/standard/engines/predicate/predicate.factor b/core/generic/standard/engines/predicate/predicate.factor
deleted file mode 100644 (file)
index 152b112..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-! Copyright (C) 2008 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: generic.standard.engines generic namespaces kernel
-kernel.private sequences classes.algebra accessors words
-combinators assocs arrays ;
-IN: generic.standard.engines.predicate
-
-TUPLE: predicate-dispatch-engine methods ;
-
-C: <predicate-dispatch-engine> predicate-dispatch-engine
-
-: class-predicates ( assoc -- assoc )
-    [ [ "predicate" word-prop picker prepend ] dip ] assoc-map ;
-
-: keep-going? ( assoc -- ? )
-    assumed get swap second first class<= ;
-
-: prune-redundant-predicates ( assoc -- default assoc' )
-    {
-        { [ dup empty? ] [ drop [ "Unreachable" throw ] { } ] }
-        { [ dup length 1 = ] [ first second { } ] }
-        { [ dup keep-going? ] [ rest-slice prune-redundant-predicates ] }
-        [ [ first second ] [ rest-slice ] bi ]
-    } cond ;
-
-: sort-methods ( assoc -- assoc' )
-    >alist [ keys sort-classes ] keep extract-keys ;
-
-: methods-with-default ( engine -- assoc )
-    methods>> clone default get object bootstrap-word pick set-at ;
-
-M: predicate-dispatch-engine engine>quot
-    methods-with-default
-    engines>quots
-    sort-methods
-    prune-redundant-predicates
-    class-predicates
-    alist>quot ;
diff --git a/core/generic/standard/engines/predicate/summary.txt b/core/generic/standard/engines/predicate/summary.txt
deleted file mode 100644 (file)
index 47fee09..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Chained-conditional dispatch strategy
diff --git a/core/generic/standard/engines/summary.txt b/core/generic/standard/engines/summary.txt
deleted file mode 100644 (file)
index 2091907..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Generic word dispatch strategy implementation
diff --git a/core/generic/standard/engines/tag/summary.txt b/core/generic/standard/engines/tag/summary.txt
deleted file mode 100644 (file)
index 3eea4b1..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Jump table keyed by pointer tag dispatch strategy
diff --git a/core/generic/standard/engines/tag/tag.factor b/core/generic/standard/engines/tag/tag.factor
deleted file mode 100644 (file)
index 5ed3300..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-! Copyright (C) 2008 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: classes.private generic.standard.engines namespaces make
-arrays assocs sequences.private quotations kernel.private
-math slots.private math.private kernel accessors words
-layouts sorting sequences combinators ;
-IN: generic.standard.engines.tag
-
-TUPLE: lo-tag-dispatch-engine methods ;
-
-C: <lo-tag-dispatch-engine> lo-tag-dispatch-engine
-
-: direct-dispatch-quot ( alist n -- quot )
-    default get <array>
-    [ <enum> swap update ] keep
-    [ dispatch ] curry >quotation ;
-
-: lo-tag-number ( class -- n )
-     dup \ hi-tag bootstrap-word eq? [
-        drop \ hi-tag tag-number
-    ] [
-        "type" word-prop
-    ] if ;
-
-: sort-tags ( assoc -- alist ) >alist sort-keys reverse ;
-
-: tag-dispatch-test ( tag# -- quot )
-    picker [ tag ] append swap [ eq? ] curry append ;
-
-: tag-dispatch-quot ( alist -- quot )
-    [ default get ] dip
-    [ [ tag-dispatch-test ] dip ] assoc-map
-    alist>quot ;
-
-M: lo-tag-dispatch-engine engine>quot
-    methods>> engines>quots*
-    [ [ lo-tag-number ] dip ] assoc-map
-    [
-        [ sort-tags tag-dispatch-quot ]
-        [ picker % [ tag ] % num-tags get direct-dispatch-quot ]
-        if-small? %
-    ] [ ] make ;
-
-TUPLE: hi-tag-dispatch-engine methods ;
-
-C: <hi-tag-dispatch-engine> hi-tag-dispatch-engine
-
-: convert-hi-tag-methods ( assoc -- assoc' )
-    \ hi-tag bootstrap-word
-    \ <hi-tag-dispatch-engine> convert-methods ;
-
-: num-hi-tags ( -- n ) num-types get num-tags get - ;
-
-: hi-tag-number ( class -- n )
-    "type" word-prop ;
-
-: hi-tag-quot ( -- quot )
-    \ hi-tag def>> ;
-
-M: hi-tag-dispatch-engine engine>quot
-    methods>> engines>quots*
-    [ [ hi-tag-number ] dip ] assoc-map
-    [
-        picker % hi-tag-quot % [
-            sort-tags linear-dispatch-quot
-        ] [
-            num-tags get , \ fixnum-fast ,
-            [ [ num-tags get - ] dip ] assoc-map
-            num-hi-tags direct-dispatch-quot
-        ] if-small? %
-    ] [ ] make ;
diff --git a/core/generic/standard/engines/tuple/summary.txt b/core/generic/standard/engines/tuple/summary.txt
deleted file mode 100644 (file)
index cb18ac5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Tuple class dispatch strategy
diff --git a/core/generic/standard/engines/tuple/tuple.factor b/core/generic/standard/engines/tuple/tuple.factor
deleted file mode 100644 (file)
index a0711af..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-! Copyright (c) 2008 Slava Pestov
-! See http://factorcode.org/license.txt for BSD license.
-USING: kernel classes.tuple.private hashtables assocs sorting
-accessors combinators sequences slots.private math.parser words
-effects namespaces make generic generic.standard.engines
-classes.algebra math math.private kernel.private
-quotations arrays definitions ;
-IN: generic.standard.engines.tuple
-
-: nth-superclass% ( n -- ) 2 * 5 + , \ slot , ; inline
-
-: nth-hashcode% ( n -- ) 2 * 6 + , \ slot , ; inline
-
-: tuple-layout% ( -- )
-    [ { tuple } declare 1 slot { array } declare ] % ; inline
-
-: tuple-layout-echelon% ( -- )
-    [ 4 slot ] % ; inline
-
-TUPLE: echelon-dispatch-engine n methods ;
-
-C: <echelon-dispatch-engine> echelon-dispatch-engine
-
-TUPLE: trivial-tuple-dispatch-engine n methods ;
-
-C: <trivial-tuple-dispatch-engine> trivial-tuple-dispatch-engine
-
-TUPLE: tuple-dispatch-engine echelons ;
-
-: push-echelon ( class method assoc -- )
-    [ swap dup "layout" word-prop third ] dip
-    [ ?set-at ] change-at ;
-
-: echelon-sort ( assoc -- assoc' )
-    V{ } clone [
-        [
-            push-echelon
-        ] curry assoc-each
-    ] keep sort-keys ;
-
-: <tuple-dispatch-engine> ( methods -- engine )
-    echelon-sort
-    [ dupd <echelon-dispatch-engine> ] assoc-map
-    \ tuple-dispatch-engine boa ;
-
-: convert-tuple-methods ( assoc -- assoc' )
-    tuple bootstrap-word
-    \ <tuple-dispatch-engine> convert-methods ;
-
-M: trivial-tuple-dispatch-engine engine>quot
-    [ n>> ] [ methods>> ] bi dup assoc-empty? [
-        2drop default get [ drop ] prepend
-    ] [
-        [
-            [ nth-superclass% ]
-            [ engines>quots* linear-dispatch-quot % ] bi*
-        ] [ ] make
-    ] if ;
-
-: hash-methods ( n methods -- buckets )
-    >alist V{ } clone [ hashcode 1array ] distribute-buckets
-    [ <trivial-tuple-dispatch-engine> ] with map ;
-
-: class-hash-dispatch-quot ( n methods -- quot )
-    [
-        \ dup ,
-        [ drop nth-hashcode% ]
-        [ hash-methods [ engine>quot ] map hash-dispatch-quot % ] 2bi
-    ] [ ] make ;
-
-: engine-word-name ( -- string )
-    generic get name>> "/tuple-dispatch-engine" append ;
-
-PREDICATE: engine-word < word
-    "tuple-dispatch-generic" word-prop generic? ;
-
-M: engine-word stack-effect
-    "tuple-dispatch-generic" word-prop
-    [ extra-values ] [ stack-effect ] bi
-    dup [
-        [ in>> length + ] [ out>> ] [ terminated?>> ] tri
-        effect boa
-    ] [ 2drop f ] if ;
-
-M: engine-word where "tuple-dispatch-generic" word-prop where ;
-
-M: engine-word crossref? "forgotten" word-prop not ;
-
-: remember-engine ( word -- )
-    generic get "engines" word-prop push ;
-
-: <engine-word> ( -- word )
-    engine-word-name f <word>
-    dup generic get "tuple-dispatch-generic" set-word-prop ;
-
-: define-engine-word ( quot -- word )
-    [ <engine-word> dup ] dip define ;
-
-: tuple-dispatch-engine-body ( engine -- quot )
-    [
-        picker %
-        tuple-layout%
-        [ n>> ] [ methods>> ] bi
-        [ <trivial-tuple-dispatch-engine> engine>quot ]
-        [ class-hash-dispatch-quot ]
-        if-small? %
-    ] [ ] make ;
-
-M: echelon-dispatch-engine engine>quot
-    dup n>> zero? [
-        methods>> dup assoc-empty?
-        [ drop default get ] [ values first engine>quot ] if
-    ] [
-        tuple-dispatch-engine-body
-    ] if ;
-
-: >=-case-quot ( default alist -- quot )
-    [ [ drop ] prepend ] dip
-    [
-        [ [ dup ] swap [ fixnum>= ] curry compose ]
-        [ [ drop ] prepose ]
-        bi* [ ] like
-    ] assoc-map
-    alist>quot ;
-
-: simplify-echelon-alist ( default alist -- default' alist' )
-    dup empty? [
-        dup first first 1 <= [
-            nip unclip second swap
-            simplify-echelon-alist
-        ] when
-    ] unless ;
-
-: echelon-case-quot ( alist -- quot )
-    #! We don't have to test for echelon 1 since all tuple
-    #! classes are at least at depth 1 in the inheritance
-    #! hierarchy.
-    default get swap simplify-echelon-alist
-    [
-        [
-            picker %
-            tuple-layout%
-            tuple-layout-echelon%
-            >=-case-quot %
-        ] [ ] make
-    ] unless-empty ;
-
-M: tuple-dispatch-engine engine>quot
-    [
-        [
-            tuple assumed set
-            echelons>> unclip-last
-            [
-                [
-                    engine>quot
-                    over 0 = [
-                        define-engine-word
-                        [ remember-engine ] [ 1quotation ] bi
-                    ] unless
-                    dup default set
-                ] assoc-map
-            ]
-            [ first2 engine>quot 2array ] bi*
-            suffix
-        ] with-scope
-        echelon-case-quot %
-    ] [ ] make ;
index 6e788eb947e26984a203189a3d1a8e0dc21e4ea7..33da0037b375db9dc9915ec05a62d58f2cc8f2de 100644 (file)
@@ -1,12 +1,7 @@
-USING: generic help.markup help.syntax sequences math
+USING: generic generic.single help.markup help.syntax sequences math
 math.parser effects ;
 IN: generic.standard
 
-HELP: no-method
-{ $values { "object" "an object" } { "generic" "a generic word" } }
-{ $description "Throws a " { $link no-method } " error." }
-{ $error-description "Thrown by the " { $snippet "generic" } " word to indicate it does not have a method for the class of " { $snippet "object" } "." } ;
-
 HELP: standard-combination
 { $class-description
     "Performs standard method combination."
@@ -22,32 +17,6 @@ HELP: standard-combination
     }
 } ;
 
-HELP: hook-combination
-{ $class-description
-    "Performs hook method combination . See " { $link POSTPONE: HOOK: } "."
-} ;
-
 HELP: define-simple-generic
 { $values { "word" "a word" } { "effect" effect } }
-{ $description "Defines a generic word with the " { $link standard-combination } " method combination and a dispatch position of 0." } ;
-
-{ standard-combination hook-combination } related-words
-
-HELP: inconsistent-next-method
-{ $error-description "Thrown by " { $link POSTPONE: call-next-method } " if the values on the stack are not compatible with the current method." }
-{ $examples
-    "The following code throws this error:"
-    { $code
-        "GENERIC: error-test ( object -- )"
-        ""
-        "M: string error-test print ;"
-        ""
-        "M: integer error-test number>string call-next-method ;"
-        ""
-        "123 error-test"
-    }
-    "This results in the method on " { $link integer } " being called, which then passes a string to " { $link POSTPONE: call-next-method } ". However, this fails because the string is not compatible with the current method."
-    $nl
-    "This usually indicates programmer error; if the intention above was to call the string method on the result of " { $link number>string } ", the code should be rewritten as follows:"
-    { $code "M: integer error-test number>string error-test ;" }
-} ;
+{ $description "Defines a generic word with the " { $link standard-combination } " method combination and a dispatch position of 0." } ;
\ No newline at end of file
diff --git a/core/generic/standard/standard-tests.factor b/core/generic/standard/standard-tests.factor
deleted file mode 100644 (file)
index 58007f7..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-IN: generic.standard.tests
-USING: tools.test math math.functions math.constants
-generic.standard strings sequences arrays kernel accessors words
-specialized-arrays.double byte-arrays bit-arrays parser
-namespaces make quotations stack-checker vectors growable
-hashtables sbufs prettyprint byte-vectors bit-vectors
-specialized-vectors.double definitions generic sets graphs assocs
-grouping see ;
-
-GENERIC: lo-tag-test ( obj -- obj' )
-
-M: integer lo-tag-test 3 + ;
-
-M: float lo-tag-test 4 - ;
-
-M: rational lo-tag-test 2 - ;
-
-M: complex lo-tag-test sq ;
-
-[ 8 ] [ 5 >bignum lo-tag-test ] unit-test
-[ 0.0 ] [ 4.0 lo-tag-test ] unit-test
-[ -1/2 ] [ 1+1/2 lo-tag-test ] unit-test
-[ -16 ] [ C{ 0 4 } lo-tag-test ] unit-test
-
-GENERIC: hi-tag-test ( obj -- obj' )
-
-M: string hi-tag-test ", in bed" append ;
-
-M: integer hi-tag-test 3 + ;
-
-M: array hi-tag-test [ hi-tag-test ] map ;
-
-M: sequence hi-tag-test reverse ;
-
-[ B{ 3 2 1 } ] [ B{ 1 2 3 } hi-tag-test ] unit-test
-
-[ { 6 9 12 } ] [ { 3 6 9 } hi-tag-test ] unit-test
-
-[ "i like monkeys, in bed" ] [ "i like monkeys" hi-tag-test ] unit-test
-
-TUPLE: shape ;
-
-TUPLE: abstract-rectangle < shape width height ;
-
-TUPLE: rectangle < abstract-rectangle ;
-
-C: <rectangle> rectangle
-
-TUPLE: parallelogram < abstract-rectangle skew ;
-
-C: <parallelogram> parallelogram
-
-TUPLE: circle < shape radius ;
-
-C: <circle> circle
-
-GENERIC: area ( shape -- n )
-
-M: abstract-rectangle area [ width>> ] [ height>> ] bi * ;
-
-M: circle area radius>> sq pi * ;
-
-[ 12 ] [ 4 3 <rectangle> area ] unit-test
-[ 12 ] [ 4 3 2 <parallelogram> area ] unit-test
-[ t ] [ 2 <circle> area 4 pi * = ] unit-test
-
-GENERIC: perimiter ( shape -- n )
-
-: rectangle-perimiter ( l w -- n ) + 2 * ;
-
-M: rectangle perimiter
-    [ width>> ] [ height>> ] bi
-    rectangle-perimiter ;
-
-: hypotenuse ( a b -- c ) [ sq ] bi@ + sqrt ;
-
-M: parallelogram perimiter
-    [ width>> ]
-    [ [ height>> ] [ skew>> ] bi hypotenuse ] bi
-    rectangle-perimiter ;
-
-M: circle perimiter 2 * pi * ;
-
-[ 14 ] [ 4 3 <rectangle> perimiter ] unit-test
-[ 30.0 ] [ 10 4 3 <parallelogram> perimiter ] unit-test
-
-GENERIC: big-mix-test ( obj -- obj' )
-
-M: object big-mix-test drop "object" ;
-
-M: tuple big-mix-test drop "tuple" ;
-
-M: integer big-mix-test drop "integer" ;
-
-M: float big-mix-test drop "float" ;
-
-M: complex big-mix-test drop "complex" ;
-
-M: string big-mix-test drop "string" ;
-
-M: array big-mix-test drop "array" ;
-
-M: sequence big-mix-test drop "sequence" ;
-
-M: rectangle big-mix-test drop "rectangle" ;
-
-M: parallelogram big-mix-test drop "parallelogram" ;
-
-M: circle big-mix-test drop "circle" ;
-
-[ "integer" ] [ 3 big-mix-test ] unit-test
-[ "float" ] [ 5.0 big-mix-test ] unit-test
-[ "complex" ] [ -1 sqrt big-mix-test ] unit-test
-[ "sequence" ] [ double-array{ 1.0 2.0 3.0 } big-mix-test ] unit-test
-[ "sequence" ] [ B{ 1 2 3 } big-mix-test ] unit-test
-[ "sequence" ] [ ?{ t f t } big-mix-test ] unit-test
-[ "sequence" ] [ SBUF" hello world" big-mix-test ] unit-test
-[ "sequence" ] [ V{ "a" "b" } big-mix-test ] unit-test
-[ "sequence" ] [ BV{ 1 2 } big-mix-test ] unit-test
-[ "sequence" ] [ ?V{ t t f f } big-mix-test ] unit-test
-[ "sequence" ] [ double-vector{ -0.3 4.6 } big-mix-test ] unit-test
-[ "string" ] [ "hello" big-mix-test ] unit-test
-[ "rectangle" ] [ 1 2 <rectangle> big-mix-test ] unit-test
-[ "parallelogram" ] [ 10 4 3 <parallelogram> big-mix-test ] unit-test
-[ "circle" ] [ 100 <circle> big-mix-test ] unit-test
-[ "tuple" ] [ H{ } big-mix-test ] unit-test
-[ "object" ] [ \ + big-mix-test ] unit-test
-
-GENERIC: small-lo-tag ( obj -- obj )
-
-M: fixnum small-lo-tag drop "fixnum" ;
-
-M: string small-lo-tag drop "string" ;
-
-M: array small-lo-tag drop "array" ;
-
-M: double-array small-lo-tag drop "double-array" ;
-
-M: byte-array small-lo-tag drop "byte-array" ;
-
-[ "fixnum" ] [ 3 small-lo-tag ] unit-test
-
-[ "double-array" ] [ double-array{ 1.0 } small-lo-tag ] unit-test
-
-! Testing next-method
-TUPLE: person ;
-
-TUPLE: intern < person ;
-
-TUPLE: employee < person ;
-
-TUPLE: tape-monkey < employee ;
-
-TUPLE: manager < employee ;
-
-TUPLE: junior-manager < manager ;
-
-TUPLE: middle-manager < manager ;
-
-TUPLE: senior-manager < manager ;
-
-TUPLE: executive < senior-manager ;
-
-TUPLE: ceo < executive ;
-
-GENERIC: salary ( person -- n )
-
-M: intern salary
-    #! Intentional mistake.
-    call-next-method ;
-
-M: employee salary drop 24000 ;
-
-M: manager salary call-next-method 12000 + ;
-
-M: middle-manager salary call-next-method 5000 + ;
-
-M: senior-manager salary call-next-method 15000 + ;
-
-M: executive salary call-next-method 2 * ;
-
-M: ceo salary
-    #! Intentional error.
-    drop 5 call-next-method 3 * ;
-
-[ salary ] must-infer
-
-[ 24000 ] [ employee boa salary ] unit-test
-
-[ 24000 ] [ tape-monkey boa salary ] unit-test
-
-[ 36000 ] [ junior-manager boa salary ] unit-test
-
-[ 41000 ] [ middle-manager boa salary ] unit-test
-
-[ 51000 ] [ senior-manager boa salary ] unit-test
-
-[ 102000 ] [ executive boa salary ] unit-test
-
-[ ceo boa salary ]
-[ T{ inconsistent-next-method f ceo salary } = ] must-fail-with
-
-[ intern boa salary ]
-[ no-next-method? ] must-fail-with
-
-! Weird shit
-TUPLE: a ;
-TUPLE: b ;
-TUPLE: c ;
-
-UNION: x a b ;
-UNION: y a c ;
-
-UNION: z x y ;
-
-GENERIC: funky* ( obj -- )
-
-M: z funky* "z" , drop ;
-
-M: x funky* "x" , call-next-method ;
-
-M: y funky* "y" , call-next-method ;
-
-M: a funky* "a" , call-next-method ;
-
-M: b funky* "b" , call-next-method ;
-
-M: c funky* "c" , call-next-method ;
-
-: funky ( obj -- seq ) [ funky* ] { } make ;
-
-[ { "b" "x" "z" } ] [ T{ b } funky ] unit-test
-
-[ { "c" "y" "z" } ] [ T{ c } funky ] unit-test
-
-[ t ] [
-    T{ a } funky
-    { { "a" "x" "z" } { "a" "y" "z" } } member?
-] unit-test
-
-! Hooks
-SYMBOL: my-var
-HOOK: my-hook my-var ( -- x )
-
-M: integer my-hook "an integer" ;
-M: string my-hook "a string" ;
-
-[ "an integer" ] [ 3 my-var set my-hook ] unit-test
-[ "a string" ] [ my-hook my-var set my-hook ] unit-test
-[ 1.0 my-var set my-hook ] [ T{ no-method f 1.0 my-hook } = ] must-fail-with
-
-HOOK: my-tuple-hook my-var ( -- x )
-
-M: sequence my-tuple-hook my-hook ;
-
-TUPLE: m-t-h-a ;
-
-M: m-t-h-a my-tuple-hook "foo" ;
-
-TUPLE: m-t-h-b < m-t-h-a ;
-
-M: m-t-h-b my-tuple-hook "bar" ;
-
-[ f ] [
-    \ my-tuple-hook [ "engines" word-prop ] keep prefix
-    [ 1quotation infer ] map all-equal?
-] unit-test
-
-HOOK: call-next-hooker my-var ( -- x )
-
-M: sequence call-next-hooker "sequence" ;
-
-M: array call-next-hooker call-next-method "array " prepend ;
-
-M: vector call-next-hooker call-next-method "vector " prepend ;
-
-M: growable call-next-hooker call-next-method "growable " prepend ;
-
-[ "vector growable sequence" ] [
-    V{ } my-var [ call-next-hooker ] with-variable
-] unit-test
-
-[ t ] [
-    { } \ nth effective-method nip \ sequence \ nth method eq?
-] unit-test
-
-[ t ] [
-    \ + \ nth effective-method nip dup \ nth "default-method" word-prop eq? and
-] unit-test
index 5dbc0d17a1284993180d83bde72b4f7193369550..96c273e3f8af073c764ea67fb65bf2d93e0f56ef 100644 (file)
-! Copyright (C) 2005, 2008 Slava Pestov.
+! Copyright (C) 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: arrays assocs kernel kernel.private slots.private math
-namespaces make sequences vectors words quotations definitions
-hashtables layouts combinators sequences.private generic
-classes classes.algebra classes.private generic.standard.engines
-generic.standard.engines.tag generic.standard.engines.predicate
-generic.standard.engines.tuple accessors ;
+USING: accessors definitions generic generic.single kernel
+namespaces words math math.order combinators sequences
+generic.single.private quotations kernel.private
+assocs arrays layouts ;
 IN: generic.standard
 
-GENERIC: dispatch# ( word -- n )
+TUPLE: standard-combination < single-combination # ;
 
-M: generic dispatch#
-    "combination" word-prop dispatch# ;
-
-GENERIC: method-declaration ( class generic -- quot )
-
-M: generic method-declaration
-    "combination" word-prop method-declaration ;
-
-M: quotation engine>quot
-    assumed get generic get method-declaration prepend ;
-
-ERROR: no-method object generic ;
-
-: error-method ( word -- quot )
-    [ picker ] dip [ no-method ] curry append ;
-
-: push-method ( method specializer atomic assoc -- )
-    [
-        [ H{ } clone <predicate-dispatch-engine> ] unless*
-        [ methods>> set-at ] keep
-    ] change-at ;
-
-: flatten-method ( class method assoc -- )
-    [ [ flatten-class keys ] keep ] 2dip [
-        [ spin ] dip push-method
-    ] 3curry each ;
-
-: flatten-methods ( assoc -- assoc' )
-    H{ } clone [
-        [
-            flatten-method
-        ] curry assoc-each
-    ] keep ;
-
-: <big-dispatch-engine> ( assoc -- engine )
-    flatten-methods
-    convert-tuple-methods
-    convert-hi-tag-methods
-    <lo-tag-dispatch-engine> ;
-
-: mangle-method ( method -- quot )
-    1quotation generic get extra-values \ drop <repetition>
-    prepend [ ] like ;
-
-: find-default ( methods -- quot )
-    #! Side-effects methods.
-    [ object bootstrap-word ] dip delete-at* [
-        drop generic get "default-method" word-prop mangle-method
-    ] unless ;
-
-: <standard-engine> ( word -- engine )
-    object bootstrap-word assumed set {
-        [ generic set ]
-        [ "engines" word-prop forget-all ]
-        [ V{ } clone "engines" set-word-prop ]
-        [
-            "methods" word-prop
-            [ mangle-method ] assoc-map
-            [ find-default default set ]
-            [ <big-dispatch-engine> ]
-            bi
-        ]
-    } cleave ;
-
-: single-combination ( word -- quot )
-    [ <standard-engine> engine>quot ] with-scope ;
-
-ERROR: inconsistent-next-method class generic ;
-
-: single-next-method-quot ( class generic -- quot/f )
-    2dup next-method dup [
-        [
-            pick "predicate" word-prop %
-            1quotation ,
-            [ inconsistent-next-method ] 2curry ,
-            \ if ,
-        ] [ ] make
-    ] [ 3drop f ] if ;
-
-: single-effective-method ( obj word -- method )
-    [ [ order [ instance? ] with find-last nip ] keep method ]
-    [ "default-method" word-prop ]
-    bi or ;
-
-TUPLE: standard-combination # ;
-
-C: <standard-combination> standard-combination
+: <standard-combination> ( n -- standard-combination )
+    dup 0 2 between? [ "Bad dispatch position" throw ] unless
+    standard-combination boa ;
 
 PREDICATE: standard-generic < generic
     "combination" word-prop standard-combination? ;
 
 PREDICATE: simple-generic < standard-generic
-    "combination" word-prop #>> zero? ;
+    "combination" word-prop #>> 0 = ;
 
 CONSTANT: simple-combination T{ standard-combination f 0 }
 
 : define-simple-generic ( word effect -- )
     [ simple-combination ] dip define-generic ;
 
-: with-standard ( combination quot -- quot' )
-    [ #>> (dispatch#) ] dip with-variable ; inline
-
-M: standard-generic extra-values drop 0 ;
-
-M: standard-combination make-default-method
-    [ error-method ] with-standard ;
+: (picker) ( n -- quot )
+    {
+        { 0 [ [ dup ] ] }
+        { 1 [ [ over ] ] }
+        { 2 [ [ pick ] ] }
+        [ 1- (picker) [ dip swap ] curry ]
+    } case ;
 
-M: standard-combination perform-combination
-    [ drop ] [ [ single-combination ] with-standard ] 2bi define ;
+M: standard-combination picker
+    combination get #>> (picker) ;
 
 M: standard-combination dispatch# #>> ;
 
-M: standard-combination method-declaration
-    dispatch# object <array> swap prefix [ declare ] curry [ ] like ;
-
-M: standard-combination next-method-quot*
-    [
-        single-next-method-quot
-        dup [ picker prepend ] when
-    ] with-standard ;
-
 M: standard-generic effective-method
-    [ dispatch# (picker) call ] keep single-effective-method ;
-
-TUPLE: hook-combination var ;
-
-C: <hook-combination> hook-combination
-
-PREDICATE: hook-generic < generic
-    "combination" word-prop hook-combination? ;
-
-: with-hook ( combination quot -- quot' )
-    0 (dispatch#) [
-        [ hook-combination ] dip with-variable
-    ] with-variable ; inline
+    [ datastack ] dip [ "combination" word-prop #>> swap <reversed> nth ] keep
+    (effective-method) ;
 
-: prepend-hook-var ( quot -- quot' )
-    hook-combination get var>> [ get ] curry prepend ;
+M: standard-combination inline-cache-quot ( word methods -- )
+    #! Direct calls to the generic word (not tail calls or indirect calls)
+    #! will jump to the inline cache entry point instead of the megamorphic
+    #! dispatch entry point.
+    combination get #>> [ f inline-cache-miss ] 3curry [ ] like ;
 
-M: hook-combination dispatch# drop 0 ;
+: make-empty-cache ( -- array )
+    mega-cache-size get f <array> ;
 
-M: hook-combination method-declaration 2drop [ ] ;
-
-M: hook-generic extra-values drop 1 ;
-
-M: hook-generic effective-method
-    [ "combination" word-prop var>> get ] keep
-    single-effective-method ;
-
-M: hook-combination make-default-method
-    [ error-method prepend-hook-var ] with-hook ;
-
-M: hook-combination perform-combination
-    [ drop ] [
-        [ single-combination prepend-hook-var ] with-hook
-    ] 2bi define ;
-
-M: hook-combination next-method-quot*
-    [
-        single-next-method-quot
-        dup [ prepend-hook-var ] when
-    ] with-hook ;
-
-M: simple-generic definer drop \ GENERIC: f ;
+M: standard-combination mega-cache-quot
+    combination get #>> make-empty-cache [ mega-cache-lookup ] 3curry [ ] like ;
 
 M: standard-generic definer drop \ GENERIC# f ;
 
-M: hook-generic definer drop \ HOOK: f ;
+M: simple-generic definer drop \ GENERIC: f ;
diff --git a/core/generic/standard/summary.txt b/core/generic/standard/summary.txt
deleted file mode 100644 (file)
index 5e731c6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Standard method combination used for most generic words
old mode 100644 (file)
new mode 100755 (executable)
index 5a19cce..0619e79
@@ -116,7 +116,7 @@ HELP: ?set-at
 { $description "If the third input is an assoc, stores the key/value pair into that assoc, or else creates a new hashtable with the key/value pair as its only entry." } ;
 
 HELP: >hashtable
-{ $values { "assoc" "an assoc" } { "hashtable" "a hashtable" } }
+{ $values { "assoc" assoc } { "hashtable" hashtable } }
 { $description "Constructs a hashtable from any assoc." } ;
 
 HELP: rehash
index 5d8e88b85f5b2ee4a78109e618f868d8773cf913..0140fcc0e8cd51fa7678e9bb10a5451e372ceb09 100644 (file)
@@ -1,7 +1,8 @@
 ! Copyright (C) 2004, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: continuations continuations.private kernel
-kernel.private sequences assocs namespaces namespaces.private ;
+kernel.private sequences assocs namespaces namespaces.private
+continuations continuations.private ;
 IN: init
 
 SYMBOL: init-hooks
index 8f0fb9e97a549e4bba189c19d20cd3ee0595a336..f57dafbdc64990c22eb1fac6a024375ea47afb08 100644 (file)
@@ -1,7 +1,7 @@
 USING: arrays debugger.threads destructors io io.directories
 io.encodings.8-bit io.encodings.ascii io.encodings.binary
 io.files io.files.private io.files.temp io.files.unique kernel
-make math sequences system threads tools.test generic.standard ;
+make math sequences system threads tools.test generic.single ;
 IN: io.files.tests
 
 [ ] [ "append-test" temp-file dup exists? [ delete-file ] [ drop ] if ] unit-test
index 1bc282e95661af65e6bad11a303a802926894e58..0f3041e67025e6b34621c894bd0427959c2084f1 100644 (file)
@@ -20,13 +20,13 @@ HOOK: (file-appender) io-backend ( path -- stream )
     swap normalize-path (file-appender) swap <encoder> ;
 
 : file-lines ( path encoding -- seq )
-    <file-reader> lines ;
+    <file-reader> stream-lines ;
 
 : with-file-reader ( path encoding quot -- )
     [ <file-reader> ] dip with-input-stream ; inline
 
 : file-contents ( path encoding -- seq )
-    <file-reader> contents ;
+    <file-reader> stream-contents ;
 
 : with-file-writer ( path encoding quot -- )
     [ <file-writer> ] dip with-output-stream ; inline
index 740152f2941420a14046046f1ef8dc0fd527031f..3469a8106477d0614eaa67dad4f6146ccb9d7aa8 100644 (file)
@@ -221,10 +221,14 @@ HELP: bl
 { $description "Outputs a space character (" { $snippet "\" \"" } ") to " { $link output-stream } "." }
 $io-error ;
 
-HELP: lines
+HELP: stream-lines
 { $values { "stream" "an input stream" } { "seq" "a sequence of strings" } }
 { $description "Reads lines of text until the stream is exhausted, collecting them in a sequence of strings." } ;
 
+HELP: lines
+{ $values { "seq" "a sequence of strings" } }
+{ $description "Reads lines of text until from the " { $link input-stream } " until it is exhausted, collecting them in a sequence of strings." } ;
+
 HELP: each-line
 { $values { "quot" { $quotation "( str -- )" } } }
 { $description "Calls the quotation with successive lines of text, until the current " { $link input-stream } " is exhausted." } ;
@@ -233,9 +237,14 @@ HELP: each-block
 { $values { "quot" { $quotation "( block -- )" } } }
 { $description "Calls the quotation with successive blocks of data, until the current " { $link input-stream } " is exhausted." } ;
 
-HELP: contents
+HELP: stream-contents
 { $values { "stream" "an input stream" } { "seq" "a string, byte array or " { $link f } } }
-{ $description "Reads the entire contents of a stream. If the stream is empty, outputs"  { $link f } "." }
+{ $description "Reads the entire contents of a stream. If the stream is empty, outputs "  { $link f } "." }
+$io-error ;
+
+HELP: contents
+{ $values { "seq" "a string, byte array or " { $link f } } }
+{ $description "Reads the entire contents of a the stream stored in " { $link input-stream } ". If the stream is empty, outputs " { $link f } "." }
 $io-error ;
 
 ARTICLE: "stream-protocol" "Stream protocol"
@@ -347,9 +356,11 @@ $nl
 "First, a simple composition of " { $link stream-write } " and " { $link stream-nl } ":"
 { $subsection stream-print }
 "Processing lines one by one:"
+{ $subsection stream-lines }
 { $subsection lines }
 { $subsection each-line }
 "Processing blocks of data:"
+{ $subsection stream-contents }
 { $subsection contents }
 { $subsection each-block }
 "Copying the contents of one stream to another:"
index 74bba7769ee48f6203c835cd7342672ed09fae53..b43098bcd4feaa83582f103d7acaec097aacaac4 100644 (file)
@@ -68,9 +68,12 @@ SYMBOL: error-stream
 
 : bl ( -- ) " " write ;
 
-: lines ( stream -- seq )
+: stream-lines ( stream -- seq )
     [ [ readln dup ] [ ] produce nip ] with-input-stream ;
 
+: lines ( -- seq )
+    input-stream get stream-lines ;
+
 <PRIVATE
 
 : each-morsel ( handler: ( data -- ) reader: ( -- data ) -- )
@@ -81,11 +84,14 @@ PRIVATE>
 : each-line ( quot -- )
     [ readln ] each-morsel ; inline
 
-: contents ( stream -- seq )
+: stream-contents ( stream -- seq )
     [
         [ 65536 read-partial dup ] [ ] produce nip concat f like
     ] with-input-stream ;
 
+: contents ( -- seq )
+    input-stream get stream-contents ;
+
 : each-block ( quot: ( block -- ) -- )
     [ 8192 read-partial ] each-morsel ; inline
 
index 3dde9152d08eeb55624c951673debdc475e1c79d..6a82d6d5456827b2c3b6bcd43f9e1e5c19a59c1f 100644 (file)
@@ -5,6 +5,6 @@ IN: io.streams.c.tests
 [ "hello world" ] [
     "hello world" "test.txt" temp-file ascii set-file-contents
 
-    "test.txt" temp-file "rb" fopen <c-reader> contents
+    "test.txt" temp-file "rb" fopen <c-reader> stream-contents
     >string
 ] unit-test
index 1d8c09a9b28617c6d139f58cdfe5611fde250b29..e67e2bc0ddb5de076284329b03ffd1e09549d758 100644 (file)
@@ -183,6 +183,20 @@ HELP: either?
     { $example "USING: kernel math prettyprint ;" "5 7 [ even? ] either? ." "f" }
 } ;
 
+HELP: execute
+{ $values { "word" word } }
+{ $description "Executes a word. Words which " { $link execute } " an input parameter must be declared " { $link POSTPONE: inline } " so that a caller which passes in a literal word can have a static stack effect." }
+{ $examples
+    { $example "USING: kernel io words ;" "IN: scratchpad" ": twice ( word -- ) dup execute execute ; inline\n: hello ( -- ) \"Hello\" print ;\n\\ hello twice" "Hello\nHello" }
+} ;
+
+{ execute POSTPONE: execute( } related-words
+
+HELP: (execute)
+{ $values { "word" word } }
+{ $description "Executes a word without checking if it is a word first." }
+{ $warning "This word is in the " { $vocab-link "kernel.private" } " vocabulary because it is unsafe. Calling with a parameter that is not a word will crash Factor. Use " { $link execute } " instead." } ;
+
 HELP: call
 { $values { "callable" callable } }
 { $description "Calls a quotation. Words which " { $link call } " an input parameter must be declared " { $link POSTPONE: inline } " so that a caller which passes in a literal quotation can have a static stack effect." }
index 5a32ca2dced334b4bc4696dea7bd015daae4a2f8..00b9500211818f40b7637b11581fefdec2982706 100644 (file)
@@ -1,4 +1,4 @@
-! Copyright (C) 2007, 2008 Slava Pestov.
+! Copyright (C) 2007, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: namespaces math words kernel assocs classes
 math.order kernel.private ;
@@ -16,12 +16,14 @@ SYMBOL: tag-numbers
 
 SYMBOL: type-numbers
 
-: tag-number ( class -- n )
-    tag-numbers get at [ object tag-number ] unless* ;
+SYMBOL: mega-cache-size
 
 : type-number ( class -- n )
     type-numbers get at ;
 
+: tag-number ( class -- n )
+    type-number dup num-tags get >= [ drop object tag-number ] when ;
+
 : tag-fixnum ( n -- tagged )
     tag-bits get shift ;
 
index 42786ffc9db8b255e25dfc108ff597c2d7e708a5..993d8d0e76229406f613a9033829da31315eafa0 100755 (executable)
@@ -1,4 +1,4 @@
-! Copyright (C) 2003, 2008 Slava Pestov.
+! Copyright (C) 2003, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel math.private ;
 IN: math
@@ -63,23 +63,22 @@ PRIVATE>
 : neg ( x -- -x ) 0 swap - ; inline
 : recip ( x -- y ) 1 swap / ; inline
 : sgn ( x -- n ) dup 0 < [ drop -1 ] [ 0 > 1 0 ? ] if ; inline
-
 : ?1+ ( x -- y ) [ 1+ ] [ 0 ] if* ; inline
-
 : rem ( x y -- z ) abs [ mod ] [ + ] [ mod ] tri ; foldable
-
 : 2^ ( n -- 2^n ) 1 swap shift ; inline
-
 : even? ( n -- ? ) 1 bitand zero? ;
-
 : odd? ( n -- ? ) 1 bitand 1 number= ;
 
 UNION: integer fixnum bignum ;
 
+TUPLE: ratio { numerator integer read-only } { denominator integer read-only } ;
+
 UNION: rational integer ratio ;
 
 UNION: real rational float ;
 
+TUPLE: complex { real real read-only } { imaginary real read-only } ;
+
 UNION: number real complex ;
 
 GENERIC: fp-nan? ( x -- ? )
old mode 100644 (file)
new mode 100755 (executable)
index 74d7c58..cd66e78
@@ -1,6 +1,6 @@
 USING: help.markup help.syntax kernel kernel.private
 sequences words namespaces.private quotations vectors
-math.parser math words.symbol ;
+math.parser math words.symbol assocs ;
 IN: namespaces
 
 ARTICLE: "namespaces-combinators" "Namespace combinators"
@@ -14,7 +14,8 @@ ARTICLE: "namespaces-change" "Changing variable values"
 { $subsection off }
 { $subsection inc }
 { $subsection dec }
-{ $subsection change } ;
+{ $subsection change }
+{ $subsection change-global } ;
 
 ARTICLE: "namespaces-global" "Global variables"
 { $subsection namespace }
@@ -73,6 +74,11 @@ HELP: change
 { $description "Applies the quotation to the old value of the variable, and assigns the resulting value to the variable." }
 { $side-effects "variable" } ;
 
+HELP: change-global
+{ $values { "variable" "a variable, by convention a symbol" } { "quot" { $quotation "( old -- new )" } } }
+{ $description "Applies the quotation to the old value of the global variable, and assigns the resulting value to the global variable." }
+{ $side-effects "variable" } ;
+
 HELP: +@
 { $values { "n" "a number" } { "variable" "a variable, by convention a symbol" } }
 { $description "Adds " { $snippet "n" } " to the value of the variable. A variable value of " { $link f } " is interpreted as being zero." }
@@ -113,19 +119,19 @@ HELP: with-variable
 } ;
 
 HELP: make-assoc
-{ $values { "quot" quotation } { "exemplar" "an assoc" } { "hash" "a new hashtable" } }
+{ $values { "quot" quotation } { "exemplar" assoc } { "hash" "a new assoc" } }
 { $description "Calls the quotation in a new namespace of the same type as " { $snippet "exemplar" } ", and outputs this namespace when the quotation returns. Useful for quickly building assocs." } ;
 
 HELP: bind
-{ $values { "ns" "a hashtable" } { "quot" quotation } }
+{ $values { "ns" assoc } { "quot" quotation } }
 { $description "Calls the quotation in the dynamic scope of " { $snippet "ns" } ". When variables are looked up by the quotation, " { $snippet "ns" } " is checked first, and setting variables in the quotation stores them in " { $snippet "ns" } "." } ;
 
 HELP: namespace
-{ $values { "namespace" "an assoc" } }
+{ $values { "namespace" assoc } }
 { $description "Outputs the current namespace. Calls to " { $link set } " modify this namespace." } ;
 
 HELP: global
-{ $values { "g" "an assoc" } }
+{ $values { "g" assoc } }
 { $description "Outputs the global namespace. The global namespace is always checked last when looking up variable values." } ;
 
 HELP: get-global
@@ -150,7 +156,7 @@ HELP: set-namestack
 { $description "Replaces the name stack with a copy of the given vector." } ;
 
 HELP: >n
-{ $values { "namespace" "an assoc" } }
+{ $values { "namespace" assoc } }
 { $description "Pushes a namespace on the name stack." } ;
 
 HELP: ndrop
index b0e764c94d96244a31a45c71a6c0a7bd03fb8bc0..310816cbf757b226113fb31763ee5e51f6963151 100644 (file)
@@ -24,12 +24,13 @@ PRIVATE>
 : get-global ( variable -- value ) global at ;
 : set-global ( value variable -- ) global set-at ;
 : change ( variable quot -- ) [ [ get ] keep ] dip dip set ; inline
+: change-global ( variable quot -- ) [ global ] dip change-at ; inline
 : +@ ( n variable -- ) [ 0 or + ] change ;
 : inc ( variable -- ) 1 swap +@ ; inline
 : dec ( variable -- ) -1 swap +@ ; inline
 : bind ( ns quot -- ) swap >n call ndrop ; inline
-: counter ( variable -- n ) global [ 0 or 1+ dup ] change-at ;
+: counter ( variable -- n ) [ 0 or 1+ dup ] change-global ;
 : make-assoc ( quot exemplar -- hash ) 20 swap new-assoc [ swap bind ] keep ; inline
 : with-scope ( quot -- ) 5 <hashtable> swap bind ; inline
 : with-variable ( value key quot -- ) [ associate ] dip bind ; inline
-: initialize ( variable quot -- ) [ global ] dip [ unless* ] curry change-at ; inline
\ No newline at end of file
+: initialize ( variable quot -- ) [ unless* ] curry change-global ; inline
\ No newline at end of file
index 7908f40cbe247378c70199c019a54bac3b5adaeb..7915dc69e092be8ac951262bd0386e8447684716 100644 (file)
@@ -272,7 +272,7 @@ print-use-hook [ [ ] ] initialize
 : parse-stream ( stream name -- quot )
     [
         [
-            lines dup parse-fresh
+            stream-lines dup parse-fresh
             [ nip ] [ finish-parsing ] 2bi
             forget-smudged
         ] with-source-file
index 556e41249e24032abdb00d79ae423b8e57c39f0b..cfd96789b4be5505c9d0196d5e0ee459737c48c4 100755 (executable)
@@ -1,6 +1,6 @@
 USING: arrays help.markup help.syntax math
 sequences.private vectors strings kernel math.order layouts
-quotations generic.standard ;
+quotations generic.single ;
 IN: sequences
 
 HELP: sequence
@@ -1466,8 +1466,8 @@ ARTICLE: "sequences-combinators" "Sequence combinators"
 { $subsection produce }
 { $subsection produce-as }
 "Filtering:"
-{ $subsection push-if }
 { $subsection filter }
+{ $subsection partition }
 "Testing if a sequence contains elements satisfying a predicate:"
 { $subsection any? }
 { $subsection all? }
index a122aa124095504c6f73adc3f8aafd487e4f7d78..3670b10d3ce30c746a3ef7a6b9715089aa33a967 100755 (executable)
@@ -1,4 +1,4 @@
-USING: kernel help.markup help.syntax sequences quotations ;
+USING: kernel help.markup help.syntax sequences quotations assocs ;
 IN: sets
 
 ARTICLE: "sets" "Set-theoretic operations on sequences"
@@ -42,7 +42,7 @@ HELP: adjoin
 { $side-effects "seq" } ;
 
 HELP: conjoin
-{ $values { "elt" object } { "assoc" "an assoc" } }
+{ $values { "elt" object } { "assoc" assoc } }
 { $description "Stores a key/value pair, both equal to " { $snippet "elt" } ", into the assoc." }
 { $examples
     { $example
@@ -54,7 +54,7 @@ HELP: conjoin
 { $side-effects "assoc" } ;
 
 HELP: unique
-{ $values { "seq" "a sequence" } { "assoc" "an assoc" } }
+{ $values { "seq" "a sequence" } { "assoc" assoc } }
 { $description "Outputs a new assoc where the keys and values are equal." }
 { $examples
     { $example "USING: sets prettyprint ;" "{ 1 1 2 2 3 3 } unique ." "H{ { 1 1 } { 2 2 } { 3 3 } }" }
index 7ac8446842d24aa564a7de8e43158849d054b3ce..1365e815242efa192f49d02f131fb66f8c9371ab 100644 (file)
@@ -1,5 +1,5 @@
 IN: slots.tests
-USING: math accessors slots strings generic.standard kernel
+USING: math accessors slots strings generic.single kernel
 tools.test generic words parser eval math.functions ;
 
 TUPLE: r/w-test foo ;
index 5b71b13552f386b7d0aa7aaf236cc671af927a30..22bf7bb821ba26dcd87cd47873724f786a14fc91 100644 (file)
@@ -58,7 +58,7 @@ unit-test
 [ "\u001234bc\0\0\0" ] [ 6 "\u001234bc" resize-string ] unit-test
 
 ! Random tester found this
-[ 2 -7 resize-string ] [ { "kernel-error" 3 12 -7 } = ] must-fail-with
+[ 2 -7 resize-string ] [ { "kernel-error" 3 11 -7 } = ] must-fail-with
 
 ! Make sure 24-bit strings work
 "hello world" "s" set
index 7ab287fd20cdddd1bbb0f1c5400982f8bfcff7e4..e8f86faa9d8defe9f48ac2d0bef6ae37fee19de8 100644 (file)
@@ -1,7 +1,7 @@
 USING: generic help.syntax help.markup kernel math parser words
 effects classes generic.standard classes.tuple generic.math
-generic.standard arrays io.pathnames vocabs.loader io sequences
-assocs words.symbol words.alias words.constant combinators ;
+generic.standard generic.single arrays io.pathnames vocabs.loader io
+sequences assocs words.symbol words.alias words.constant combinators ;
 IN: syntax
 
 ARTICLE: "parser-algorithm" "Parser algorithm"
index 2e072f72d823d867ef423adb92ea04b722f360b8..3512b92e4c21bfb922ad826f820852f8ec105945 100644 (file)
@@ -4,7 +4,7 @@ USING: accessors alien arrays byte-arrays definitions generic
 hashtables kernel math namespaces parser lexer sequences strings
 strings.parser sbufs vectors words words.symbol words.constant
 words.alias quotations io assocs splitting classes.tuple
-generic.standard generic.math generic.parser classes
+generic.standard generic.hook generic.math generic.parser classes
 io.pathnames vocabs vocabs.parser classes.parser classes.union
 classes.intersection classes.mixin classes.predicate
 classes.singleton classes.tuple.parser compiler.units
index 2b978e866625c101e51be13c2122119d6d1dd26f..6c12b7b325b48a47586feb5e963b9c048dc1e2be 100644 (file)
@@ -65,8 +65,22 @@ M: object vocab-main vocab vocab-main ;
 
 M: f vocab-main ;
 
+SYMBOL: vocab-observers
+
+GENERIC: vocabs-changed ( obj -- )
+
+: add-vocab-observer ( obj -- )
+    vocab-observers get push ;
+
+: remove-vocab-observer ( obj -- )
+    vocab-observers get delq ;
+
+: notify-vocab-observers ( -- )
+    vocab-observers get [ vocabs-changed ] each ;
+
 : create-vocab ( name -- vocab )
-    dictionary get [ <vocab> ] cache ;
+    dictionary get [ <vocab> ] cache
+    notify-vocab-observers ;
 
 ERROR: no-vocab name ;
 
@@ -99,7 +113,8 @@ M: string >vocab-link dup vocab [ ] [ <vocab-link> ] ?if ;
 
 : forget-vocab ( vocab -- )
     dup words forget-all
-    vocab-name dictionary get delete-at ;
+    vocab-name dictionary get delete-at
+    notify-vocab-observers ;
 
 M: vocab-spec forget* forget-vocab ;
 
index 94609a06e5956f55fd5a4f918ebbe7b577cb83d2..3725086f70d7d8dc52a3c0847e0dda7a12f9c64c 100644 (file)
@@ -1,5 +1,5 @@
 USING: definitions help.markup help.syntax kernel parser
-kernel.private words.private vocabs classes quotations
+kernel.private vocabs classes quotations
 strings effects compiler.units ;
 IN: words
 
@@ -163,15 +163,6 @@ $nl
 
 ABOUT: "words"
 
-HELP: execute ( word -- )
-{ $values { "word" word } }
-{ $description "Executes a word. Words which " { $link execute } " an input parameter must be declared " { $link POSTPONE: inline } " so that a caller which passes in a literal word can have a static stack effect." }
-{ $examples
-    { $example "USING: kernel io words ;" "IN: scratchpad" ": twice ( word -- ) dup execute execute ; inline\n: hello ( -- ) \"Hello\" print ;\n\\ hello twice" "Hello\nHello" }
-} ;
-
-{ execute POSTPONE: execute( } related-words
-
 HELP: deferred
 { $class-description "The class of deferred words created by " { $link POSTPONE: DEFER: } "." } ;
 
index eb0599db78ede6b9e3512d23ea4990a485929a99..1976c1e4cd295e5674bf3bf9fd39ffd9201c8baa 100755 (executable)
@@ -1,9 +1,9 @@
 ! Copyright (C) 2004, 2009 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors arrays definitions graphs assocs kernel
-kernel.private slots.private math namespaces sequences strings
-vectors sbufs quotations assocs hashtables sorting words.private
-vocabs math.order sets ;
+kernel.private kernel.private slots.private math namespaces sequences
+strings vectors sbufs quotations assocs hashtables sorting vocabs
+math.order sets ;
 IN: words
 
 : word ( -- word ) \ word get-global ;
@@ -154,8 +154,16 @@ M: word reset-word
 : reset-generic ( word -- )
     [ subwords forget-all ]
     [ reset-word ]
-    [ { "methods" "combination" "default-method" } reset-props ]
-    tri ;
+    [
+        f >>direct-entry-def
+        {
+            "methods"
+            "combination"
+            "default-method"
+            "engines"
+            "decision-tree"
+        } reset-props
+    ] tri ;
 
 : gensym ( -- word )
     "( gensym )" f <word> ;
diff --git a/extra/audio/audio.factor b/extra/audio/audio.factor
new file mode 100644 (file)
index 0000000..04df36e
--- /dev/null
@@ -0,0 +1,23 @@
+USING: accessors alien arrays combinators kernel math openal ;
+IN: audio
+
+TUPLE: audio
+    { channels integer }
+    { sample-bits integer }
+    { sample-rate integer }
+    { size integer }
+    { data c-ptr } ;
+
+C: <audio> audio
+
+ERROR: format-unsupported-by-openal audio ;
+
+: openal-format ( audio -- format )
+    dup [ channels>> ] [ sample-bits>> ] bi 2array {
+        { { 1  8 } [ drop AL_FORMAT_MONO8    ] }
+        { { 1 16 } [ drop AL_FORMAT_MONO16   ] }
+        { { 2  8 } [ drop AL_FORMAT_STEREO8  ] }
+        { { 2 16 } [ drop AL_FORMAT_STEREO16 ] }
+        [ drop format-unsupported-by-openal ]
+    } case ;
+
diff --git a/extra/audio/wav/wav.factor b/extra/audio/wav/wav.factor
new file mode 100644 (file)
index 0000000..6b76e98
--- /dev/null
@@ -0,0 +1,85 @@
+USING: alien.c-types alien.syntax audio combinators
+combinators.short-circuit io io.binary io.encodings.binary
+io.files io.streams.byte-array kernel locals math
+sequences ;
+IN: audio.wav
+
+CONSTANT: RIFF-MAGIC "RIFF"
+CONSTANT: WAVE-MAGIC "WAVE"
+CONSTANT: FMT-MAGIC  "fmt "
+CONSTANT: DATA-MAGIC "data"
+
+C-STRUCT: riff-chunk-header
+    { "char[4]" "id" }
+    { "uchar[4]" "size" }
+    ;
+
+C-STRUCT: riff-chunk
+    { "riff-chunk-header" "header" }
+    { "char[4]" "format" }
+    ;
+
+C-STRUCT: wav-fmt-chunk
+    { "riff-chunk-header" "header" }
+    { "uchar[2]" "audio-format" }
+    { "uchar[2]" "num-channels" }
+    { "uchar[4]" "sample-rate" }
+    { "uchar[4]" "byte-rate" }
+    { "uchar[2]" "block-align" }
+    { "uchar[2]" "bits-per-sample" }
+    ;
+
+C-STRUCT: wav-data-chunk
+    { "riff-chunk-header" "header" }
+    { "uchar[0]" "body" }
+    ;
+
+ERROR: invalid-wav-file ;
+
+: ensured-read ( count -- output/f )
+    [ read ] keep over length = [ drop f ] unless ;
+: ensured-read* ( count -- output )
+    ensured-read [ invalid-wav-file ] unless* ;
+
+: read-chunk ( -- byte-array/f )
+    4 ensured-read [ 4 ensured-read* dup le> ensured-read* 3append ] [ f ] if* ;
+: read-riff-chunk ( -- byte-array/f )
+    "riff-chunk" heap-size ensured-read* ;
+
+: id= ( chunk id -- ? )
+    [ 4 head ] dip sequence= ;
+
+: check-chunk ( chunk id min-size -- ? )
+    [ id= ] [ [ length ] dip >= ] bi-curry* bi and ;
+
+:: read-wav-chunks ( -- fmt data )
+    f :> fmt! f :> data!
+    [ { [ fmt data and not ] [ read-chunk ] } 0&& dup ]
+    [ {
+        { [ dup FMT-MAGIC  "wav-fmt-chunk"  heap-size check-chunk ] [ fmt!  ] }
+        { [ dup DATA-MAGIC "wav-data-chunk" heap-size check-chunk ] [ data! ] }
+    } cond ] while drop
+    fmt data 2dup and [ invalid-wav-file ] unless ;
+
+: verify-wav ( chunk -- )
+    {
+        [ RIFF-MAGIC id= ]
+        [ riff-chunk-format 4 memory>byte-array WAVE-MAGIC id= ]
+    } 1&&
+    [ invalid-wav-file ] unless ;
+
+: (read-wav) ( -- audio )
+    read-wav-chunks
+    [
+        [ wav-fmt-chunk-num-channels    2 memory>byte-array le> ]
+        [ wav-fmt-chunk-bits-per-sample 2 memory>byte-array le> ]
+        [ wav-fmt-chunk-sample-rate     4 memory>byte-array le> ] tri
+    ] [
+        [ riff-chunk-header-size 4 memory>byte-array le> dup ]
+        [ wav-data-chunk-body ] bi swap memory>byte-array
+    ] bi* <audio> ;
+
+: read-wav ( filename -- audio )
+    binary [
+        read-riff-chunk verify-wav (read-wav)
+    ] with-file-reader ;
index ca48e6208c8167abf5c495282284d3746513fb7d..220f16fad57e8cdcb5cee5e40c134e1c426f8875 100755 (executable)
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel vocabs vocabs.loader tools.time tools.vocabs
 arrays assocs io.styles io help.markup prettyprint sequences
-continuations debugger math namespaces ;
+continuations debugger math namespaces memory ;
 IN: benchmark
 
 <PRIVATE
@@ -14,7 +14,7 @@ PRIVATE>
 
 : run-benchmark ( vocab -- )
     [ "=== " write vocab-name print flush ] [
-        [ [ require ] [ [ run ] benchmark ] [ ] tri timings ]
+        [ [ require ] [ gc [ run ] benchmark ] [ ] tri timings ]
         [ swap errors ]
         recover get set-at
     ] bi ;
index c4887c03c4ba4cdddfe516b0db77679b2dbb986f..fccd80a607f015a1640a0dcddc0c47c17cb15cf4 100644 (file)
@@ -3,7 +3,7 @@ IN: benchmark.typecheck3
 
 TUPLE: hello n ;
 
-: hello-n* ( obj -- val ) dup tag 2 eq? [ 2 slot ] [ 3 throw ] if ;
+: hello-n* ( obj -- val ) 2 slot ;
 
 : foo ( obj -- obj n ) 0 100000000 [ over hello-n* + ] times ;
 
diff --git a/extra/benchmark/typecheck4/authors.txt b/extra/benchmark/typecheck4/authors.txt
deleted file mode 100755 (executable)
index 1901f27..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Slava Pestov
diff --git a/extra/benchmark/typecheck4/typecheck4.factor b/extra/benchmark/typecheck4/typecheck4.factor
deleted file mode 100644 (file)
index c881864..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-USING: math kernel kernel.private slots.private ;
-IN: benchmark.typecheck4
-
-TUPLE: hello n ;
-
-: hello-n* ( obj -- val ) 2 slot ;
-
-: foo ( obj -- obj n ) 0 100000000 [ over hello-n* + ] times ;
-
-: typecheck-main ( -- ) 0 hello boa foo 2drop ;
-
-MAIN: typecheck-main
diff --git a/extra/bson/authors.txt b/extra/bson/authors.txt
new file mode 100644 (file)
index 0000000..5df962b
--- /dev/null
@@ -0,0 +1 @@
+Sascha Matzke
diff --git a/extra/bson/bson.factor b/extra/bson/bson.factor
new file mode 100644 (file)
index 0000000..a97b502
--- /dev/null
@@ -0,0 +1,6 @@
+USING: vocabs.loader ;
+
+IN: bson
+
+"bson.reader" require
+"bson.writer" require
diff --git a/extra/bson/constants/authors.txt b/extra/bson/constants/authors.txt
new file mode 100644 (file)
index 0000000..5df962b
--- /dev/null
@@ -0,0 +1 @@
+Sascha Matzke
diff --git a/extra/bson/constants/constants.factor b/extra/bson/constants/constants.factor
new file mode 100644 (file)
index 0000000..5148413
--- /dev/null
@@ -0,0 +1,49 @@
+USING: accessors constructors kernel strings uuid ;
+
+IN: bson.constants
+
+: <objid> ( -- objid )
+   uuid1 ; inline
+
+TUPLE: oid { a initial: 0 } { b initial: 0 } ;
+
+TUPLE: objref ns objid ;
+
+CONSTRUCTOR: objref ( ns objid -- objref ) ;
+
+TUPLE: mdbregexp { regexp string } { options string } ;
+
+: <mdbregexp> ( string -- mdbregexp )
+   [ mdbregexp new ] dip >>regexp ;
+
+
+CONSTANT: MDB_OID_FIELD "_id"
+CONSTANT: MDB_META_FIELD "_mfd"
+
+CONSTANT: T_EOO  0  
+CONSTANT: T_Double  1  
+CONSTANT: T_Integer  16  
+CONSTANT: T_Boolean  8  
+CONSTANT: T_String  2  
+CONSTANT: T_Object  3  
+CONSTANT: T_Array  4  
+CONSTANT: T_Binary  5  
+CONSTANT: T_Undefined  6  
+CONSTANT: T_OID  7  
+CONSTANT: T_Date  9  
+CONSTANT: T_NULL  10  
+CONSTANT: T_Regexp  11  
+CONSTANT: T_DBRef  12  
+CONSTANT: T_Code  13  
+CONSTANT: T_ScopedCode  17  
+CONSTANT: T_Symbol  14  
+CONSTANT: T_JSTypeMax  16  
+CONSTANT: T_MaxKey  127  
+
+CONSTANT: T_Binary_Function 1   
+CONSTANT: T_Binary_Bytes 2
+CONSTANT: T_Binary_UUID 3
+CONSTANT: T_Binary_MD5 5
+CONSTANT: T_Binary_Custom 128
+
+
diff --git a/extra/bson/constants/summary.txt b/extra/bson/constants/summary.txt
new file mode 100644 (file)
index 0000000..11b0592
--- /dev/null
@@ -0,0 +1 @@
+Shared constants and classes
diff --git a/extra/bson/reader/authors.txt b/extra/bson/reader/authors.txt
new file mode 100644 (file)
index 0000000..5df962b
--- /dev/null
@@ -0,0 +1 @@
+Sascha Matzke
diff --git a/extra/bson/reader/reader.factor b/extra/bson/reader/reader.factor
new file mode 100644 (file)
index 0000000..96cde41
--- /dev/null
@@ -0,0 +1,200 @@
+USING: accessors assocs bson.constants byte-arrays byte-vectors fry io
+io.binary io.encodings.string io.encodings.utf8 kernel math namespaces
+sequences serialize arrays calendar io.encodings ;
+
+IN: bson.reader
+
+<PRIVATE
+
+TUPLE: element { type integer } name ;
+TUPLE: state
+    { size initial: -1 } { read initial: 0 } exemplar
+    result scope element ;
+
+: <state> ( exemplar -- state )
+    [ state new ] dip
+    [ clone >>exemplar ] keep
+    clone [ >>result ] [ V{ } clone [ push ] keep >>scope ] bi
+    V{ } clone [ T_Object "" element boa swap push ] keep >>element ; 
+
+PREDICATE: bson-eoo     < integer T_EOO = ;
+PREDICATE: bson-not-eoo < integer T_EOO > ;
+
+PREDICATE: bson-double  < integer T_Double = ;
+PREDICATE: bson-integer < integer T_Integer = ;
+PREDICATE: bson-string  < integer T_String = ;
+PREDICATE: bson-object  < integer T_Object = ;
+PREDICATE: bson-array   < integer T_Array = ;
+PREDICATE: bson-binary  < integer T_Binary = ;
+PREDICATE: bson-regexp  < integer T_Regexp = ;
+PREDICATE: bson-binary-bytes < integer T_Binary_Bytes = ;
+PREDICATE: bson-binary-function < integer T_Binary_Function = ;
+PREDICATE: bson-binary-uuid < integer T_Binary_UUID = ;
+PREDICATE: bson-binary-custom < integer T_Binary_Custom = ;
+PREDICATE: bson-oid     < integer T_OID = ;
+PREDICATE: bson-boolean < integer T_Boolean = ;
+PREDICATE: bson-date    < integer T_Date = ;
+PREDICATE: bson-null    < integer T_NULL = ;
+PREDICATE: bson-ref     < integer T_DBRef = ;
+
+GENERIC: element-read ( type -- cont? )
+GENERIC: element-data-read ( type -- object )
+GENERIC: element-binary-read ( length type -- object )
+
+: byte-array>number ( seq -- number )
+    byte-array>bignum >integer ; inline
+
+: get-state ( -- state )
+    state get ; inline
+
+: count-bytes ( count -- )
+    [ get-state ] dip '[ _ + ] change-read drop ; inline
+
+: read-int32 ( -- int32 )
+    4 [ read byte-array>number ] [ count-bytes ] bi  ; inline
+
+: read-longlong ( -- longlong )
+    8 [ read byte-array>number ] [ count-bytes ] bi ; inline
+
+: read-double ( -- double )
+    8 [ read byte-array>number bits>double ] [ count-bytes ] bi ; inline
+
+: read-byte-raw ( -- byte-raw )
+    1 [ read ] [ count-bytes ] bi ; inline
+
+: read-byte ( -- byte )
+    read-byte-raw first ; inline
+
+: read-cstring ( -- string )
+    input-stream get utf8 <decoder>
+    "\0" swap stream-read-until drop ; inline
+
+: read-sized-string ( length -- string )
+    drop read-cstring ; inline
+
+: read-element-type ( -- type )
+    read-byte ; inline
+
+: push-element ( type name -- element )
+    element boa
+    [ get-state element>> push ] keep ; inline
+
+: pop-element ( -- element )
+    get-state element>> pop ; inline
+
+: peek-scope ( -- ht )
+    get-state scope>> peek ; inline
+
+: read-elements ( -- )
+    read-element-type
+    element-read 
+    [ read-elements ] when ; inline recursive
+
+GENERIC: fix-result ( assoc type -- result )
+
+M: bson-object fix-result ( assoc type -- result )
+    drop ;
+
+M: bson-array fix-result ( assoc type -- result )
+    drop
+    values ;
+
+GENERIC: end-element ( type -- )
+
+M: bson-object end-element ( type -- )
+    drop ;
+
+M: bson-array end-element ( type -- )
+    drop ;
+
+M: object end-element ( type -- )
+    drop
+    pop-element drop ;
+
+M: bson-eoo element-read ( type -- cont? )
+    drop
+    get-state scope>> [ pop ] keep swap ! vec assoc
+    pop-element [ type>> ] keep       ! vec assoc element
+    [ fix-result ] dip
+    rot length 0 >                      ! assoc element 
+    [ name>> peek-scope set-at t ]
+    [ drop [ get-state ] dip >>result drop f ] if ;
+
+M: bson-not-eoo element-read ( type -- cont? )
+    [ peek-scope ] dip                                 ! scope type 
+    '[ _ read-cstring push-element [ name>> ] [ type>> ] bi 
+       [ element-data-read ] keep
+       end-element
+       swap
+    ] dip set-at t ;
+
+: [scope-changer] ( state -- state quot )
+    dup exemplar>> '[ [ [ _ clone ] dip push ] keep ] ; inline
+
+: (object-data-read) ( type -- object )
+    drop
+    read-int32 drop
+    get-state
+    [scope-changer] change-scope
+    scope>> peek ; inline
+    
+M: bson-object element-data-read ( type -- object )
+    (object-data-read) ;
+
+M: bson-array element-data-read ( type -- object )
+    (object-data-read) ;
+    
+M: bson-string element-data-read ( type -- object )
+    drop
+    read-int32 read-sized-string ;
+
+M: bson-integer element-data-read ( type -- object )
+    drop
+    read-int32 ;
+
+M: bson-double element-data-read ( type -- double )
+    drop
+    read-double ;
+
+M: bson-boolean element-data-read ( type -- boolean )
+   drop
+   read-byte 1 = ;
+
+M: bson-date element-data-read ( type -- timestamp )
+   drop
+   read-longlong millis>timestamp ;
+
+M: bson-binary element-data-read ( type -- binary )
+   drop
+   read-int32 read-byte element-binary-read ;
+
+M: bson-regexp element-data-read ( type -- mdbregexp )
+   drop mdbregexp new
+   read-cstring >>regexp read-cstring >>options ;
+M: bson-null element-data-read ( type -- bf  )
+    drop
+    f ;
+
+M: bson-oid element-data-read ( type -- oid )
+    drop
+    read-longlong
+    read-int32 oid boa ;
+
+M: bson-binary-custom element-binary-read ( size type -- dbref )
+    2drop
+    read-cstring
+    read-cstring objref boa ;
+
+M: bson-binary-bytes element-binary-read ( size type -- bytes )
+    drop read ;
+
+M: bson-binary-function element-binary-read ( size type -- quot )
+    drop read bytes>object ;
+
+PRIVATE>
+
+: stream>assoc ( exemplar -- assoc bytes-read )
+    <state> dup state
+    [ read-int32 >>size read-elements ] with-variable 
+    [ result>> ] [ read>> ] bi ; 
diff --git a/extra/bson/reader/summary.txt b/extra/bson/reader/summary.txt
new file mode 100644 (file)
index 0000000..384fe07
--- /dev/null
@@ -0,0 +1 @@
+BSON to Factor deserializer
diff --git a/extra/bson/summary.txt b/extra/bson/summary.txt
new file mode 100644 (file)
index 0000000..58604e6
--- /dev/null
@@ -0,0 +1 @@
+BSON reader and writer
diff --git a/extra/bson/writer/authors.txt b/extra/bson/writer/authors.txt
new file mode 100644 (file)
index 0000000..5df962b
--- /dev/null
@@ -0,0 +1 @@
+Sascha Matzke
diff --git a/extra/bson/writer/summary.txt b/extra/bson/writer/summary.txt
new file mode 100644 (file)
index 0000000..5dc8501
--- /dev/null
@@ -0,0 +1 @@
+Factor to BSON serializer
diff --git a/extra/bson/writer/writer.factor b/extra/bson/writer/writer.factor
new file mode 100644 (file)
index 0000000..1b9d45b
--- /dev/null
@@ -0,0 +1,164 @@
+! Copyright (C) 2008 Sascha Matzke.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors assocs bson.constants byte-arrays byte-vectors
+calendar fry io io.binary io.encodings io.encodings.binary
+io.encodings.utf8 io.streams.byte-array kernel math math.parser
+namespaces quotations sequences sequences.private serialize strings
+words combinators.short-circuit literals ;
+
+IN: bson.writer
+
+<PRIVATE
+
+SYMBOL: shared-buffer 
+
+CONSTANT: INT32-SIZE 4
+CONSTANT: CHAR-SIZE 1
+CONSTANT: INT64-SIZE 8
+
+: (buffer) ( -- buffer )
+    shared-buffer get
+    [ 8192 <byte-vector> [ shared-buffer set ] keep ] unless* ; inline
+
+: >le-stream ( x n -- )
+    swap
+    '[ _ swap nth-byte 0 B{ 0 }
+       [ set-nth-unsafe ] keep write ] each ; inline
+
+PRIVATE>
+
+: reset-buffer ( buffer -- )
+    0 >>length drop ; inline
+
+: ensure-buffer ( -- )
+    (buffer) drop ; inline
+
+: with-buffer ( quot -- byte-vector )
+    [ (buffer) [ reset-buffer ] keep dup ] dip
+    with-output-stream* dup encoder? [ stream>> ] when ; inline
+
+: with-length ( quot: ( -- ) -- bytes-written start-index )
+    [ (buffer) [ length ] keep ] dip call
+    length swap [ - ] keep ; inline
+
+: with-length-prefix ( quot: ( -- ) -- )
+    [ B{ 0 0 0 0 } write ] prepose with-length
+    [ INT32-SIZE >le ] dip (buffer)
+    '[ _ over [ nth-unsafe ] dip _ + _ set-nth-unsafe ]
+    [ INT32-SIZE ] dip each-integer ; inline
+
+: with-length-prefix-excl ( quot: ( -- ) -- )
+    [ B{ 0 0 0 0 } write ] prepose with-length
+    [ INT32-SIZE - INT32-SIZE >le ] dip (buffer)
+    '[ _ over [ nth-unsafe ] dip _ + _ set-nth-unsafe ]
+    [ INT32-SIZE ] dip each-integer ; inline
+    
+<PRIVATE
+
+GENERIC: bson-type? ( obj -- type ) foldable flushable
+GENERIC: bson-write ( obj -- )
+
+M: t bson-type? ( boolean -- type ) drop T_Boolean ; 
+M: f bson-type? ( boolean -- type ) drop T_Boolean ; 
+
+M: real bson-type? ( real -- type ) drop T_Double ; 
+M: word bson-type? ( word -- type ) drop T_String ; 
+M: tuple bson-type? ( tuple -- type ) drop T_Object ;  
+M: sequence bson-type? ( seq -- type ) drop T_Array ;
+M: string bson-type? ( string -- type ) drop T_String ; 
+M: integer bson-type? ( integer -- type ) drop T_Integer ; 
+M: assoc bson-type? ( assoc -- type ) drop T_Object ;
+M: timestamp bson-type? ( timestamp -- type ) drop T_Date ;
+M: mdbregexp bson-type? ( regexp -- type ) drop T_Regexp ;
+
+M: oid bson-type? ( word -- type ) drop T_OID ;
+M: objref bson-type? ( objref -- type ) drop T_Binary ;
+M: quotation bson-type? ( quotation -- type ) drop T_Binary ; 
+M: byte-array bson-type? ( byte-array -- type ) drop T_Binary ; 
+
+: write-utf8-string ( string -- )
+    output-stream get utf8 <encoder> stream-write ; inline
+
+: write-byte ( byte -- ) CHAR-SIZE >le-stream ; inline
+: write-int32 ( int -- ) INT32-SIZE >le-stream ; inline
+: write-double ( real -- ) double>bits INT64-SIZE >le-stream ; inline
+: write-cstring ( string -- ) write-utf8-string 0 write-byte ; inline
+: write-longlong ( object -- ) INT64-SIZE >le-stream ; inline
+
+: write-eoo ( -- ) T_EOO write-byte ; inline
+: write-type ( obj -- obj ) [ bson-type? write-byte ] keep ; inline
+: write-pair ( name object -- ) write-type [ write-cstring ] dip bson-write ; inline
+
+M: f bson-write ( f -- )
+    drop 0 write-byte ; 
+
+M: t bson-write ( t -- )
+    drop 1 write-byte ;
+
+M: string bson-write ( obj -- )
+    '[ _ write-cstring ] with-length-prefix-excl ;
+
+M: integer bson-write ( num -- )
+    write-int32 ;
+
+M: real bson-write ( num -- )
+    >float write-double ;
+
+M: timestamp bson-write ( timestamp -- )
+    timestamp>millis write-longlong ;
+
+M: byte-array bson-write ( binary -- )
+    [ length write-int32 ] keep
+    T_Binary_Bytes write-byte
+    write ; 
+
+M: quotation bson-write ( quotation -- )
+    object>bytes [ length write-int32 ] keep
+    T_Binary_Function write-byte
+    write ; 
+
+M: oid bson-write ( oid -- )
+    [ a>> write-longlong ] [ b>> write-int32 ] bi ;
+
+M: objref bson-write ( objref -- )
+    [ binary ] dip
+    '[ _
+       [ ns>> write-cstring ]
+       [ objid>> write-cstring ] bi ] with-byte-writer
+    [ length write-int32 ] keep
+    T_Binary_Custom write-byte write ;
+       
+M: mdbregexp bson-write ( regexp -- )
+   [ regexp>> write-cstring ]
+   [ options>> write-cstring ] bi ; 
+    
+M: sequence bson-write ( array -- )
+    '[ _ [ [ write-type ] dip number>string
+           write-cstring bson-write ] each-index
+       write-eoo ] with-length-prefix ;
+
+: write-oid ( assoc -- )
+    [ MDB_OID_FIELD ] dip at
+    [ [ MDB_OID_FIELD ] dip write-pair ] when* ; inline
+
+: skip-field? ( name -- boolean )
+   { $[ MDB_OID_FIELD MDB_META_FIELD ] } member? ; inline
+
+M: assoc bson-write ( assoc -- )
+    '[ _  [ write-oid ] keep
+       [ over skip-field? [ 2drop ] [ write-pair ] if ] assoc-each
+       write-eoo ] with-length-prefix ; 
+
+M: word bson-write name>> bson-write ;
+
+PRIVATE>
+
+: assoc>bv ( assoc -- byte-vector )
+    [ '[ _ bson-write ] with-buffer ] with-scope ; inline
+
+: assoc>stream ( assoc -- )
+    bson-write ; inline
+
+: mdb-special-value? ( value -- ? )
+   { [ timestamp? ] [ quotation? ] [ mdbregexp? ]
+     [ oid? ] [ byte-array? ] } 1|| ;
\ No newline at end of file
index 1879c52826035660476ec8fb72ae773d5932d481..73bee76c0a693afe59d87ef521a83b5bdb8b044b 100755 (executable)
@@ -7,7 +7,7 @@ IN: contributors
 
 : changelog ( -- authors )
     image parent-directory [
-        "git log --pretty=format:%an" ascii <process-reader> lines
+        "git log --pretty=format:%an" ascii <process-reader> stream-lines
     ] with-directory ;
 
 : patch-counts ( authors -- assoc )
index eff95bbcd625c6876cccf5fb7b3076408576fcc9..274e99d2f68459a2bb33295145f670dbc521e8f5 100755 (executable)
@@ -2,10 +2,37 @@ USING: kernel io strings byte-arrays sequences namespaces math
 parser crypto.hmac tools.test ;
 IN: crypto.hmac.tests
 
-[ "\u000092\u000094rz68\u0000bb\u00001c\u000013\u0000f4\u00008e\u0000f8\u000015\u00008b\u0000fc\u00009d" ] [ 16 11 <string> "Hi There" byte-array>md5-hmac >string ] unit-test
-[ "u\u00000cx>j\u0000b0\u0000b5\u000003\u0000ea\u0000a8n1\n]\u0000b78" ] [ "Jefe" "what do ya want for nothing?" byte-array>md5-hmac >string ] unit-test
-[ "V\u0000be4R\u00001d\u000014L\u000088\u0000db\u0000b8\u0000c73\u0000f0\u0000e8\u0000b3\u0000f6" ] [ 16 HEX: aa <string> 50 HEX: dd <repetition> >byte-array byte-array>md5-hmac >string ] unit-test
+[
+    "\u000092\u000094rz68\u0000bb\u00001c\u000013\u0000f4\u00008e\u0000f8\u000015\u00008b\u0000fc\u00009d"
+] [
+    16 11 <string> "Hi There" sequence>md5-hmac >string ] unit-test
 
-[ "g[\u00000b:\eM\u0000dfN\u000012Hr\u0000dal/c+\u0000fe\u0000d9W\u0000e9" ] [ 16 11 <string> "Hi There" >byte-array byte-array>sha1-hmac >string ] unit-test
-[ "\u0000ef\u0000fc\u0000dfj\u0000e5\u0000eb/\u0000a2\u0000d2t\u000016\u0000d5\u0000f1\u000084\u0000df\u00009c%\u00009a|y" ] [ "Jefe" "what do ya want for nothing?" >byte-array byte-array>sha1-hmac >string ] unit-test
-[ "\u0000d70YM\u000016~5\u0000d5\u000095o\u0000d8\0=\r\u0000b3\u0000d3\u0000f4m\u0000c7\u0000bb" ] [ 16 HEX: aa <string> 50 HEX: dd <repetition> >byte-array byte-array>sha1-hmac >string ] unit-test
+[ "u\u00000cx>j\u0000b0\u0000b5\u000003\u0000ea\u0000a8n1\n]\u0000b78" ]
+[ "Jefe" "what do ya want for nothing?" sequence>md5-hmac >string ] unit-test
+
+[
+    "V\u0000be4R\u00001d\u000014L\u000088\u0000db\u0000b8\u0000c73\u0000f0\u0000e8\u0000b3\u0000f6"
+]
+[
+    16 HEX: aa <string>
+    50 HEX: dd <repetition> sequence>md5-hmac >string
+] unit-test
+
+[
+    "g[\u00000b:\eM\u0000dfN\u000012Hr\u0000dal/c+\u0000fe\u0000d9W\u0000e9"
+] [
+    16 11 <string> "Hi There" sequence>sha1-hmac >string
+] unit-test
+
+[
+    "\u0000ef\u0000fc\u0000dfj\u0000e5\u0000eb/\u0000a2\u0000d2t\u000016\u0000d5\u0000f1\u000084\u0000df\u00009c%\u00009a|y"
+] [
+    "Jefe" "what do ya want for nothing?" sequence>sha1-hmac >string
+] unit-test
+
+[
+    "\u0000d70YM\u000016~5\u0000d5\u000095o\u0000d8\0=\r\u0000b3\u0000d3\u0000f4m\u0000c7\u0000bb"
+] [
+    16 HEX: aa <string>
+    50 HEX: dd <repetition> sequence>sha1-hmac >string
+] unit-test
index 73b15b947315dd6fc84848f1b75f959a1c408ae3..6e6229f18243dcc4ca9bb100ca473f422d7e1cb5 100755 (executable)
@@ -6,6 +6,8 @@ io.streams.byte-array kernel math math.vectors memoize sequences
 io.encodings.binary ;
 IN: crypto.hmac
 
+<PRIVATE
+
 : sha1-hmac ( Ko Ki -- hmac )
     initialize-sha1 process-sha1-block
     stream>sha1 get-sha1
@@ -24,6 +26,7 @@ IN: crypto.hmac
     [ bitxor ] 2map ;
 
 MEMO: ipad ( -- seq ) 64 HEX: 36 <array> ;
+
 MEMO: opad ( -- seq ) 64 HEX: 5c <array> ;
 
 : init-hmac ( K -- o i )
@@ -31,13 +34,15 @@ MEMO: opad ( -- seq ) 64 HEX: 5c <array> ;
     [ opad seq-bitxor ] keep
     ipad seq-bitxor ;
 
+PRIVATE>
+
 : stream>sha1-hmac ( K stream -- hmac )
     [ init-hmac sha1-hmac ] with-input-stream ;
 
 : file>sha1-hmac ( K path -- hmac )
     binary <file-reader> stream>sha1-hmac ;
 
-: byte-array>sha1-hmac ( K string -- hmac )
+: sequence>sha1-hmac ( K sequence -- hmac )
     binary <byte-reader> stream>sha1-hmac ;
 
 : stream>md5-hmac ( K stream -- hmac )
@@ -46,5 +51,5 @@ MEMO: opad ( -- seq ) 64 HEX: 5c <array> ;
 : file>md5-hmac ( K path -- hmac )
     binary <file-reader> stream>md5-hmac ;
 
-: byte-array>md5-hmac ( K string -- hmac )
+: sequence>md5-hmac ( K sequence -- hmac )
     binary <byte-reader> stream>md5-hmac ;
diff --git a/extra/drills/deployed/deploy.factor b/extra/drills/deployed/deploy.factor
new file mode 100644 (file)
index 0000000..2f62912
--- /dev/null
@@ -0,0 +1,15 @@
+USING: tools.deploy.config ;
+H{
+    { deploy-unicode? f }
+    { deploy-threads? t }
+    { deploy-math? t }
+    { deploy-name "drills" }
+    { deploy-ui? t }
+    { deploy-compiler? t }
+    { "stop-after-last-window?" t }
+    { deploy-word-props? f }
+    { deploy-c-types? f }
+    { deploy-io 2 }
+    { deploy-word-defs? f }
+    { deploy-reflection 1 }
+}
diff --git a/extra/drills/deployed/deployed.factor b/extra/drills/deployed/deployed.factor
new file mode 100644 (file)
index 0000000..43873c9
--- /dev/null
@@ -0,0 +1,36 @@
+USING: accessors arrays cocoa.dialogs combinators continuations
+fry grouping io.encodings.utf8 io.files io.styles kernel math
+math.parser models models.arrow models.history namespaces random
+sequences splitting ui ui.gadgets.alerts ui.gadgets.book-extras
+ui.gadgets.books ui.gadgets.buttons ui.gadgets.frames
+ui.gadgets.grids ui.gadgets.labels ui.gadgets.tracks fonts
+wrap.strings system ;
+
+IN: drills.deployed
+SYMBOLS: it startLength ;
+: big ( gadget -- gadget ) T{ font { name "sans-serif" } { size 30 } } >>font ;
+: card ( model quot -- button ) <arrow> <label-control> big [ next ] <book-btn> ;
+: op ( quot str -- gadget ) <label> big swap <book-bevel-btn> ;
+
+: show ( model -- gadget ) dup it set-global [ random ] <arrow>
+   { [ [ first ] card ]
+     [ [ second ] card ]
+     [ '[ |<< it get _ model-changed ] "No" op ]
+          [ '[ |<< [ it get [
+        _ value>> swap remove
+        [ [ it get go-back ] "Drill Complete" alert return ] when-empty
+     ] change-model ] with-return ] "Yes" op ]
+   } cleave
+2array { 1 0 } <track> swap [ 0.5 track-add ] each
+3array <book*> 3 3 <frame> { 1 1 } >>filled-cell { 450 175 } >>pref-dim swap { 1 1 } grid-add
+it get [ length startLength get swap - number>string "/" startLength get number>string 3append ] <arrow> <label-control> { 1 2 } grid-add ;
+
+: drill ( -- ) [
+   open-panel [
+         [ utf8 file-lines [ "\t" split [ 25 wrap-string ] map ] map dup [ first2 swap 2array ] map append ] map concat
+            [ length startLength set-global ] keep <history> [ add-history ] [ show ] bi
+         "Got it?" open-window
+   ] [ 0 exit ] if*
+] with-ui ;
+
+MAIN: drill
\ No newline at end of file
diff --git a/extra/drills/deployed/tags.txt b/extra/drills/deployed/tags.txt
new file mode 100644 (file)
index 0000000..6bf6830
--- /dev/null
@@ -0,0 +1 @@
+unportable
index 98da12959b881689364366b4813abed904ca26b4..9ee4e9b6ebc23636c1c63cc6e5fa97efd920a42f 100644 (file)
@@ -3,40 +3,34 @@ fry grouping io.encodings.utf8 io.files io.styles kernel math
 math.parser models models.arrow models.history namespaces random
 sequences splitting ui ui.gadgets.alerts ui.gadgets.book-extras
 ui.gadgets.books ui.gadgets.buttons ui.gadgets.frames
-ui.gadgets.grids ui.gadgets.labels ui.gadgets.tracks ui.gestures
-ui.gadgets.corners ;
+ui.gadgets.grids ui.gadgets.labels ui.gadgets.tracks fonts
+wrap.strings ;
 
 IN: drills
 SYMBOLS: it startLength ;
-: big ( gadget -- gadget ) { "sans-serif" plain 30 } >>font ;
+: big ( gadget -- gadget ) T{ font { name "sans-serif" } { size 30 } } >>font ;
 : card ( model quot -- button ) <arrow> <label-control> big [ next ] <book-btn> ;
 : op ( quot str -- gadget ) <label> big swap <book-bevel-btn> ;
 
 : show ( model -- gadget ) dup it set-global [ random ] <arrow>
    { [ [ first ] card ]
-   [ [ [ second ] [ drop [ "malformed input" throw ] "Malformed Input" alert ] recover ] card ]
-   [ '[ |<< [ it get [
-      _ value>> swap remove
-      [ [ it get go-back ] "Drill Complete" alert return ] when-empty
-   ] change-model ] with-return ] "Yes" op ]
-   [ '[ |<< it get _ model-changed ] "No" op ] } cleave
+     [ [ second ] card ]
+     [ '[ |<< it get _ model-changed ] "No" op ]
+          [ '[ |<< [ it get [
+        _ value>> swap remove
+        [ [ it get go-back ] "Drill Complete" alert return ] when-empty
+     ] change-model ] with-return ] "Yes" op ]
+   } cleave
 2array { 1 0 } <track> swap [ 0.5 track-add ] each
-3array <book*> 3 3 <frame> { 450 175 } >>pref-dim swap @center grid-add
-it get [ length startLength get swap - number>string "/" startLength get number>string 3append ] <arrow> <label-control> @bottom grid-add ;
+3array <book*> 3 3 <frame> { 1 1 } >>filled-cell { 450 175 } >>pref-dim swap { 1 1 } grid-add
+it get [ length startLength get swap - number>string "/" startLength get number>string 3append ] <arrow> <label-control> { 1 2 } grid-add ;
 
-: drill ( -- ) [ 
+: drill ( -- ) [
    open-panel [
-      [ utf8 file-lines [ "\t" split
-         [ " " split 4 group [ " " join ] map ] map ] map ] map concat dup [ [ first ] [ second ] bi swap 2array ] map append
-         [ length startLength set-global ] keep <history> [ add-history ] [ show ] bi
-      "Got it?" open-window
+         [ utf8 file-lines [ "\t" split [ 25 wrap-string ] map ] map dup [ first2 swap 2array ] map append ] map concat
+            [ length startLength set-global ] keep <history> [ add-history ] [ show ] bi
+         "Got it?" open-window
    ] when*
 ] with-ui ;
 
-
-MAIN: drill
-
-    
-! FIXME: command-line opening
-! TODO: Menu bar
-! TODO: Pious hot-buttons
\ No newline at end of file
+MAIN: drill
\ No newline at end of file
diff --git a/extra/file-trees/file-trees-tests.factor b/extra/file-trees/file-trees-tests.factor
new file mode 100644 (file)
index 0000000..dbb8f9f
--- /dev/null
@@ -0,0 +1,4 @@
+USING: kernel file-trees ;
+IN: file-trees.tests
+{ "/sample/1" "/sample/2" "/killer/1" "/killer/2/3"
+"/killer/2/4" "/killer/2/4/6" "/megakiller" } create-tree drop
\ No newline at end of file
diff --git a/extra/file-trees/file-trees.factor b/extra/file-trees/file-trees.factor
new file mode 100644 (file)
index 0000000..788291c
--- /dev/null
@@ -0,0 +1,23 @@
+USING: accessors delegate delegate.protocols io.pathnames
+kernel locals namespaces sequences vectors
+tools.annotations prettyprint ;
+IN: file-trees
+
+TUPLE: tree node children ;
+CONSULT: sequence-protocol tree children>> [ node>> ] map ;
+
+: <tree> ( start -- tree ) V{ } clone
+   [ tree boa dup children>> ] [ ".." swap tree boa ] bi swap push ;
+
+DEFER: (tree-insert)
+
+: tree-insert ( path tree -- ) [ unclip <tree> ] [ children>> ] bi* (tree-insert) ;
+:: (tree-insert) ( path-rest path-head tree-children -- )
+   tree-children [ node>> path-head node>> = ] find nip
+   [ path-rest swap tree-insert ]
+   [ 
+      path-head tree-children push
+      path-rest [ path-head tree-insert ] unless-empty
+   ] if* ;
+: create-tree ( file-list -- tree ) [ path-components ] map
+   t <tree> [ [ tree-insert ] curry each ] keep ;
\ No newline at end of file
diff --git a/extra/fuel/fuel-tests.factor b/extra/fuel/fuel-tests.factor
new file mode 100644 (file)
index 0000000..a0cab88
--- /dev/null
@@ -0,0 +1,33 @@
+! Copyright (C) 2009 Nicholas Seckar.
+! See http://factorcode.org/license.txt for BSD license.
+USING: continuations eval fuel fuel.private namespaces tools.test words ;
+IN: fuel.tests
+
+: fake-continuation ( -- continuation )
+    f f f "fake" f <continuation> ;
+
+: make-uses-restart ( -- restart )
+    "Use the words vocabulary" \ word?
+    fake-continuation <restart> ;
+
+: make-defer-restart ( -- restart )
+    "Defer word in current vocabulary" f
+    fake-continuation <restart> ;
+
+{ f } [ make-defer-restart is-use-restart ] unit-test
+{ t } [ make-uses-restart is-use-restart ] unit-test
+
+{ "words" } [ make-uses-restart get-restart-vocab ] unit-test
+
+{ f } [ make-defer-restart is-suggested-restart ] unit-test
+{ f } [ make-uses-restart is-suggested-restart ] unit-test
+{ f } [ { "io" } :uses-suggestions
+        [ make-uses-restart is-suggested-restart ] with-variable
+] unit-test
+{ t } [ { "words" } :uses-suggestions
+        [ make-uses-restart is-suggested-restart ] with-variable
+] unit-test
+
+{ } [
+    { "kernel" } [ "\\ dup drop" eval( -- ) ] fuel-use-suggested-vocabs
+] unit-test
index 413aefdc761e62d69b9a2a6c6db89a8f4370eb08..a9ed17877ee9ebc6e095ea8c8f8beaa9419cd3e5 100644 (file)
@@ -1,9 +1,9 @@
 ! Copyright (C) 2008, 2009 Jose Antonio Ortega Ruiz.
 ! See http://factorcode.org/license.txt for BSD license.
 
-USING: assocs compiler.units fuel.eval fuel.help fuel.remote fuel.xref
-help.topics io.pathnames kernel namespaces parser sequences
-tools.scaffold vocabs.loader ;
+USING: accessors assocs compiler.units continuations fuel.eval fuel.help
+fuel.remote fuel.xref help.topics io.pathnames kernel namespaces parser
+sequences tools.scaffold vocabs.loader words ;
 
 IN: fuel
 
@@ -28,6 +28,22 @@ IN: fuel
 <PRIVATE
 
 SYMBOL: :uses
+SYMBOL: :uses-suggestions
+
+: is-use-restart ( restart -- ? )
+    name>> [ "Use the " head? ] [ " vocabulary" tail? ] bi and ;
+
+: get-restart-vocab ( restart -- vocab/f )
+    obj>> dup word? [ vocabulary>> ] [ drop f ] if ;
+
+: is-suggested-restart ( restart -- ? )
+    dup is-use-restart [
+        get-restart-vocab :uses-suggestions get member?
+    ] [ drop f ] if ;
+
+: try-suggested-restarts ( -- )
+    restarts get [ is-suggested-restart ] filter
+    dup length 1 = [ first restart ] [ drop ] if ;
 
 : fuel-set-use-hook ( -- )
     [ amended-use get clone :uses prefix fuel-eval-set-result ]
@@ -38,6 +54,10 @@ SYMBOL: :uses
 
 PRIVATE>
 
+: fuel-use-suggested-vocabs ( suggestions quot -- ... )
+    [ :uses-suggestions set ] dip
+    [ try-suggested-restarts rethrow ] recover ; inline
+
 : fuel-run-file ( path -- )
     [ fuel-set-use-hook run-file ] curry with-scope ; inline
 
index a2beaf6d9bb6682ce285ddf2184cff412fec9088..20815859ab341a624d087363630270a3f5536221 100755 (executable)
@@ -2,10 +2,10 @@ USING: windows.dinput windows.dinput.constants parser
 alien.c-types windows.ole32 namespaces assocs kernel arrays
 vectors windows.kernel32 windows.com windows.dinput shuffle
 windows.user32 windows.messages sequences combinators locals
-math.rectangles accessors math windows alien
-alien.strings io.encodings.utf16 io.encodings.utf16n
-continuations byte-arrays game-input.dinput.keys-array
-game-input ui.backend.windows ;
+math.rectangles accessors math alien alien.strings
+io.encodings.utf16 io.encodings.utf16n continuations
+byte-arrays game-input.dinput.keys-array game-input
+ui.backend.windows windows.errors ;
 IN: game-input.dinput
 
 SINGLETON: dinput-game-input-backend
@@ -22,7 +22,7 @@ SYMBOLS: +dinput+ +keyboard-device+ +keyboard-state+
     +dinput+ set-global ;
 
 : delete-dinput ( -- )
-    +dinput+ global [ com-release f ] change-at ;
+    +dinput+ [ com-release f ] change-global ;
 
 : device-for-guid ( guid -- device )
     +dinput+ get swap f <void*>
@@ -172,10 +172,8 @@ TUPLE: window-rect < rect window-loc ;
     [ +device-change-window+ set-global ] bi ;
 
 : close-device-change-window ( -- )
-    +device-change-handle+ global
-    [ UnregisterDeviceNotification drop f ] change-at
-    +device-change-window+ global
-    [ DestroyWindow win32-error=0/f f ] change-at ;
+    +device-change-handle+ [ UnregisterDeviceNotification drop f ] change-global
+    +device-change-window+ [ DestroyWindow win32-error=0/f f ] change-global ;
 
 : add-wm-devicechange ( -- )
     [ 4dup handle-wm-devicechange DefWindowProc ]
@@ -185,14 +183,11 @@ TUPLE: window-rect < rect window-loc ;
     WM_DEVICECHANGE wm-handlers get-global delete-at ;
 
 : release-controllers ( -- )
-    +controller-devices+ global [
-        [ drop com-release ] assoc-each f
-    ] change-at
+    +controller-devices+ [ [ drop com-release ] assoc-each f ] change-global
     f +controller-guids+ set-global ;
 
 : release-keyboard ( -- )
-    +keyboard-device+ global
-    [ com-release f ] change-at
+    +keyboard-device+ [ com-release f ] change-global
     f +keyboard-state+ set-global ;
 
 M: dinput-game-input-backend (open-game-input)
index 254ed61ab0516543c9abe32ee88a5ac409cd6516..2ded2638996402ff893906d1ec5f1a2c387a39ea 100755 (executable)
@@ -239,7 +239,7 @@ M: iokit-game-input-backend (reset-game-input)
 
 M: iokit-game-input-backend (close-game-input)
     +hid-manager+ get-global [
-        +hid-manager+ global 
+        +hid-manager+ [ 
             [
                 CFRunLoopGetMain CFRunLoopDefaultMode
                 IOHIDManagerUnscheduleFromRunLoop
@@ -247,7 +247,7 @@ M: iokit-game-input-backend (close-game-input)
             [ 0 IOHIDManagerClose drop ]
             [ CFRelease ] tri
             f
-        ] change-at
+        ] change-global
         f +keyboard-state+ set-global
         f +controller-states+ set-global
     ] when ;
diff --git a/extra/game-loop/game-loop.factor b/extra/game-loop/game-loop.factor
new file mode 100644 (file)
index 0000000..8e7c701
--- /dev/null
@@ -0,0 +1,93 @@
+USING: accessors destructors kernel math math.order namespaces
+system threads ;
+IN: game-loop
+
+TUPLE: game-loop
+    { tick-length integer read-only }
+    delegate
+    { last-tick integer }
+    thread 
+    { running? boolean }
+    { tick-number integer }
+    { frame-number integer }
+    { benchmark-time integer }
+    { benchmark-tick-number integer }
+    { benchmark-frame-number integer } ;
+
+GENERIC: tick* ( delegate -- )
+GENERIC: draw* ( tick-slice delegate -- )
+
+SYMBOL: game-loop
+
+: since-last-tick ( loop -- milliseconds )
+    last-tick>> millis swap - ;
+
+: tick-slice ( loop -- slice )
+    [ since-last-tick ] [ tick-length>> ] bi /f 1.0 min ;
+
+CONSTANT: MAX-FRAMES-TO-SKIP 5
+
+<PRIVATE
+
+: redraw ( loop -- )
+    [ 1+ ] change-frame-number
+    [ tick-slice ] [ delegate>> ] bi draw* ;
+
+: tick ( loop -- )
+    delegate>> tick* ;
+
+: increment-tick ( loop -- )
+    [ 1+ ] change-tick-number
+    dup tick-length>> [ + ] curry change-last-tick
+    drop ;
+
+: ?tick ( loop count -- )
+    dup zero? [ drop millis >>last-tick drop ] [
+        over [ since-last-tick ] [ tick-length>> ] bi >=
+        [ [ drop increment-tick ] [ drop tick ] [ 1- ?tick ] 2tri ]
+        [ 2drop ] if
+    ] if ;
+
+: (run-loop) ( loop -- )
+    dup running?>>
+    [ [ MAX-FRAMES-TO-SKIP ?tick ] [ redraw ] [ yield (run-loop) ] tri ]
+    [ drop ] if ;
+
+: run-loop ( loop -- )
+    dup game-loop [ (run-loop) ] with-variable ;
+
+: benchmark-millis ( loop -- millis )
+    millis swap benchmark-time>> - ;
+
+PRIVATE>
+
+: reset-loop-benchmark ( loop -- )
+    millis >>benchmark-time
+    dup tick-number>> >>benchmark-tick-number
+    dup frame-number>> >>benchmark-frame-number
+    drop ;
+
+: benchmark-ticks-per-second ( loop -- n )
+    [ tick-number>> ] [ benchmark-tick-number>> - ] [ benchmark-millis ] tri /f ;
+: benchmark-frames-per-second ( loop -- n )
+    [ frame-number>> ] [ benchmark-frame-number>> - ] [ benchmark-millis ] tri /f ;
+
+: start-loop ( loop -- )
+    millis >>last-tick
+    t >>running?
+    [ reset-loop-benchmark ]
+    [ [ run-loop ] curry "game loop" spawn ]
+    [ (>>thread) ] tri ;
+
+: stop-loop ( loop -- )
+    f >>running?
+    f >>thread
+    drop ;
+
+: <game-loop> ( tick-length delegate -- loop )
+    millis f f 0 0 millis 0 0
+    game-loop boa ;
+
+M: game-loop dispose
+    stop-loop ;
+
index d145b3bd2c447861c04d1101d3644d3ce79a4f5e..161a81d555cca122d66373cedcd1941b82246e5d 100644 (file)
@@ -33,7 +33,7 @@ M: object handle-message drop ;
         "--pretty=format:%h %an: %s" ,
         ".." glue ,
     ] { } make
-    latin1 [ input-stream get lines ] with-process-reader ;
+    latin1 [ lines ] with-process-reader ;
 
 : updates ( from to -- lines )
     git-log reverse
index 285a684f0659993167239f349579391483c4b6df..b255b351f0cb613368a48d4d2f57ed87209c3a04 100755 (executable)
@@ -16,7 +16,7 @@ M: output-process-error error.
 
 : try-output-process ( command -- )
     >process +stdout+ >>stderr utf8 <process-reader*>
-    [ contents ] [ dup wait-for-process ] bi*
+    [ stream-contents ] [ dup wait-for-process ] bi*
     0 = [ 2drop ] [ output-process-error ] if ;
 
 HOOK: really-delete-tree os ( path -- )
diff --git a/extra/merger/deploy.factor b/extra/merger/deploy.factor
new file mode 100644 (file)
index 0000000..54535d5
--- /dev/null
@@ -0,0 +1,15 @@
+USING: tools.deploy.config ;
+H{
+    { deploy-math? t }
+    { deploy-io 2 }
+    { deploy-unicode? t }
+    { deploy-c-types? f }
+    { "stop-after-last-window?" t }
+    { deploy-ui? t }
+    { deploy-reflection 1 }
+    { deploy-compiler? t }
+    { deploy-name "Merger" }
+    { deploy-word-props? f }
+    { deploy-threads? t }
+    { deploy-word-defs? f }
+}
diff --git a/extra/merger/merger.factor b/extra/merger/merger.factor
new file mode 100644 (file)
index 0000000..c4986bf
--- /dev/null
@@ -0,0 +1,30 @@
+USING: accessors arrays fry io.directories kernel models sequences sets ui
+ui.gadgets ui.gadgets.buttons ui.gadgets.labeled
+ui.gadgets.tracks ui.gadgets.labels ui.gadgets.glass
+math.rectangles cocoa.dialogs ;
+IN: merger
+: main ( -- ) [
+   vertical <track>
+    { "From:" "To:" } f <model> f <model> 2array
+    [
+      [
+         "…" [
+            open-panel [ first
+            [ <label> 1array >>children drop ]
+            [ swap set-control-value ] 2bi ] [ drop ] if*
+         ] <border-button> swap >>model swap <labeled-gadget>
+         1 track-add
+      ] 2each
+    ] keep
+    dup first2
+    '[ _ [ value>> ] all? [ parent>> "processing..." <label> [
+         <zero-rect> show-glass
+         _ value>> [
+            "." _ value>> [ [ directory-files ] bi@ diff ] keep copy-files-into
+         ] with-directory
+      ] keep hide-glass
+    ] [ drop ] if ]
+    "merge" swap <border-button> 0.4 track-add { 300 220 } >>pref-dim "Merging" open-window
+] with-ui ;
+
+MAIN: main
\ No newline at end of file
diff --git a/extra/merger/tags.txt b/extra/merger/tags.txt
new file mode 100644 (file)
index 0000000..c80b8b4
--- /dev/null
@@ -0,0 +1,2 @@
+unportable
+
diff --git a/extra/modules/remote-loading/authors.txt b/extra/modules/remote-loading/authors.txt
new file mode 100644 (file)
index 0000000..2300f69
--- /dev/null
@@ -0,0 +1 @@
+Sam Anklesaria
diff --git a/extra/modules/remote-loading/remote-loading.factor b/extra/modules/remote-loading/remote-loading.factor
new file mode 100644 (file)
index 0000000..7a51f24
--- /dev/null
@@ -0,0 +1,4 @@
+USING: modules.rpc-server vocabs ;
+IN: modules.remote-loading mem-service
+
+: get-vocab ( vocabstr -- vocab ) vocab ;
\ No newline at end of file
diff --git a/extra/modules/remote-loading/summary.txt b/extra/modules/remote-loading/summary.txt
new file mode 100644 (file)
index 0000000..304f855
--- /dev/null
@@ -0,0 +1 @@
+required for listeners allowing remote loading of modules
\ No newline at end of file
diff --git a/extra/modules/rpc-server/authors.txt b/extra/modules/rpc-server/authors.txt
new file mode 100644 (file)
index 0000000..2300f69
--- /dev/null
@@ -0,0 +1 @@
+Sam Anklesaria
diff --git a/extra/modules/rpc-server/rpc-server.factor b/extra/modules/rpc-server/rpc-server.factor
new file mode 100644 (file)
index 0000000..525ff35
--- /dev/null
@@ -0,0 +1,37 @@
+USING: accessors assocs continuations effects io
+io.encodings.binary io.servers.connection kernel
+memoize namespaces parser sets sequences serialize
+threads vocabs vocabs.parser words ;
+
+IN: modules.rpc-server
+
+SYMBOL: serving-vocabs V{ } clone serving-vocabs set-global
+
+: do-rpc ( args word -- bytes )
+   [ execute ] curry with-datastack object>bytes ; inline
+
+MEMO: mem-do-rpc ( args word -- bytes ) do-rpc ; inline
+
+: process ( vocabspec -- ) vocab-words [ deserialize ] dip deserialize
+   swap at "executer" get execute( args word -- bytes ) write flush ;
+
+: (serve) ( -- ) deserialize dup serving-vocabs get-global index
+   [ process ] [ drop ] if ;
+
+: start-serving-vocabs ( -- ) [
+   <threaded-server> 5000 >>insecure binary >>encoding [ (serve) ] >>handler
+   start-server ] in-thread ;
+
+: (service) ( -- ) serving-vocabs get-global empty? [ start-serving-vocabs ] when
+   current-vocab serving-vocabs get-global adjoin
+   "get-words" create-in
+   in get [ vocab vocab-words [ stack-effect ] { } assoc-map-as ] curry
+   (( -- words )) define-inline ;
+
+SYNTAX: service \ do-rpc  "executer" set (service) ;
+SYNTAX: mem-service \ mem-do-rpc "executer" set (service) ;
+
+load-vocab-hook [
+   [ dup words>> values
+   \ mem-do-rpc "memoize" word-prop [ delete-at ] curry each ]
+append ] change-global
\ No newline at end of file
diff --git a/extra/modules/rpc-server/summary.txt b/extra/modules/rpc-server/summary.txt
new file mode 100644 (file)
index 0000000..396a1c8
--- /dev/null
@@ -0,0 +1 @@
+remote procedure call server
\ No newline at end of file
diff --git a/extra/modules/rpc/authors.txt b/extra/modules/rpc/authors.txt
new file mode 100644 (file)
index 0000000..2300f69
--- /dev/null
@@ -0,0 +1 @@
+Sam Anklesaria
diff --git a/extra/modules/rpc/rpc-docs.factor b/extra/modules/rpc/rpc-docs.factor
new file mode 100644 (file)
index 0000000..af99d21
--- /dev/null
@@ -0,0 +1,9 @@
+USING: help.syntax help.markup ;
+IN: modules.rpc
+ARTICLE: { "modules" "protocol" } "RPC Protocol"
+{ $list
+   "Send vocab as string"
+   "Send arglist"
+   "Send word as string"
+   "Receive result list"
+} ;
\ No newline at end of file
diff --git a/extra/modules/rpc/rpc.factor b/extra/modules/rpc/rpc.factor
new file mode 100644 (file)
index 0000000..1c1217a
--- /dev/null
@@ -0,0 +1,26 @@
+USING: accessors compiler.units combinators fry generalizations io
+io.encodings.binary io.sockets kernel namespaces
+parser sequences serialize vocabs vocabs.parser words ;
+IN: modules.rpc
+
+DEFER: get-words
+
+: remote-quot ( addrspec vocabspec effect str -- quot )
+   '[ _ 5000 <inet> binary
+      [
+         _ serialize _ in>> length narray serialize _ serialize flush deserialize dup length firstn
+      ] with-client
+    ] ;
+
+: define-remote ( addrspec vocabspec effect str -- ) [
+      [ remote-quot ] 2keep create-in -rot define-declared word make-inline
+   ] with-compilation-unit ;
+
+: with-in ( vocab quot -- vocab ) over
+   [ '[ _ set-in @ ] in get swap dip set-in ] dip vocab ; inline
+
+: remote-vocab ( addrspec vocabspec -- vocab )
+   dup "-remote" append [ 
+      [ (( -- words )) [ "get-words" remote-quot ] keep call-effect ] 2keep
+      [ rot first2 swap define-remote ] 2curry each
+   ] with-in ;
\ No newline at end of file
diff --git a/extra/modules/rpc/summary.txt b/extra/modules/rpc/summary.txt
new file mode 100644 (file)
index 0000000..cc1501f
--- /dev/null
@@ -0,0 +1 @@
+remote procedure call client
\ No newline at end of file
diff --git a/extra/modules/uploads/authors.txt b/extra/modules/uploads/authors.txt
new file mode 100644 (file)
index 0000000..2300f69
--- /dev/null
@@ -0,0 +1 @@
+Sam Anklesaria
diff --git a/extra/modules/uploads/summary.txt b/extra/modules/uploads/summary.txt
new file mode 100644 (file)
index 0000000..1ba8ffe
--- /dev/null
@@ -0,0 +1 @@
+module pushing in remote-loading listeners
\ No newline at end of file
diff --git a/extra/modules/uploads/uploads.factor b/extra/modules/uploads/uploads.factor
new file mode 100644 (file)
index 0000000..137a2c9
--- /dev/null
@@ -0,0 +1,5 @@
+USING: assocs modules.rpc-server vocabs
+modules.remote-loading words ;
+IN: modules.uploads service
+
+: upload-vocab ( word binary -- ) \ get-vocab "memoize" word-prop set-at ;
\ No newline at end of file
diff --git a/extra/modules/using/authors.txt b/extra/modules/using/authors.txt
new file mode 100644 (file)
index 0000000..2300f69
--- /dev/null
@@ -0,0 +1 @@
+Sam Anklesaria
diff --git a/extra/modules/using/summary.txt b/extra/modules/using/summary.txt
new file mode 100644 (file)
index 0000000..6bafda7
--- /dev/null
@@ -0,0 +1 @@
+improved module import syntax
\ No newline at end of file
diff --git a/extra/modules/using/tests/tags.txt b/extra/modules/using/tests/tags.txt
new file mode 100644 (file)
index 0000000..6bf6830
--- /dev/null
@@ -0,0 +1 @@
+unportable
diff --git a/extra/modules/using/tests/test-server.factor b/extra/modules/using/tests/test-server.factor
new file mode 100644 (file)
index 0000000..3e6b736
--- /dev/null
@@ -0,0 +1,3 @@
+USING: modules.rpc-server io.servers.connection ;
+IN: modules.test-server service
+: rpc-hello ( -- str ) "hello world" stop-this-server ;
\ No newline at end of file
diff --git a/extra/modules/using/tests/tests.factor b/extra/modules/using/tests/tests.factor
new file mode 100644 (file)
index 0000000..894075a
--- /dev/null
@@ -0,0 +1,4 @@
+USING: modules.using ;
+IN: modules.using.tests
+USING: tools.test localhost::modules.test-server ;
+[ "hello world" ] [ rpc-hello ] unit-test
\ No newline at end of file
diff --git a/extra/modules/using/using-docs.factor b/extra/modules/using/using-docs.factor
new file mode 100644 (file)
index 0000000..c78e546
--- /dev/null
@@ -0,0 +1,14 @@
+USING: modules.using modules.rpc-server help.syntax help.markup strings ;
+IN: modules
+
+HELP: service
+{ $syntax "IN: module service" }
+{ $description "Starts a server for requests for remote procedure calls." } ;
+
+ARTICLE: { "modules" "remote-loading" } "Using the remote-loading vocabulary"
+"If loaded, starts serving vocabularies, accessable through a " { $link POSTPONE: USING: } " form" ;
+
+HELP: USING:
+{ $syntax "USING: rpc-server::module fetch-sever::module { module qualified-name } { module => word ... } ... ;" }
+{ $description "Adds vocabularies to the front of the search path.  Vocabularies can be fetched remotely, if preceded by a valid hostname.  Name pairs facilitate imports like in the "
+{ $link POSTPONE: QUALIFIED: } " or " { $link POSTPONE: FROM: } " forms." } ;
\ No newline at end of file
diff --git a/extra/modules/using/using.factor b/extra/modules/using/using.factor
new file mode 100644 (file)
index 0000000..b0891aa
--- /dev/null
@@ -0,0 +1,36 @@
+USING: assocs kernel modules.remote-loading modules.rpc
+namespaces peg peg.ebnf peg-lexer sequences vocabs vocabs.parser
+strings ;
+IN: modules.using
+
+: >qualified ( vocab prefix -- assoc )
+    [ vocab-words ] [ 58 suffix ] bi* [ swap [ prepend ] dip ] curry assoc-map ;
+
+: >partial-vocab ( words assoc -- assoc )
+    [ dupd at [ no-word-error ] unless* ] curry { } map>assoc ;
+
+: remote-load ( addr vocabspec -- voab ) [ "modules.remote-loading" remote-vocab (use+) ] dip get-vocab ;
+
+: load'em ( vocab words/? -- ) [ swap >partial-vocab ] when* use get push ;
+
+EBNF: modulize
+tokenpart = (!(':').)+ => [[ >string ]]
+s = ':' => [[ drop ignore ]]
+rpc = tokenpart s s tokenpart => [[ first2 remote-vocab ]]
+remote = tokenpart s tokenpart => [[ first2 remote-load ]]
+plain = tokenpart => [[ load-vocab ]]
+module = rpc | remote | plain
+;EBNF
+
+ON-BNF: USING:
+tokenizer = <foreign factor>
+sym = !(";"|"}"|"=>").
+modspec = sym => [[ modulize ]]
+qualified = modspec sym => [[ first2 >qualified ]]
+unqualified = modspec => [[ vocab-words ]]
+words = ("=>" sym+ )? => [[ [ f ] [ second ] if-empty ]]
+long = "{" ( qualified | unqualified ) words "}" => [[ rest first2 load'em ignore ]]
+short = modspec => [[ use+ ignore ]]
+wordSpec = long | short
+using = wordSpec+ ";" => [[ drop ignore ]]
+;ON-BNF
\ No newline at end of file
diff --git a/extra/mongodb/authors.txt b/extra/mongodb/authors.txt
new file mode 100644 (file)
index 0000000..5df962b
--- /dev/null
@@ -0,0 +1 @@
+Sascha Matzke
diff --git a/extra/mongodb/benchmark/authors.txt b/extra/mongodb/benchmark/authors.txt
new file mode 100644 (file)
index 0000000..5df962b
--- /dev/null
@@ -0,0 +1 @@
+Sascha Matzke
diff --git a/extra/mongodb/benchmark/benchmark.factor b/extra/mongodb/benchmark/benchmark.factor
new file mode 100644 (file)
index 0000000..02dfa8a
--- /dev/null
@@ -0,0 +1,312 @@
+USING: calendar math fry kernel assocs math.ranges bson.reader io.streams.byte-array
+sequences formatting combinators namespaces io tools.time prettyprint io.encodings.binary
+accessors words mongodb.driver strings math.parser tools.walker bson.writer
+tools.continuations ;
+
+IN: mongodb.benchmark
+
+SYMBOL: collection
+
+: get* ( symbol default -- value )
+    [ get ] dip or ; inline
+
+: ensure-number ( v -- n )
+    dup string? [ string>number ] when ; inline
+
+: trial-size ( -- size )
+    "per-trial" 5000 get* ensure-number ; inline flushable
+
+: batch-size ( -- size )
+    "batch-size" 100 get* ensure-number ; inline flushable
+
+TUPLE: result doc collection index batch lasterror ;
+
+: <result> ( -- ) result new result set ; inline
+
+
+CONSTANT: CHECK-KEY f 
+
+CONSTANT: DOC-SMALL H{ }
+
+CONSTANT: DOC-MEDIUM H{ { "integer" 5 }
+                        { "number" 5.05 }
+                        { "boolean" f }
+                        { "array"
+                          { "test" "benchmark" } } }
+
+CONSTANT: DOC-LARGE H{ { "base_url" "http://www.example.com/test-me" }
+                       { "total_word_count" 6743 }
+                       { "access_time" f } 
+                       { "meta_tags" H{ { "description" "i am a long description string" }
+                                        { "author" "Holly Man" }
+                                        { "dynamically_created_meta_tag" "who know\n what" } } }
+                       { "page_structure" H{ { "counted_tags" 3450 }
+                                             { "no_of_js_attached" 10 }
+                                             { "no_of_images" 6 } } }
+                       { "harvested_words" { "10gen" "web" "open" "source" "application" "paas" 
+                                             "platform-as-a-service" "technology" "helps" 
+                                             "developers" "focus" "building" "mongodb" "mongo"
+                                             "10gen" "web" "open" "source" "application" "paas" 
+                                             "platform-as-a-service" "technology" "helps" 
+                                             "developers" "focus" "building" "mongodb" "mongo"
+                                             "10gen" "web" "open" "source" "application" "paas" 
+                                             "platform-as-a-service" "technology" "helps" 
+                                             "developers" "focus" "building" "mongodb" "mongo"
+                                             "10gen" "web" "open" "source" "application" "paas" 
+                                             "platform-as-a-service" "technology" "helps" 
+                                             "developers" "focus" "building" "mongodb" "mongo"
+                                             "10gen" "web" "open" "source" "application" "paas" 
+                                             "platform-as-a-service" "technology" "helps" 
+                                             "developers" "focus" "building" "mongodb" "mongo"
+                                             "10gen" "web" "open" "source" "application" "paas" 
+                                             "platform-as-a-service" "technology" "helps" 
+                                             "developers" "focus" "building" "mongodb" "mongo"
+                                             "10gen" "web" "open" "source" "application" "paas" 
+                                             "platform-as-a-service" "technology" "helps" 
+                                             "developers" "focus" "building" "mongodb" "mongo"
+                                             "10gen" "web" "open" "source" "application" "paas" 
+                                             "platform-as-a-service" "technology" "helps" 
+                                             "developers" "focus" "building" "mongodb" "mongo"
+                                             "10gen" "web" "open" "source" "application" "paas" 
+                                             "platform-as-a-service" "technology" "helps" 
+                                             "developers" "focus" "building" "mongodb" "mongo"
+                                             "10gen" "web" "open" "source" "application" "paas" 
+                                             "platform-as-a-service" "technology" "helps" 
+                                             "developers" "focus" "building" "mongodb" "mongo"
+                                             "10gen" "web" "open" "source" "application" "paas" 
+                                             "platform-as-a-service" "technology" "helps" 
+                                             "developers" "focus" "building" "mongodb" "mongo"
+                                             "10gen" "web" "open" "source" "application" "paas" 
+                                             "platform-as-a-service" "technology" "helps" 
+                                             "developers" "focus" "building" "mongodb" "mongo"
+                                             "10gen" "web" "open" "source" "application" "paas" 
+                                             "platform-as-a-service" "technology" "helps" 
+                                             "developers" "focus" "building" "mongodb" "mongo"
+                                             "10gen" "web" "open" "source" "application" "paas" 
+                                             "platform-as-a-service" "technology" "helps" 
+                                             "developers" "focus" "building" "mongodb" "mongo"
+                                             "10gen" "web" "open" "source" "application" "paas" 
+                                             "platform-as-a-service" "technology" "helps" 
+                                             "developers" "focus" "building" "mongodb" "mongo"
+                                             "10gen" "web" "open" "source" "application" "paas" 
+                                             "platform-as-a-service" "technology" "helps" 
+                                             "developers" "focus" "building" "mongodb" "mongo"
+                                             "10gen" "web" "open" "source" "application" "paas" 
+                                             "platform-as-a-service" "technology" "helps" 
+                                             "developers" "focus" "building" "mongodb" "mongo"
+                                             "10gen" "web" "open" "source" "application" "paas" 
+                                             "platform-as-a-service" "technology" "helps" 
+                                             "developers" "focus" "building" "mongodb" "mongo"
+                                             "10gen" "web" "open" "source" "application" "paas" 
+                                             "platform-as-a-service" "technology" "helps" 
+                                             "developers" "focus" "building" "mongodb" "mongo"
+                                             "10gen" "web" "open" "source" "application" "paas" 
+                                             "platform-as-a-service" "technology" "helps" 
+                                             "developers" "focus" "building" "mongodb" "mongo" } } }
+
+: set-doc ( name -- )
+    [ result ] dip '[ _ >>doc ] change ; inline
+
+: small-doc ( -- quot )
+    "small" set-doc [ ] ; inline
+
+: medium-doc ( -- quot )
+    "medium" set-doc [ ] ; inline
+
+: large-doc ( -- quot )
+    "large" set-doc [ ] ; inline
+
+: small-doc-prepare ( -- quot: ( i -- doc ) )
+    small-doc drop
+    '[ "x" DOC-SMALL clone [ set-at ] keep ] ; 
+
+: medium-doc-prepare ( -- quot: ( i -- doc ) )
+    medium-doc drop
+    '[ "x" DOC-MEDIUM clone [ set-at ] keep ] ; 
+
+: large-doc-prepare ( -- quot: ( i -- doc ) )
+    large-doc drop
+    [ "x" DOC-LARGE clone [ set-at ] keep 
+       [ now "access-time" ] dip
+       [ set-at ] keep ] ;
+
+: (insert) ( quot: ( i -- doc ) collection -- )
+    [ trial-size ] 2dip
+    '[ _ call( i -- doc ) [ _ ] dip
+       result get lasterror>> [ save ] [ save-unsafe ] if ] each-integer ; 
+
+: (prepare-batch) ( i b quot: ( i -- doc ) -- batch-seq )
+    [ [ * ] keep 1 range boa ] dip
+    '[ _ call( i -- doc ) ] map ; 
+
+: (insert-batch) ( quot: ( i -- doc ) collection -- )
+    [ trial-size batch-size [ / ] keep ] 2dip
+    '[ _ _ (prepare-batch) [ _ ] dip
+       result get lasterror>> [ save ] [ save-unsafe ] if
+    ] each-integer ; 
+
+: bchar ( boolean -- char )
+    [ "t" ] [ "f" ] if ; inline 
+
+: collection-name ( -- collection )
+    collection "benchmark" get*
+    result get doc>>
+    result get index>> bchar
+    "%s-%s-%s" sprintf
+    [ [ result get ] dip >>collection drop ] keep ; 
+    
+: prepare-collection ( -- collection )
+    collection-name
+    [ "_x_idx" drop-index ] keep
+    [ drop-collection ] keep
+    [ create-collection ] keep ; 
+
+: prepare-index ( collection -- )
+    "_x_idx" [ "x" asc ] key-spec <index-spec> unique-index ensure-index ; 
+
+: insert ( doc-quot: ( i -- doc ) -- quot: ( -- ) )
+    prepare-collection
+    result get index>> [ [ prepare-index ] keep ] when
+    result get batch>>
+    [ '[ _ _ (insert-batch) ] ] [ '[ _ _ (insert) ] ] if ;
+
+: serialize ( doc-quot: ( i -- doc ) -- quot: ( -- ) )
+    '[ trial-size [ _ call( i -- doc ) assoc>bv drop ] each-integer ] ; 
+
+: deserialize ( doc-quot: ( i -- doc ) -- quot: ( -- ) )
+    [ 0 ] dip call( i -- doc ) assoc>bv
+    '[ trial-size [  _ binary [ H{ } stream>assoc 2drop ] with-byte-reader ] times ] ; 
+
+: check-for-key ( assoc key -- )
+    CHECK-KEY [ swap key? [ "ups... where's the key" throw ] unless ] [ 2drop ] if ; 
+
+: (check-find-result) ( result -- )
+    "x" check-for-key ; inline
+  
+: (find) ( cursor -- )
+    [ find [ (check-find-result) ] each (find) ] when* ; inline recursive
+
+: find-one ( quot -- quot: ( -- ) )
+    drop
+    [ trial-size
+      collection-name
+      trial-size 2 / "x" H{ } clone [ set-at ] keep
+      '[ _ _ <query> 1 limit (find) ] times ] ;
+  
+: find-all ( quot -- quot: ( -- ) )
+    drop
+    collection-name
+    H{ } clone
+    '[ _ _ <query> (find) ] ;
+  
+: find-range ( quot -- quot: ( -- ) )
+    drop
+    [ trial-size batch-size /i
+       collection-name
+       trial-size 2 / "$gt" H{ } clone [ set-at ] keep
+       [ trial-size 2 / batch-size + "$lt" ] dip [ set-at ] keep
+       "x" H{ } clone [ set-at ] keep
+       '[ _ _ <query> (find) ] times ] ;
+
+: batch ( -- )
+    result [ t >>batch ] change ; inline
+   
+: index ( -- )
+    result [ t >>index ] change ; inline
+
+: errcheck ( -- )
+    result [ t >>lasterror ] change ; inline
+
+: print-result ( time -- )
+    [ result get [ collection>> ] keep
+      [ batch>> bchar ] keep
+      [ index>> bchar ] keep
+      lasterror>> bchar
+      trial-size ] dip
+    1000000 / /i
+    "%-18s: {batch:%s,index:%s;errchk:%s} %10s docs/s"
+    sprintf print flush ; 
+
+: print-separator ( -- )
+    "----------------------------------------------------------------" print flush ; inline
+
+: print-separator-bold ( -- )
+    "================================================================" print flush ; inline
+
+: print-header ( -- )
+    trial-size
+    batch-size
+    "MongoDB Factor Driver Benchmark\n%d ops per Trial, Batch-Size: %d"
+    sprintf print flush
+    print-separator-bold ;
+
+: with-result ( options quot -- )
+    '[ <result> _ call( options -- time ) print-result ] with-scope ; 
+
+: [bench-quot] ( feat-seq op-word -- quot: ( doc-word -- ) )
+    '[ _ swap _
+       '[ [ [ _ execute( -- quot ) ] dip
+          [ execute( -- ) ] each _ execute( quot -- quot ) benchmark ] with-result ] each
+       print-separator ] ; 
+
+: run-serialization-bench ( doc-word-seq feat-seq -- )
+    "Serialization Tests" print
+    print-separator-bold
+    \ serialize [bench-quot] '[ _ call( doc-word -- ) ] each ; 
+
+: run-deserialization-bench ( doc-word-seq feat-seq -- )
+    "Deserialization Tests" print
+    print-separator-bold
+    \ deserialize [bench-quot] '[ _ call( doc-word -- ) ] each ; 
+    
+: run-insert-bench ( doc-word-seq feat-seq -- )
+    "Insert Tests" print
+    print-separator-bold 
+    \ insert [bench-quot] '[ _ call( doc-word -- ) ] each ; 
+
+: run-find-one-bench ( doc-word-seq feat-seq -- )
+    "Query Tests - Find-One" print
+    print-separator-bold
+    \ find-one [bench-quot] '[ _ call( doc-word -- ) ] each ; 
+
+: run-find-all-bench ( doc-word-seq feat-seq -- )
+    "Query Tests - Find-All" print
+    print-separator-bold
+    \ find-all [bench-quot] '[ _ call( doc-word -- ) ] each ; 
+
+: run-find-range-bench ( doc-word-seq feat-seq -- )
+    "Query Tests - Find-Range" print
+    print-separator-bold
+    \ find-range [bench-quot] '[ _ call( doc-word -- ) ] each ; 
+
+    
+: run-benchmarks ( -- )
+    "db" "db" get* "host" "127.0.0.1" get* "port" 27020 get* ensure-number <mdb>
+    [ print-header
+      ! serialization
+      { small-doc-prepare medium-doc-prepare
+        large-doc-prepare }
+      { { } } run-serialization-bench
+      ! deserialization
+      { small-doc-prepare medium-doc-prepare
+        large-doc-prepare }
+      { { } } run-deserialization-bench
+      ! insert
+      { small-doc-prepare medium-doc-prepare
+        large-doc-prepare }
+      { { } { index } { errcheck } { index errcheck }
+        { batch } { batch errcheck } { batch index errcheck }
+      } run-insert-bench
+      ! find-one
+      { small-doc medium-doc large-doc }
+      { { } { index } } run-find-one-bench
+      ! find-all
+      { small-doc medium-doc large-doc }
+      { { } { index } } run-find-all-bench
+      ! find-range
+      { small-doc medium-doc large-doc }
+      { { } { index } } run-find-range-bench        
+    ] with-db ;
+        
+MAIN: run-benchmarks
+
diff --git a/extra/mongodb/benchmark/summary.txt b/extra/mongodb/benchmark/summary.txt
new file mode 100644 (file)
index 0000000..5d0e4f5
--- /dev/null
@@ -0,0 +1 @@
+serialization/deserialization and insert/query benchmarks for mongodb.driver
diff --git a/extra/mongodb/connection/authors.txt b/extra/mongodb/connection/authors.txt
new file mode 100644 (file)
index 0000000..5df962b
--- /dev/null
@@ -0,0 +1 @@
+Sascha Matzke
diff --git a/extra/mongodb/connection/connection.factor b/extra/mongodb/connection/connection.factor
new file mode 100644 (file)
index 0000000..7477ee5
--- /dev/null
@@ -0,0 +1,146 @@
+USING: accessors assocs fry io.encodings.binary io.sockets kernel math
+math.parser mongodb.msg mongodb.operations namespaces destructors
+constructors sequences splitting checksums checksums.md5 formatting
+io.streams.duplex io.encodings.utf8 io.encodings.string combinators.smart
+arrays hashtables sequences.deep vectors locals ;
+
+IN: mongodb.connection
+
+: md5-checksum ( string -- digest )
+    utf8 encode md5 checksum-bytes hex-string ; inline
+
+TUPLE: mdb-db name username pwd-digest nodes collections ;
+
+TUPLE: mdb-node master? { address inet } remote ;
+
+CONSTRUCTOR: mdb-node ( address master? -- mdb-node ) ;
+
+TUPLE: mdb-connection instance node handle remote local ;
+
+CONSTRUCTOR: mdb-connection ( instance -- mdb-connection ) ;
+
+: check-ok ( result -- errmsg ? )
+    [ [ "errmsg" ] dip at ] 
+    [ [ "ok" ] dip at >integer 1 = ] bi ; inline 
+
+: <mdb-db> ( name nodes -- mdb-db )
+    mdb-db new swap >>nodes swap >>name H{ } clone >>collections ;
+
+: master-node ( mdb -- node )
+    nodes>> t swap at ;
+
+: slave-node ( mdb -- node )
+    nodes>> f swap at ;
+
+: with-connection ( connection quot -- * )
+    [ mdb-connection set ] prepose with-scope ; inline
+    
+: mdb-instance ( -- mdb )
+    mdb-connection get instance>> ; inline
+
+: index-collection ( -- ns )
+    mdb-instance name>> "%s.system.indexes" sprintf ; inline
+
+: namespaces-collection ( -- ns )
+    mdb-instance name>> "%s.system.namespaces" sprintf ; inline
+
+: cmd-collection ( -- ns )
+    mdb-instance name>> "%s.$cmd" sprintf ; inline
+
+: index-ns ( colname -- index-ns )
+    [ mdb-instance name>> ] dip "%s.%s" sprintf ; inline
+
+: send-message ( message -- )
+    [ mdb-connection get handle>> ] dip '[ _ write-message ] with-stream* ;
+
+: send-query-plain ( query-message -- result )
+    [ mdb-connection get handle>> ] dip
+    '[ _ write-message read-message ] with-stream* ;
+
+: send-query-1result ( collection assoc -- result )
+    <mdb-query-msg>
+        1 >>return#
+    send-query-plain objects>>
+    [ f ] [ first ] if-empty ;
+
+<PRIVATE
+
+: get-nonce ( -- nonce )
+    cmd-collection H{ { "getnonce" 1 } } send-query-1result 
+    [ "nonce" swap at ] [ f ] if* ;
+
+: auth? ( mdb -- ? )
+    [ username>> ] [ pwd-digest>> ] bi and ; 
+
+: calculate-key-digest ( nonce -- digest )
+    mdb-instance
+    [ username>> ]
+    [ pwd-digest>> ] bi
+    3array concat md5-checksum ; inline
+
+: build-auth-query ( -- query-assoc )
+    { "authenticate" 1 }
+    "user"  mdb-instance username>> 2array
+    "nonce" get-nonce 2array
+    3array >hashtable
+    [ [ "nonce" ] dip at calculate-key-digest "key" ] keep
+    [ set-at ] keep ; 
+    
+: perform-authentication ( --  )
+    cmd-collection build-auth-query send-query-1result
+    check-ok [ drop ] [ throw ] if ; inline
+
+: authenticate-connection ( mdb-connection -- )
+   [ mdb-connection get instance>> auth?
+     [ perform-authentication ] when
+   ] with-connection ; inline
+
+: open-connection ( mdb-connection node -- mdb-connection )
+   [ >>node ] [ address>> ] bi
+   [ >>remote ] keep binary <client>
+   [ >>handle ] dip >>local ;
+
+: get-ismaster ( -- result )
+    "admin.$cmd" H{ { "ismaster" 1 } } send-query-1result ; 
+
+: split-host-str ( hoststr -- host port )
+   ":" split [ first ] [ second string>number ] bi ; inline
+
+: eval-ismaster-result ( node result -- )
+   [ [ "ismaster" ] dip at >integer 1 = >>master? drop ]
+   [ [ "remote" ] dip at
+     [ split-host-str <inet> f <mdb-node> >>remote ] when*
+     drop ] 2bi ;
+
+: check-node ( mdb node --  )
+   [ <mdb-connection> &dispose ] dip
+   [ open-connection ] keep swap
+   [ get-ismaster eval-ismaster-result ] with-connection ;
+
+: nodelist>table ( seq -- assoc )
+   [ [ master?>> ] keep 2array ] map >hashtable ;
+   
+PRIVATE>
+
+:: verify-nodes ( mdb -- )
+    [ [let* | acc [ V{ } clone ]
+              node1 [ mdb dup master-node [ check-node ] keep ]
+              node2 [ mdb node1 remote>>
+                      [ [ check-node ] keep ]
+                      [ drop f ] if*  ]
+              | node1 [ acc push ] when*
+                node2 [ acc push ] when*
+                mdb acc nodelist>table >>nodes drop 
+              ]
+    ] with-destructors ; 
+              
+: mdb-open ( mdb -- mdb-connection )
+    clone [ <mdb-connection> ] keep
+    master-node open-connection
+    [ authenticate-connection ] keep ; 
+
+: mdb-close ( mdb-connection -- )
+     [ dispose f ] change-handle drop ;
+
+M: mdb-connection dispose
+     mdb-close ;
\ No newline at end of file
diff --git a/extra/mongodb/connection/summary.txt b/extra/mongodb/connection/summary.txt
new file mode 100644 (file)
index 0000000..44cfb3f
--- /dev/null
@@ -0,0 +1 @@
+low-level connection handling for mongodb.driver
diff --git a/extra/mongodb/driver/authors.txt b/extra/mongodb/driver/authors.txt
new file mode 100644 (file)
index 0000000..5df962b
--- /dev/null
@@ -0,0 +1 @@
+Sascha Matzke
diff --git a/extra/mongodb/driver/driver-docs.factor b/extra/mongodb/driver/driver-docs.factor
new file mode 100644 (file)
index 0000000..7dbf564
--- /dev/null
@@ -0,0 +1,283 @@
+! Copyright (C) 2009 Your name.
+! See http://factorcode.org/license.txt for BSD license.
+USING: assocs help.markup help.syntax kernel quotations ;
+IN: mongodb.driver
+
+HELP: <mdb-collection>
+{ $values
+  { "name" "name of the collection" }
+  { "collection" "mdb-collection instance" }
+}
+{ $examples { $unchecked-example "USING: mongodb.driver ;" "\"mycollection\" <mdb-collection> t >>capped 1000000 >>max" "" } }
+{ $description "Creates a new mdb-collection instance. Use this to create capped/limited collections." } ;
+
+HELP: <mdb>
+{ $values
+  { "db" "name of the database to use" }
+  { "host" "host name or IP address" }
+  { "port" "port number" }
+  { "mdb" "mdb-db instance" }
+}
+{ $description "Create a new mdb-db instance and automatically resolves master/slave information in a paired MongoDB setup." }
+{ $examples
+  { $unchecked-example "USING: mongodb.driver ;" "\"db\" \"127.0.0.1\" 27017 <mdb>" "" } } ;
+
+HELP: <query>
+{ $values
+  { "collection" "collection to query" }
+  { "assoc" "query assoc" }
+  { "mdb-query-msg" "mdb-query-msg instance" }
+}
+{ $description "Creates a new mdb-query-msg instance. "
+  "This word must be called from within a with-db scope."
+  "For more see: "
+  { $link with-db } }
+{ $examples
+  { $unchecked-example "USING: mongodb.driver ;" "\"mycollection\" H{ } <query>" "" } } ;
+
+HELP: <update>
+{ $values
+  { "collection" "collection to update" }
+  { "selector" "selector assoc (selects which object(s) to update" }
+  { "object" "updated object or update instruction" }
+  { "mdb-update-msg" "mdb-update-msg instance" }
+}
+{ $description "Creates an update message for the object(s) identified by the given selector."
+  "MongoDB supports full object updates as well as partial update modifiers such as $set, $inc or $push"
+  "For more information see: " { $url "http://www.mongodb.org/display/DOCS/Updates" } } ;
+
+HELP: >upsert
+{ $values
+  { "mdb-update-msg" "a mdb-update-msg" }
+  { "mdb-update-msg" "mdb-update-msg with the upsert indicator set to t" }
+}
+{ $description "Marks a mdb-update-msg as upsert operation"
+  "(inserts object identified by the update selector if it doesn't exist in the collection)" } ;
+
+HELP: PARTIAL?
+{ $values  
+  { "value" "partial?" }
+}
+{ $description "key which refers to a partially loaded object" } ;
+
+HELP: asc
+{ $values
+  { "key" "sort key" }
+  { "spec" "sort spec" }
+}
+{ $description "indicates that the values of the specified key should be sorted in ascending order" } ;
+
+HELP: count
+{ $values
+  { "mdb-query-msg" "query" }
+  { "result" "number of objects in the collection that match the query" }
+}
+{ $description "count objects in a collection" } ;
+
+HELP: create-collection
+{ $values
+  { "name" "collection name" }
+}
+{ $description "Creates a new collection with the given name." } ;
+
+HELP: delete
+{ $values
+  { "collection" "a collection" }
+  { "selector" "assoc which identifies the objects to be removed from the collection" }
+}
+{ $description "removes objects from the collection (with lasterror check)" } ;
+
+HELP: delete-unsafe
+{ $values
+  { "collection" "a collection" }
+  { "selector" "assoc which identifies the objects to be removed from the collection" }
+}
+{ $description "removes objects from the collection (without error check)" } ;
+
+HELP: desc
+{ $values
+  { "key" "sort key" }
+  { "spec" "sort spec" }
+}
+{ $description "indicates that the values of the specified key should be sorted in descending order" } ;
+
+HELP: drop-collection
+{ $values
+  { "name" "a collection" }
+}
+{ $description "removes the collection and all objects in it from the database" } ;
+
+HELP: drop-index
+{ $values
+  { "collection" "a collection" }
+  { "name" "an index name" }
+}
+{ $description "drops the specified index from the collection" } ;
+
+HELP: ensure-collection
+{ $values
+  { "name" "a collection; e.g. mycollection " }
+}
+{ $description "ensures that the collection exists in the database" } ;
+
+HELP: ensure-index
+{ $values
+  { "index-spec" "an index specification" }
+}
+{ $description "Ensures the existence of the given index. "
+  "For more information on MongoDB indexes see: " { $url "http://www.mongodb.org/display/DOCS/Indexes" } }
+{ $examples
+  { $unchecked-example "USING: mongodb.driver ;"
+    "\"db\" \"127.0.0.1\" 27017 <mdb>"
+    "[ \"mycollection\" nameIdx [ \"name\" asc ] keyspec <index-spec> ensure-index ] with-db" "" }
+  { $unchecked-example  "USING: mongodb.driver ;"
+    "\"db\" \"127.0.0.1\" 27017 <mdb>" "[ \"mycollection\" nameIdx [ \"name\" asc ] keyspec <index-spec> unique-index ensure-index ] with-db" "" } } ;
+
+HELP: explain.
+{ $values
+  { "mdb-query-msg" "a query message" }
+}
+{ $description "Prints the execution plan for the given query" } ;
+
+HELP: find
+{ $values
+  { "selector" "a mdb-query or mdb-cursor" }
+  { "mdb-cursor/f" "a cursor (if there are more results) or f" }
+  { "seq" "a sequences of objects" }
+}
+{ $description "executes the given query" }
+{ $examples
+  { $unchecked-example "USING: mongodb.driver ;"
+    "\"db\" \"127.0.0.1\" 27017 <mdb>"
+    "[ \"mycollection\" H{ { \"name\" \"Alfred\" } } <query> find ] with-db" "" } } ;
+
+HELP: find-one
+{ $values
+  { "mdb-query-msg" "a query" }
+  { "result/f" "a single object or f" }
+}
+{ $description "Executes the query and returns one object at most" } ;
+
+HELP: hint
+{ $values
+  { "mdb-query-msg" "a query" }
+  { "index-hint" "a hint to an index" }
+  { "mdb-query-msg" "modified query object" }
+}
+{ $description "Annotates the query with a hint to an index. "
+  "For detailed information see: " { $url "http://www.mongodb.org/display/DOCS/Optimizing+Mongo+Performance#OptimizingMongoPerformance-Hint" } }
+{ $examples
+  { $unchecked-example "USING: mongodb.driver ;"
+    "\"db\" \"127.0.0.1\" 27017 <mdb>"
+    "[ \"mycollection\" H{ { \"name\" \"Alfred\" } { \"age\" 70 } } <query> H{ { \"name\" 1 } } hint find ] with-db" "" } } ;
+
+HELP: lasterror
+{ $values
+  
+  { "error" "error message or f" }
+}
+{ $description "Checks if the last operation resulted in an error on the MongoDB side"
+  "For more information see: " { $url "http://www.mongodb.org/display/DOCS/Mongo+Commands#MongoCommands-LastErrorCommands" } } ;
+
+HELP: limit
+{ $values
+  { "mdb-query-msg" "a query" }
+  { "limit#" "number of objects that should be returned at most" }
+  { "mdb-query-msg" "modified query object" }
+}
+{ $description "Limits the number of returned objects to limit#" }
+{ $examples
+  { $unchecked-example "USING: mongodb.driver ;"
+    "\"db\" \"127.0.0.1\" 27017 <mdb>"
+    "[ \"mycollection\" H{ } <query> 10 limit find ] with-db" "" } } ;
+
+HELP: load-collection-list
+{ $values
+  
+  { "collection-list" "list of collections in the current database" }
+}
+{ $description "Returns a list of all collections that exist in the current database" } ;
+
+HELP: load-index-list
+{ $values
+  
+  { "index-list" "list of indexes" }
+}
+{ $description "Returns a list of all indexes that exist in the current database" } ;
+
+HELP: mdb-collection
+{ $var-description "MongoDB collection" } ;
+
+HELP: mdb-cursor
+{ $var-description "MongoDB cursor" } ;
+
+HELP: mdb-error
+{ $values
+  { "msg" "error message" }
+}
+{ $description "error class" } ;
+
+HELP: r/
+{ $values
+  { "token" "a regexp string" }
+  { "mdbregexp" "a mdbregexp tuple instance" }
+}
+{ $description "creates a new mdbregexp instance" } ;
+
+HELP: save
+{ $values
+  { "collection" "a collection" }
+  { "assoc" "object" }
+}
+{ $description "Saves the object to the given collection."
+  " If the object contains a field name \"_id\" this command automatically performs an update (with upsert) instead of a plain save" } ;
+
+HELP: save-unsafe
+{ $values
+  { "collection" "a collection" }
+  { "assoc" "object" }
+}
+{ $description "Save the object to the given collection without automatic error check" } ;
+
+HELP: skip
+{ $values
+  { "mdb-query-msg" "a query message" }
+  { "skip#" "number of objects to skip" }
+  { "mdb-query-msg" "annotated query message" }
+}
+{ $description "annotates a query message with a number of objects to skip when returning the results" } ;
+
+HELP: sort
+{ $values
+  { "mdb-query-msg" "a query message" }
+  { "sort-quot" "a quotation with sort specifiers" }
+  { "mdb-query-msg" "annotated query message" }
+}
+{ $description "annotates the query message for sort specifiers" } ;
+
+HELP: update
+{ $values
+  { "mdb-update-msg" "a mdb-update message" }
+}
+{ $description "performs an update" } ;
+
+HELP: update-unsafe
+{ $values
+  { "mdb-update-msg" "a mdb-update message" }
+}
+{ $description "performs an update without automatic error check" } ;
+
+HELP: validate.
+{ $values
+  { "collection" "collection to validate" }
+}
+{ $description "validates the collection" } ;
+
+HELP: with-db
+{ $values
+  { "mdb" "mdb instance" }
+  { "quot" "quotation to execute with the given mdb instance as context" }
+}
+{ $description "executes a quotation with the given mdb instance in its context" } ;
+
+
diff --git a/extra/mongodb/driver/driver.factor b/extra/mongodb/driver/driver.factor
new file mode 100644 (file)
index 0000000..a972d1c
--- /dev/null
@@ -0,0 +1,305 @@
+USING: accessors assocs bson.constants bson.writer combinators combinators.smart
+constructors continuations destructors formatting fry io io.pools
+io.encodings.binary io.sockets io.streams.duplex kernel linked-assocs hashtables
+namespaces parser prettyprint sequences sets splitting strings uuid arrays
+math math.parser memoize mongodb.connection mongodb.msg mongodb.operations  ;
+
+IN: mongodb.driver
+
+TUPLE: mdb-pool < pool mdb ;
+
+TUPLE: mdb-cursor id query ;
+
+TUPLE: mdb-collection
+{ name string }
+{ capped boolean initial: f }
+{ size integer initial: -1 }
+{ max integer initial: -1 } ;
+
+CONSTRUCTOR: mdb-collection ( name -- collection ) ;
+
+TUPLE: index-spec
+{ ns string } { name string } { key hashtable } { unique? boolean initial: f } ;
+
+CONSTRUCTOR: index-spec ( ns name key -- index-spec ) ;
+
+: unique-index ( index-spec -- index-spec )
+    t >>unique? ;
+
+M: mdb-pool make-connection
+    mdb>> mdb-open ;
+
+: <mdb-pool> ( mdb -- pool ) [ mdb-pool <pool> ] dip >>mdb ; inline
+
+CONSTANT: PARTIAL? "partial?"
+
+ERROR: mdb-error msg ;
+
+: >pwd-digest ( user password -- digest )
+    "mongo" swap 3array ":" join md5-checksum ; 
+
+<PRIVATE
+
+GENERIC: <mdb-cursor> ( id mdb-query-msg/mdb-getmore-msg -- mdb-cursor )
+
+M: mdb-query-msg <mdb-cursor>
+    mdb-cursor boa ;
+
+M: mdb-getmore-msg <mdb-cursor>
+    query>> mdb-cursor boa ;
+
+: >mdbregexp ( value -- regexp )
+   first <mdbregexp> ; inline
+
+GENERIC: update-query ( mdb-result-msg mdb-query-msg/mdb-getmore-msg -- )
+
+M: mdb-query-msg update-query 
+    swap [ start#>> ] [ returned#>> ] bi + >>skip# drop ;
+
+M: mdb-getmore-msg update-query
+    query>> update-query ; 
+      
+: make-cursor ( mdb-result-msg mdb-query-msg/mdb-getmore-msg -- mdb-cursor/f )
+    over cursor>> 0 > 
+    [ [ update-query ]
+      [ [ cursor>> ] dip <mdb-cursor> ] 2bi
+    ] [ 2drop f ] if ;
+
+DEFER: send-query
+
+GENERIC: verify-query-result ( mdb-result-msg mdb-query-msg/mdb-getmore-msg -- mdb-result-msg mdb-query-msg/mdb-getmore-msg ) 
+
+M: mdb-query-msg verify-query-result ;
+
+M: mdb-getmore-msg verify-query-result
+    over flags>> ResultFlag_CursorNotFound =
+    [ nip query>> [ send-query-plain ] keep ] when ;
+    
+: send-query ( mdb-query-msg/mdb-getmore-msg -- mdb-cursor/f seq )
+    [ send-query-plain ] keep
+    verify-query-result 
+    [ collection>> >>collection drop ]
+    [ return#>> >>requested# ] 
+    [ make-cursor ] 2tri
+    swap objects>> ;
+
+PRIVATE>
+
+SYNTAX: r/ ( token -- mdbregexp )
+    \ / [ >mdbregexp ] parse-literal ; 
+
+: with-db ( mdb quot -- * )
+    '[ _ mdb-open &dispose _ with-connection ] with-destructors ; inline
+  
+: >id-selector ( assoc -- selector )
+    [ MDB_OID_FIELD swap at ] keep
+    H{ } clone [ set-at ] keep ;
+
+: <mdb> ( db host port -- mdb )
+   <inet> t [ <mdb-node> ] keep
+   H{ } clone [ set-at ] keep <mdb-db>
+   [ verify-nodes ] keep ;
+
+GENERIC: create-collection ( name -- )
+
+M: string create-collection
+    <mdb-collection> create-collection ;
+
+M: mdb-collection create-collection
+    [ cmd-collection ] dip
+    <linked-hash> [
+        [ [ name>> "create" ] dip set-at ]
+        [ [ [ capped>> ] keep ] dip
+          '[ _ _
+             [ [ drop t "capped" ] dip set-at ]
+             [ [ size>> "size" ] dip set-at ]
+             [ [ max>> "max" ] dip set-at ] 2tri ] when
+        ] 2bi
+    ] keep <mdb-query-msg> 1 >>return# send-query-plain drop ;
+
+: load-collection-list ( -- collection-list )
+    namespaces-collection
+    H{ } clone <mdb-query-msg> send-query-plain objects>> ;
+
+<PRIVATE
+
+: ensure-valid-collection-name ( collection -- )
+    [ ";$." intersect length 0 > ] keep
+    '[ _ "%s contains invalid characters ( . $ ; )" sprintf throw ] when ; inline
+
+: (ensure-collection) ( collection --  )
+    mdb-instance collections>> dup keys length 0 = 
+    [ load-collection-list      
+      [ [ "options" ] dip key? ] filter
+      [ [ "name" ] dip at "." split second <mdb-collection> ] map
+      over '[ [ ] [ name>> ] bi _ set-at ] each ] [ ] if
+    [ dup ] dip key? [ drop ]
+    [ [ ensure-valid-collection-name ] keep create-collection ] if ; 
+
+: reserved-namespace? ( name -- ? )
+    [ "$cmd" = ] [ "system" head? ] bi or ;
+
+: check-collection ( collection -- fq-collection )
+    dup mdb-collection? [ name>> ] when
+    "." split1 over mdb-instance name>> =
+    [ nip ] [ drop ] if
+    [ ] [ reserved-namespace? ] bi
+    [ [ (ensure-collection) ] keep ] unless
+    [ mdb-instance name>> ] dip "%s.%s" sprintf ; 
+
+: fix-query-collection ( mdb-query -- mdb-query )
+    [ check-collection ] change-collection ; inline
+
+GENERIC: get-more ( mdb-cursor -- mdb-cursor seq )
+
+M: mdb-cursor get-more 
+    [ [ query>> dup [ collection>> ] [ return#>> ] bi ]
+      [ id>> ] bi <mdb-getmore-msg> swap >>query send-query ] 
+    [ f f ] if* ;
+
+PRIVATE>
+
+: <query> ( collection assoc -- mdb-query-msg )
+    <mdb-query-msg> ; inline
+
+GENERIC# limit 1 ( mdb-query-msg limit# -- mdb-query-msg )
+
+M: mdb-query-msg limit 
+    >>return# ; inline
+
+GENERIC# skip 1 ( mdb-query-msg skip# -- mdb-query-msg )
+
+M: mdb-query-msg skip 
+    >>skip# ; inline
+
+: asc ( key -- spec ) 1 2array ; inline
+: desc ( key -- spec ) -1 2array ; inline
+
+GENERIC# sort 1 ( mdb-query-msg sort-quot -- mdb-query-msg )
+
+M: mdb-query-msg sort
+    output>array >>orderby ; inline
+
+: key-spec ( spec-quot -- spec-assoc )
+    output>array >hashtable ; inline
+
+GENERIC# hint 1 ( mdb-query-msg index-hint -- mdb-query-msg )
+
+M: mdb-query-msg hint 
+    >>hint ;
+
+GENERIC: find ( selector -- mdb-cursor/f seq )
+
+M: mdb-query-msg find
+    fix-query-collection send-query ;
+
+M: mdb-cursor find
+    get-more ;
+
+GENERIC: explain. ( mdb-query-msg -- )
+
+M: mdb-query-msg explain.
+    t >>explain find nip . ;
+
+GENERIC: find-one ( mdb-query-msg -- result/f )
+
+M: mdb-query-msg find-one
+    fix-query-collection 
+    1 >>return# send-query-plain objects>>
+    dup empty? [ drop f ] [ first ] if ;
+
+GENERIC: count ( mdb-query-msg -- result )
+
+M: mdb-query-msg count    
+    [ collection>> "count" H{ } clone [ set-at ] keep ] keep
+    query>> [ over [ "query" ] dip set-at ] when*
+    [ cmd-collection ] dip <mdb-query-msg> find-one 
+    [ check-ok nip ] keep '[ "n" _ at >fixnum ] [ f ] if ;
+
+: lasterror ( -- error )
+    cmd-collection H{ { "getlasterror" 1 } } <mdb-query-msg>
+    find-one [ "err" ] dip at ;
+
+GENERIC: validate. ( collection -- )
+
+M: string validate.
+    [ cmd-collection ] dip
+    "validate" H{ } clone [ set-at ] keep
+    <mdb-query-msg> find-one [ check-ok nip ] keep
+    '[ "result" _ at print ] [  ] if ;
+
+M: mdb-collection validate.
+    name>> validate. ;
+
+<PRIVATE
+
+: send-message-check-error ( message -- )
+    send-message lasterror [ mdb-error ] when* ;
+
+PRIVATE>
+
+GENERIC: save ( collection assoc -- )
+M: assoc save
+    [ check-collection ] dip
+    <mdb-insert-msg> send-message-check-error ;
+
+GENERIC: save-unsafe ( collection assoc -- )
+M: assoc save-unsafe
+    [ check-collection ] dip
+    <mdb-insert-msg> send-message ;
+
+GENERIC: ensure-index ( index-spec -- )
+M: index-spec ensure-index
+    <linked-hash> [ [ uuid1 "_id" ] dip set-at ] keep
+    [ { [ [ name>> "name" ] dip set-at ]
+        [ [ ns>> index-ns "ns" ] dip set-at ]
+        [ [ key>> "key" ] dip set-at ]
+        [ swap unique?>>
+          [ swap [ "unique" ] dip set-at ] [ drop ] if* ] } 2cleave
+    ] keep
+    [ index-collection ] dip save ;
+
+: drop-index ( collection name -- )
+    H{ } clone
+    [ [ "index" ] dip set-at ] keep
+    [ [ "deleteIndexes" ] dip set-at ] keep
+    [ cmd-collection ] dip <mdb-query-msg>
+    find-one drop ;
+
+: <update> ( collection selector object -- mdb-update-msg )
+    [ check-collection ] 2dip <mdb-update-msg> ;
+
+: >upsert ( mdb-update-msg -- mdb-update-msg )
+    1 >>upsert? ; 
+
+GENERIC: update ( mdb-update-msg -- )
+M: mdb-update-msg update
+    send-message-check-error ;
+
+GENERIC: update-unsafe ( mdb-update-msg -- )
+M: mdb-update-msg update-unsafe
+    send-message ;
+GENERIC: delete ( collection selector -- )
+M: assoc delete
+    [ check-collection ] dip
+    <mdb-delete-msg> send-message-check-error ;
+
+GENERIC: delete-unsafe ( collection selector -- )
+M: assoc delete-unsafe
+    [ check-collection ] dip
+    <mdb-delete-msg> send-message ;
+
+: load-index-list ( -- index-list )
+    index-collection
+    H{ } clone <mdb-query-msg> find nip ;
+
+: ensure-collection ( name -- )
+    check-collection drop ;
+
+: drop-collection ( name -- )
+    [ cmd-collection ] dip
+    "drop" H{ } clone [ set-at ] keep
+    <mdb-query-msg> find-one drop ;
+
+
diff --git a/extra/mongodb/driver/summary.txt b/extra/mongodb/driver/summary.txt
new file mode 100644 (file)
index 0000000..2ac1f95
--- /dev/null
@@ -0,0 +1 @@
+A driver for the MongoDB document-oriented database (http://www.mongodb.org)
diff --git a/extra/mongodb/driver/tags.txt b/extra/mongodb/driver/tags.txt
new file mode 100644 (file)
index 0000000..aa0d57e
--- /dev/null
@@ -0,0 +1 @@
+database
diff --git a/extra/mongodb/mmm/authors.txt b/extra/mongodb/mmm/authors.txt
new file mode 100644 (file)
index 0000000..5df962b
--- /dev/null
@@ -0,0 +1 @@
+Sascha Matzke
diff --git a/extra/mongodb/mmm/mmm.factor b/extra/mongodb/mmm/mmm.factor
new file mode 100644 (file)
index 0000000..25c4c88
--- /dev/null
@@ -0,0 +1,102 @@
+USING: accessors fry io io.encodings.binary io.servers.connection
+io.sockets io.streams.byte-array kernel math mongodb.msg classes formatting
+namespaces prettyprint tools.walker calendar calendar.format bson.writer.private
+json.writer mongodb.operations.private mongodb.operations ;
+
+IN: mongodb.mmm
+
+SYMBOLS: mmm-port mmm-server-ip mmm-server-port mmm-server mmm-dump-output mmm-t-srv ; 
+
+GENERIC: dump-message ( message -- )
+
+: check-options ( -- )
+    mmm-port get [ 27040 mmm-port set ] unless
+    mmm-server-ip get [ "127.0.0.1" mmm-server-ip set ] unless
+    mmm-server-port get [ 27017 mmm-server-port set ] unless
+    mmm-server-ip get mmm-server-port get <inet> mmm-server set ;
+
+: read-msg-binary ( -- )
+    read-int32
+    [ write-int32 ] keep
+    4 - read write ;
+    
+: read-request-header ( -- msg-stub )
+    mdb-msg new
+    read-int32 MSG-HEADER-SIZE - >>length
+    read-int32 >>req-id
+    read-int32 >>resp-id
+    read-int32 >>opcode ;
+    
+: read-request ( -- msg-stub binary )
+    binary [ read-msg-binary ] with-byte-writer    
+    [ binary [ read-request-header ] with-byte-reader ] keep ; ! msg-stub binary
+
+: dump-request ( msg-stub binary -- )
+    [ mmm-dump-output get ] 2dip
+    '[ _ drop _ binary [ read-message dump-message ] with-byte-reader ] with-output-stream ;
+
+: read-reply ( -- binary )
+    binary [ read-msg-binary ] with-byte-writer ;
+
+: forward-request-read-reply ( msg-stub binary -- binary )
+    [ mmm-server get binary ] 2dip
+    '[ _ opcode>> _ write flush
+       OP_Query =
+       [ read-reply ]
+       [ f ] if ] with-client ; 
+
+: dump-reply ( binary -- )
+    [ mmm-dump-output get ] dip
+    '[ _ binary [ read-message dump-message ] with-byte-reader ] with-output-stream ;
+
+: message-prefix ( message -- prefix message )
+    [ now timestamp>http-string ] dip
+    [ class name>> ] keep
+    [ "%s: %s" sprintf ] dip ; inline
+
+M: mdb-query-msg dump-message ( message -- )
+    message-prefix
+    [ collection>> ] keep
+    query>> >json
+    "%s -> %s: %s \n" printf ;
+
+M: mdb-insert-msg dump-message ( message -- )
+    message-prefix
+    [ collection>> ] keep
+    objects>> >json
+    "%s -> %s : %s \n" printf ;
+
+M: mdb-reply-msg dump-message ( message -- )
+    message-prefix
+    [ cursor>> ] keep
+    [ start#>> ] keep
+    [ returned#>> ] keep
+    objects>> >json
+    "%s -> cursor: %d, start: %d, returned#: %d,  -> %s \n" printf ; 
+
+M: mdb-msg dump-message ( message -- )
+    message-prefix drop "%s \n" printf ;
+
+: forward-reply ( binary -- )
+    write flush ;
+
+: handle-mmm-connection ( -- )
+    read-request
+    [ dump-request ] 2keep
+    forward-request-read-reply
+    [ dump-reply ] keep 
+    forward-reply ; 
+
+: start-mmm-server ( -- )
+    output-stream get mmm-dump-output set
+    <threaded-server> [ mmm-t-srv set ] keep 
+    "127.0.0.1" mmm-port get <inet4> >>insecure
+    binary >>encoding
+    [ handle-mmm-connection ] >>handler
+    start-server* ;
+
+: run-mmm ( -- )
+    check-options
+    start-mmm-server ;
+    
+MAIN: run-mmm
\ No newline at end of file
diff --git a/extra/mongodb/mmm/summary.txt b/extra/mongodb/mmm/summary.txt
new file mode 100644 (file)
index 0000000..0670873
--- /dev/null
@@ -0,0 +1 @@
+mongo-message-monitor - a small proxy to introspect messages send to MongoDB
diff --git a/extra/mongodb/mongodb-docs.factor b/extra/mongodb/mongodb-docs.factor
new file mode 100644 (file)
index 0000000..ff8a769
--- /dev/null
@@ -0,0 +1,27 @@
+USING: assocs help.markup help.syntax kernel quotations ;
+IN: mongodb
+
+ARTICLE: "mongodb" "MongoDB factor integration"
+"The " { $vocab-link "mongodb" } " vocabulary provides two different interfaces to the MongoDB document-oriented database"
+{ $heading "Low-level driver" }
+"The " { $vocab-link "mongodb.driver" } " vocabulary provides a low-level interface to MongoDB."
+{ $unchecked-example
+  "USING: mongodb.driver ;"
+  "\"db\" \"127.0.0.1\" 27017 <mdb>"
+  "[ \"mycollection\" [ H{ { \"name\" \"Alfred\" } { \"age\" 57 } } save ] "
+  "                 [ ageIdx [ \"age\" asc ] key-spec <index-spec> ensure-index ]"
+  "                 [ H{ { \"age\" H{ { \"$gt\" 50 } } } } <query> find-one ] tri ] with-db "
+  "" }
+{ $heading "Highlevel tuple integration" }
+"The " { $vocab-link "mongodb.tuple" } " vocabulary lets you define persistent tuples that can be stored to and retrieved from a MongoDB database"
+{ $unchecked-example
+  "USING: mongodb.driver mongodb.tuple fry ;"
+  "MDBTUPLE: person name age ; "
+  "person \"persons\" { { \"age\" +fieldindex+ } } define-persistent "
+  "\"db\" \"127.0.0.1\" 27017 <mdb>"
+  "person new \"Alfred\" >>name 57 >>age"
+  "'[ _ save-tuple person new 57 >>age select-tuple ] with-db"
+  "" }
+;
+
+ABOUT: "mongodb"
\ No newline at end of file
diff --git a/extra/mongodb/mongodb.factor b/extra/mongodb/mongodb.factor
new file mode 100644 (file)
index 0000000..c5417cc
--- /dev/null
@@ -0,0 +1,8 @@
+USING: vocabs.loader ;
+
+IN: mongodb
+
+"mongodb.connection" require
+"mongodb.driver" require
+"mongodb.tuple" require
+
diff --git a/extra/mongodb/msg/authors.txt b/extra/mongodb/msg/authors.txt
new file mode 100644 (file)
index 0000000..5df962b
--- /dev/null
@@ -0,0 +1 @@
+Sascha Matzke
diff --git a/extra/mongodb/msg/msg.factor b/extra/mongodb/msg/msg.factor
new file mode 100644 (file)
index 0000000..dd8bae8
--- /dev/null
@@ -0,0 +1,105 @@
+USING: accessors assocs hashtables constructors kernel linked-assocs math
+sequences strings ;
+
+IN: mongodb.msg
+
+CONSTANT: OP_Reply   1 
+CONSTANT: OP_Message 1000 
+CONSTANT: OP_Update  2001 
+CONSTANT: OP_Insert  2002 
+CONSTANT: OP_Query   2004 
+CONSTANT: OP_GetMore 2005 
+CONSTANT: OP_Delete  2006 
+CONSTANT: OP_KillCursors 2007
+
+CONSTANT: ResultFlag_CursorNotFound  1 ! /* returned, with zero results, when getMore is called but the cursor id is not valid at the server. */
+CONSTANT: ResultFlag_ErrSet  2 ! /* { $err : ... } is being returned */
+CONSTANT: ResultFlag_ShardConfigStale 4 !  /* have to update config from the server,  usually $err is also set */
+            
+TUPLE: mdb-msg
+{ opcode integer } 
+{ req-id integer initial: 0 }
+{ resp-id integer initial: 0 }
+{ length integer initial: 0 }     
+{ flags integer initial: 0 } ;
+
+TUPLE: mdb-query-msg < mdb-msg
+{ collection string }
+{ skip# integer initial: 0 }
+{ return# integer initial: 0 }
+{ query assoc }
+{ returnfields assoc }
+{ orderby sequence }
+explain hint ;
+
+TUPLE: mdb-insert-msg < mdb-msg
+{ collection string }
+{ objects sequence } ;
+
+TUPLE: mdb-update-msg < mdb-msg
+{ collection string }
+{ upsert? integer initial: 0 }
+{ selector assoc }
+{ object assoc } ;
+
+TUPLE: mdb-delete-msg < mdb-msg
+{ collection string }
+{ selector assoc } ;
+
+TUPLE: mdb-getmore-msg < mdb-msg
+{ collection string }
+{ return# integer initial: 0 }
+{ cursor integer initial: 0 }
+{ query mdb-query-msg } ;
+
+TUPLE: mdb-killcursors-msg < mdb-msg
+{ cursors# integer initial: 0 }
+{ cursors sequence } ;
+
+TUPLE: mdb-reply-msg < mdb-msg
+{ collection string }
+{ cursor integer initial: 0 }
+{ start# integer initial: 0 }
+{ requested# integer initial: 0 }
+{ returned# integer initial: 0 }
+{ objects sequence } ;
+
+
+CONSTRUCTOR: mdb-getmore-msg ( collection return# cursor -- mdb-getmore-msg )
+    OP_GetMore >>opcode ; inline
+
+CONSTRUCTOR: mdb-delete-msg ( collection selector -- mdb-delete-msg )
+    OP_Delete >>opcode ; inline
+
+CONSTRUCTOR: mdb-query-msg ( collection query -- mdb-query-msg )
+    OP_Query >>opcode ; inline
+
+GENERIC: <mdb-killcursors-msg> ( object -- mdb-killcursors-msg )
+
+M: sequence <mdb-killcursors-msg> ( sequences -- mdb-killcursors-msg )
+    [ mdb-killcursors-msg new ] dip
+    [ length >>cursors# ] keep
+    >>cursors OP_KillCursors >>opcode ; inline
+
+M: integer <mdb-killcursors-msg> ( integer -- mdb-killcursors-msg )
+    V{ } clone [ push ] keep <mdb-killcursors-msg> ;
+
+GENERIC: <mdb-insert-msg> ( collection objects -- mdb-insert-msg )
+
+M: sequence <mdb-insert-msg> ( collection sequence -- mdb-insert-msg )
+    [ mdb-insert-msg new ] 2dip
+    [ >>collection ] dip
+    >>objects OP_Insert >>opcode ;
+
+M: assoc <mdb-insert-msg> ( collection assoc -- mdb-insert-msg )
+    [ mdb-insert-msg new ] 2dip
+    [ >>collection ] dip
+    V{ } clone tuck push
+    >>objects OP_Insert >>opcode ;
+
+
+CONSTRUCTOR: mdb-update-msg ( collection selector object -- mdb-update-msg )
+    OP_Update >>opcode ; inline
+    
+CONSTRUCTOR: mdb-reply-msg ( -- mdb-reply-msg ) ; inline
+
diff --git a/extra/mongodb/msg/summary.txt b/extra/mongodb/msg/summary.txt
new file mode 100644 (file)
index 0000000..daff8c2
--- /dev/null
@@ -0,0 +1 @@
+message primitives for the communication with MongoDB
diff --git a/extra/mongodb/operations/authors.txt b/extra/mongodb/operations/authors.txt
new file mode 100644 (file)
index 0000000..5df962b
--- /dev/null
@@ -0,0 +1 @@
+Sascha Matzke
diff --git a/extra/mongodb/operations/operations.factor b/extra/mongodb/operations/operations.factor
new file mode 100644 (file)
index 0000000..001e844
--- /dev/null
@@ -0,0 +1,222 @@
+USING: accessors assocs bson.reader bson.writer byte-arrays
+byte-vectors combinators formatting fry io io.binary io.encodings.private
+io.encodings.binary io.encodings.string io.encodings.utf8 io.encodings.utf8.private io.files
+kernel locals math mongodb.msg namespaces sequences uuid bson.writer.private ;
+
+IN: alien.c-types
+
+M: byte-vector byte-length length ;
+
+IN: mongodb.operations
+
+<PRIVATE
+
+PREDICATE: mdb-reply-op < integer OP_Reply = ;
+PREDICATE: mdb-query-op < integer OP_Query = ;
+PREDICATE: mdb-insert-op < integer OP_Insert = ;
+PREDICATE: mdb-update-op < integer OP_Update = ;
+PREDICATE: mdb-delete-op < integer OP_Delete = ;
+PREDICATE: mdb-getmore-op < integer OP_GetMore = ;
+PREDICATE: mdb-killcursors-op < integer OP_KillCursors = ;
+
+PRIVATE>
+
+GENERIC: write-message ( message -- )
+
+<PRIVATE
+
+CONSTANT: MSG-HEADER-SIZE 16
+
+SYMBOL: msg-bytes-read 
+
+: bytes-read> ( -- integer )
+    msg-bytes-read get ; inline
+
+: >bytes-read ( integer -- )
+    msg-bytes-read set ; inline
+
+: change-bytes-read ( integer -- )
+    bytes-read> [ 0 ] unless* + >bytes-read ; inline
+
+: read-int32 ( -- int32 ) 4 [ read le> ] [ change-bytes-read ] bi ; inline
+: read-longlong ( -- longlong ) 8 [ read le> ] [ change-bytes-read ] bi ; inline
+: read-byte-raw ( -- byte-raw ) 1 [ read le> ] [ change-bytes-read ] bi ; inline
+: read-byte ( -- byte ) read-byte-raw first ; inline
+
+: (read-cstring) ( acc -- )
+    [ read-byte ] dip ! b acc
+    2dup push             ! b acc
+    [ 0 = ] dip      ! bool acc
+    '[ _ (read-cstring) ] unless ; inline recursive
+
+: read-cstring ( -- string )
+    BV{ } clone
+    [ (read-cstring) ] keep
+    [ zero? ] trim-tail
+    >byte-array utf8 decode ; inline
+
+GENERIC: (read-message) ( message opcode -- message )
+
+: copy-header ( message msg-stub -- message )
+    [ length>> ] keep [ >>length ] dip
+    [ req-id>> ] keep [ >>req-id ] dip
+    [ resp-id>> ] keep [ >>resp-id ] dip
+    [ opcode>> ] keep [ >>opcode ] dip
+    flags>> >>flags ;
+
+M: mdb-query-op (read-message) ( msg-stub opcode -- message )
+    drop
+    [ mdb-query-msg new ] dip copy-header
+    read-cstring >>collection
+    read-int32 >>skip#
+    read-int32 >>return#
+    H{ } stream>assoc change-bytes-read >>query 
+    dup length>> bytes-read> >
+    [ H{ } stream>assoc change-bytes-read >>returnfields ] when ;
+
+M: mdb-insert-op (read-message) ( msg-stub opcode -- message )
+    drop
+    [ mdb-insert-msg new ] dip copy-header
+    read-cstring >>collection
+    V{ } clone >>objects
+    [ '[ _ length>> bytes-read> > ] ] keep tuck
+    '[ H{ } stream>assoc change-bytes-read _ objects>> push ]
+    while ;
+
+M: mdb-delete-op (read-message) ( msg-stub opcode -- message )
+    drop
+    [ mdb-delete-msg new ] dip copy-header
+    read-cstring >>collection
+    H{ } stream>assoc change-bytes-read >>selector ;
+
+M: mdb-getmore-op (read-message) ( msg-stub opcode -- message )
+    drop
+    [ mdb-getmore-msg new ] dip copy-header
+    read-cstring >>collection
+    read-int32 >>return#
+    read-longlong >>cursor ;
+
+M: mdb-killcursors-op (read-message) ( msg-stub opcode -- message )
+    drop
+    [ mdb-killcursors-msg new ] dip copy-header
+    read-int32 >>cursors#
+    V{ } clone >>cursors
+    [ [ cursors#>> ] keep 
+      '[ read-longlong _ cursors>> push ] times ] keep ;
+
+M: mdb-update-op (read-message) ( msg-stub opcode -- message )
+    drop
+    [ mdb-update-msg new ] dip copy-header
+    read-cstring >>collection
+    read-int32 >>upsert?
+    H{ } stream>assoc change-bytes-read >>selector
+    H{ } stream>assoc change-bytes-read >>object ;
+
+M: mdb-reply-op (read-message) ( msg-stub opcode -- message )
+    drop
+    [ <mdb-reply-msg> ] dip copy-header
+    read-longlong >>cursor
+    read-int32 >>start#
+    read-int32 [ >>returned# ] keep
+    [ H{ } stream>assoc drop ] accumulator [ times ] dip >>objects ;    
+
+: read-header ( message -- message )
+    read-int32 >>length
+    read-int32 >>req-id
+    read-int32 >>resp-id
+    read-int32 >>opcode
+    read-int32 >>flags ; inline
+
+: write-header ( message -- )
+    [ req-id>> write-int32 ] keep
+    [ resp-id>> write-int32 ] keep 
+    opcode>> write-int32 ; inline
+
+PRIVATE>
+
+: read-message ( -- message )
+    mdb-msg new
+    0 >bytes-read
+    read-header
+    [ ] [ opcode>> ] bi (read-message) ;
+
+<PRIVATE
+
+USE: tools.walker
+
+: dump-to-file ( array -- )
+    [ uuid1 "/tmp/mfb/%s.dump" sprintf binary ] dip
+    '[ _ write ] with-file-writer ;
+
+: (write-message) ( message quot -- )    
+    '[ [ [ _ write-header ] dip _ call ] with-length-prefix ] with-buffer
+    ! [ dump-to-file ] keep
+    write flush ; inline
+
+: build-query-object ( query -- selector )
+    [let | selector [ H{ } clone ] |
+        { [ orderby>> [ "orderby" selector set-at ] when* ]
+          [ explain>> [ "$explain" selector set-at ] when* ]
+          [ hint>> [ "$hint" selector set-at ] when* ] 
+          [ query>> "query" selector set-at ]
+        } cleave
+        selector
+    ] ;     
+
+PRIVATE>
+
+M: mdb-query-msg write-message ( message -- )
+     dup
+     '[ _ 
+        [ flags>> write-int32 ] keep 
+        [ collection>> write-cstring ] keep
+        [ skip#>> write-int32 ] keep
+        [ return#>> write-int32 ] keep
+        [ build-query-object assoc>stream ] keep
+        returnfields>> [ assoc>stream ] when* 
+     ] (write-message) ;
+M: mdb-insert-msg write-message ( message -- )
+    dup
+    '[ _
+       [ flags>> write-int32 ] keep
+       [ collection>> write-cstring ] keep
+       objects>> [ assoc>stream ] each
+    ] (write-message) ;
+
+M: mdb-update-msg write-message ( message -- )
+    dup
+    '[ _
+       [ flags>> write-int32 ] keep
+       [ collection>> write-cstring ] keep
+       [ upsert?>> write-int32 ] keep
+       [ selector>> assoc>stream ] keep
+       object>> assoc>stream
+    ] (write-message) ;
+
+M: mdb-delete-msg write-message ( message -- )
+    dup
+    '[ _
+       [ flags>> write-int32 ] keep
+       [ collection>> write-cstring ] keep
+       0 write-int32
+       selector>> assoc>stream
+    ] (write-message) ;
+
+M: mdb-getmore-msg write-message ( message -- )
+    dup
+    '[ _
+       [ flags>> write-int32 ] keep
+       [ collection>> write-cstring ] keep
+       [ return#>> write-int32 ] keep
+       cursor>> write-longlong
+    ] (write-message) ;
+
+M: mdb-killcursors-msg write-message ( message -- )
+    dup
+    '[ _
+       [ flags>> write-int32 ] keep
+       [ cursors#>> write-int32 ] keep
+       cursors>> [ write-longlong ] each
+    ] (write-message) ;
+
diff --git a/extra/mongodb/operations/summary.txt b/extra/mongodb/operations/summary.txt
new file mode 100644 (file)
index 0000000..ab9f94e
--- /dev/null
@@ -0,0 +1 @@
+low-level message reading and writing
diff --git a/extra/mongodb/summary.txt b/extra/mongodb/summary.txt
new file mode 100644 (file)
index 0000000..87c5b2d
--- /dev/null
@@ -0,0 +1 @@
+MongoDB Factor integration
diff --git a/extra/mongodb/tags.txt b/extra/mongodb/tags.txt
new file mode 100644 (file)
index 0000000..aa0d57e
--- /dev/null
@@ -0,0 +1 @@
+database
diff --git a/extra/mongodb/tuple/authors.txt b/extra/mongodb/tuple/authors.txt
new file mode 100644 (file)
index 0000000..5df962b
--- /dev/null
@@ -0,0 +1 @@
+Sascha Matzke
diff --git a/extra/mongodb/tuple/collection/authors.txt b/extra/mongodb/tuple/collection/authors.txt
new file mode 100644 (file)
index 0000000..5df962b
--- /dev/null
@@ -0,0 +1 @@
+Sascha Matzke
diff --git a/extra/mongodb/tuple/collection/collection.factor b/extra/mongodb/tuple/collection/collection.factor
new file mode 100644 (file)
index 0000000..a4f86cd
--- /dev/null
@@ -0,0 +1,117 @@
+
+USING: accessors arrays assocs bson.constants classes classes.tuple
+combinators continuations fry kernel mongodb.driver sequences strings
+vectors words combinators.smart literals ;
+
+IN: mongodb.tuple
+
+SINGLETONS: +transient+ +load+ ;
+
+IN: mongodb.tuple.collection
+
+FROM: mongodb.tuple => +transient+ +load+ ;
+
+MIXIN: mdb-persistent
+
+SLOT: _id
+SLOT: _mfd
+
+TUPLE: mdb-tuple-collection < mdb-collection { classes } ;
+
+GENERIC: tuple-collection ( object -- mdb-collection )
+
+GENERIC: mdb-slot-map  ( tuple -- string )
+
+<PRIVATE
+
+CONSTANT: MDB_COLLECTION     "_mdb_col"
+CONSTANT: MDB_SLOTDEF_LIST   "_mdb_slot_list"
+CONSTANT: MDB_COLLECTION_MAP "_mdb_col_map"
+
+: (mdb-collection) ( class -- mdb-collection )     
+    dup MDB_COLLECTION word-prop
+    [ nip ]
+    [ superclass [ (mdb-collection) ] [ f ] if* ] if* ; inline recursive
+
+: (mdb-slot-map) ( class -- slot-defs )
+    superclasses [ MDB_SLOTDEF_LIST word-prop ] map assoc-combine  ; inline 
+
+: split-optl ( seq -- key options )
+    [ first ] [ rest ] bi ; inline
+
+: opt>assoc ( seq -- assoc )
+    [ dup assoc?
+      [ 1array { "" } append ] unless ] map ;
+
+: optl>map ( seq -- map )
+    H{ } clone tuck
+    '[ split-optl opt>assoc swap _ set-at ] each ; inline
+
+PRIVATE>
+
+: MDB_ADDON_SLOTS ( -- slots )
+   { $[ MDB_OID_FIELD MDB_META_FIELD ] } ; inline
+
+: link-class ( collection class -- )
+    over classes>>
+    [ 2dup member? [ 2drop ] [ push ] if ]
+    [ 1vector >>classes ] if* drop ; inline
+
+: link-collection ( class collection -- )
+    [ swap link-class ]
+    [ MDB_COLLECTION set-word-prop ] 2bi ; inline
+
+: mdb-check-slots ( superclass slots -- superclass slots )
+    over all-slots [ name>> ] map [ MDB_OID_FIELD ] dip member?
+    [  ] [ MDB_ADDON_SLOTS prepend ] if ; inline
+
+: set-slot-map ( class options -- )
+    optl>map MDB_SLOTDEF_LIST set-word-prop ; inline
+  
+M: tuple-class tuple-collection ( tuple -- mdb-collection )
+    (mdb-collection) ;
+M: mdb-persistent tuple-collection ( tuple -- mdb-collection )
+    class (mdb-collection) ;
+M: mdb-persistent mdb-slot-map ( tuple -- string )
+    class (mdb-slot-map) ;
+
+M: tuple-class mdb-slot-map ( class -- assoc )
+    (mdb-slot-map) ;
+
+M: mdb-collection mdb-slot-map ( collection -- assoc )
+    classes>> [ mdb-slot-map ] map assoc-combine ;
+
+<PRIVATE
+
+: collection-map ( -- assoc )
+    mdb-persistent MDB_COLLECTION_MAP word-prop
+    [ mdb-persistent MDB_COLLECTION_MAP H{ } clone
+      [ set-word-prop ] keep ] unless* ; inline
+
+: slot-option? ( tuple slot option -- ? )
+    [ swap mdb-slot-map at ] dip
+    '[ _ swap key? ] [ f ] if* ;
+  
+PRIVATE>
+
+GENERIC: <mdb-tuple-collection> ( name -- mdb-tuple-collection )
+M: string <mdb-tuple-collection> ( name -- mdb-tuple-collection )
+    collection-map [ ] [ key? ] 2bi 
+    [ at ] [ [ mdb-tuple-collection new dup ] 2dip 
+             [ [ >>name ] keep ] dip set-at ] if ; inline
+M: mdb-tuple-collection <mdb-tuple-collection> ( mdb-tuple-collection -- mdb-tuple-collection ) ;
+M: mdb-collection <mdb-tuple-collection> ( mdb-collection -- mdb-tuple-collection )
+    [ name>> <mdb-tuple-collection> ] keep
+    {
+        [ capped>> >>capped ]
+        [ size>> >>size ]
+        [ max>> >>max ]
+    } cleave ;
+
+: transient-slot? ( tuple slot -- ? )
+    +transient+ slot-option? ;
+
+: load-slot? ( tuple slot -- ? )
+    +load+ slot-option? ;
diff --git a/extra/mongodb/tuple/collection/summary.txt b/extra/mongodb/tuple/collection/summary.txt
new file mode 100644 (file)
index 0000000..e568b51
--- /dev/null
@@ -0,0 +1 @@
+tuple class MongoDB collection handling
diff --git a/extra/mongodb/tuple/index/authors.txt b/extra/mongodb/tuple/index/authors.txt
new file mode 100644 (file)
index 0000000..5df962b
--- /dev/null
@@ -0,0 +1 @@
+Sascha Matzke
diff --git a/extra/mongodb/tuple/index/index.factor b/extra/mongodb/tuple/index/index.factor
new file mode 100644 (file)
index 0000000..1e7a679
--- /dev/null
@@ -0,0 +1,56 @@
+USING: kernel fry accessors formatting linked-assocs assocs sequences sequences.deep
+mongodb.tuple.collection combinators mongodb.tuple.collection ; 
+
+IN: mongodb.tuple
+
+SINGLETONS: +fieldindex+ +compoundindex+ +deepindex+ ;
+
+IN: mongodb.tuple.index
+
+TUPLE: tuple-index name spec ;
+
+<PRIVATE
+
+: index-type ( type -- name )
+    { { +fieldindex+ [ "field" ] }
+      { +deepindex+ [ "deep" ] }
+      { +compoundindex+ [ "compound" ] } } case ;
+  
+: index-name ( slot index-spec -- name )
+    [ first index-type ] keep
+    rest "-" join
+    "%s-%s-%s-Idx" sprintf ;
+
+: build-index ( element slot -- assoc )
+    swap [ <linked-hash> ] 2dip
+    [ rest ] keep first ! assoc slot options itype
+    { { +fieldindex+ [ drop [ 1 ] dip pick set-at  ] }
+      { +deepindex+ [ first "%s.%s" sprintf [ 1 ] dip pick set-at ] }
+      { +compoundindex+ [
+          2over swap [ 1 ] 2dip set-at [ drop ] dip ! assoc options
+          over '[ _ [ 1 ] 2dip set-at ] each ] }
+    } case ;
+
+: build-index-seq ( slot optlist -- index-seq )
+    [ V{ } clone ] 2dip pick  ! v{} slot optl v{}      
+    [ swap ] dip  ! v{} optl slot v{ }
+    '[ _ tuple-index new ! element slot exemplar 
+       2over swap index-name >>name  ! element slot clone
+       [ build-index ] dip swap >>spec _ push
+    ] each ;
+
+: is-index-declaration? ( entry -- ? )
+    first
+    { { +fieldindex+ [ t ] }
+      { +compoundindex+ [ t ] }
+      { +deepindex+ [ t ] }
+      [ drop f ] } case ;
+
+PRIVATE>
+
+: tuple-index-list ( mdb-collection/class -- seq )
+    mdb-slot-map V{ } clone tuck
+    '[ [ is-index-declaration? ] filter
+       build-index-seq _ push 
+    ] assoc-each flatten ;
+
diff --git a/extra/mongodb/tuple/index/summary.txt b/extra/mongodb/tuple/index/summary.txt
new file mode 100644 (file)
index 0000000..e4a1549
--- /dev/null
@@ -0,0 +1 @@
+tuple class index handling
diff --git a/extra/mongodb/tuple/persistent/authors.txt b/extra/mongodb/tuple/persistent/authors.txt
new file mode 100644 (file)
index 0000000..5df962b
--- /dev/null
@@ -0,0 +1 @@
+Sascha Matzke
diff --git a/extra/mongodb/tuple/persistent/persistent.factor b/extra/mongodb/tuple/persistent/persistent.factor
new file mode 100644 (file)
index 0000000..061b27d
--- /dev/null
@@ -0,0 +1,115 @@
+USING: accessors assocs bson.constants combinators.short-circuit
+constructors continuations fry kernel mirrors mongodb.tuple.collection
+mongodb.tuple.state namespaces sequences words bson.writer combinators
+hashtables linked-assocs ;
+
+IN: mongodb.tuple.persistent
+
+SYMBOLS: object-map ;
+
+GENERIC: tuple>assoc ( tuple -- assoc )
+
+GENERIC: tuple>selector ( tuple -- selector )
+
+DEFER: assoc>tuple
+
+<PRIVATE
+
+: mdbinfo>tuple-class ( tuple-info -- class )
+   [ first ] keep second lookup ; inline
+
+: tuple-instance ( tuple-info -- instance )
+    mdbinfo>tuple-class new ; inline 
+
+: prepare-assoc>tuple ( assoc -- tuple keylist mirror assoc )
+   [ tuple-info tuple-instance dup
+     <mirror> [ keys ] keep ] keep swap ; inline
+
+: make-tuple ( assoc -- tuple )
+   prepare-assoc>tuple
+   '[ dup _ at assoc>tuple swap _ set-at ] each
+   [ mark-persistent ] keep ; inline recursive
+
+: at+ ( value key assoc -- value )
+    2dup key?
+    [ at nip ] [ [ dup ] 2dip set-at ] if ; inline
+
+: data-tuple? ( tuple -- ? )
+    dup tuple?
+    [ assoc? not ] [ drop f ] if  ; inline
+
+: add-storable ( assoc ns -- )
+   [ H{ } clone ] dip object-map get at+
+   [ dup [ MDB_OID_FIELD ] dip at ] dip set-at ; inline
+
+: write-field? ( tuple key value -- ? )
+   pick mdb-persistent? [ 
+      { [ [ 2drop ] dip not ]
+        [ drop transient-slot? ] } 3|| not ] [ 3drop t ] if ; inline
+
+TUPLE: cond-value value quot ;
+
+CONSTRUCTOR: cond-value ( value quot -- cond-value ) ;
+
+: write-mdb-persistent ( value quot: ( tuple -- assoc ) -- value' )
+   over [ (( tuple -- assoc )) call-effect ] dip 
+   [ tuple-collection name>> ] keep
+   [ add-storable ] dip
+   [ tuple-collection name>> ] [ _id>> ] bi <objref> ; inline
+
+: write-field ( value quot: ( tuple -- assoc ) -- value' )
+   <cond-value> {
+      { [ dup value>> mdb-special-value? ] [ value>> ]  }
+      { [ dup value>> mdb-persistent? ]
+        [ [ value>> ] [ quot>> ] bi write-mdb-persistent ] }
+      { [ dup value>> data-tuple? ]
+        [ [ value>> ] [ quot>> ] bi (( tuple -- assoc )) call-effect ]  }
+      { [ dup value>> [ hashtable? ] [ linked-assoc? ] bi or ]
+        [ [ value>> ] [ quot>> ] bi '[ _ write-field ] assoc-map ] }
+      [ value>> ]
+   } cond ; inline recursive
+
+: write-tuple-fields ( mirror tuple assoc quot: ( tuple -- assoc ) -- )
+   swap ! m t q q a 
+   '[ _ 2over write-field?
+      [ _ write-field swap _ set-at ]
+      [ 2drop ] if
+   ] assoc-each ; 
+
+: prepare-assoc ( tuple -- assoc mirror tuple assoc )
+   H{ } clone swap [ <mirror> ] keep pick ; inline
+
+: ensure-mdb-info ( tuple -- tuple )    
+   dup _id>> [ <objid> >>_id ] unless
+   [ mark-persistent ] keep ; inline
+
+: with-object-map ( quot: ( -- ) -- store-assoc )
+   [ H{ } clone dup object-map ] dip with-variable ; inline
+
+: (tuple>assoc) ( tuple -- assoc )
+   [ prepare-assoc [ tuple>assoc ] write-tuple-fields ] keep
+   over set-tuple-info ; inline
+
+PRIVATE>
+
+GENERIC: tuple>storable ( tuple -- storable )
+
+M: mdb-persistent tuple>storable ( mdb-persistent -- object-map )
+   '[ _ [ tuple>assoc ] write-mdb-persistent drop ] with-object-map ; inline
+
+M: mdb-persistent tuple>assoc ( tuple -- assoc )
+   ensure-mdb-info (tuple>assoc) ;
+
+M: tuple tuple>assoc ( tuple -- assoc )
+   (tuple>assoc) ;
+
+M: tuple tuple>selector ( tuple -- assoc )
+    prepare-assoc [ tuple>selector ] write-tuple-fields ;
+
+: assoc>tuple ( assoc -- tuple )
+    dup assoc?
+    [ [ dup tuple-info?
+        [ make-tuple ]
+        [ ] if ] [ drop ] recover
+    ] [ ] if ; inline recursive
+
diff --git a/extra/mongodb/tuple/persistent/summary.txt b/extra/mongodb/tuple/persistent/summary.txt
new file mode 100644 (file)
index 0000000..46f32e4
--- /dev/null
@@ -0,0 +1 @@
+tuple to MongoDB storable conversion (and back)
diff --git a/extra/mongodb/tuple/state/authors.txt b/extra/mongodb/tuple/state/authors.txt
new file mode 100644 (file)
index 0000000..5df962b
--- /dev/null
@@ -0,0 +1 @@
+Sascha Matzke
diff --git a/extra/mongodb/tuple/state/state.factor b/extra/mongodb/tuple/state/state.factor
new file mode 100644 (file)
index 0000000..2192363
--- /dev/null
@@ -0,0 +1,52 @@
+USING: classes kernel accessors sequences fry assocs mongodb.tuple.collection
+words classes.tuple slots generic ;
+
+IN: mongodb.tuple.state
+
+<PRIVATE
+
+CONSTANT: MDB_TUPLE_INFO       "_mfd_t_info"
+CONSTANT: MDB_DIRTY_FLAG       "d?"
+CONSTANT: MDB_PERSISTENT_FLAG  "p?"
+CONSTANT: MDB_DIRTY_ADVICE     "mdb-dirty-set"
+
+PRIVATE>
+
+SYMBOL: mdb-dirty-handling?
+
+: advised-with? ( name word loc -- ? )
+   word-prop key? ; inline
+
+: <tuple-info> ( tuple -- tuple-info )
+    class V{ } clone tuck  
+    [ [ name>> ] dip push ]
+    [ [ vocabulary>> ] dip push ] 2bi ; inline
+
+: tuple-info ( assoc -- tuple-info )
+    [ MDB_TUPLE_INFO ] dip at ; inline
+
+: set-tuple-info ( tuple assoc -- )
+   [ <tuple-info> MDB_TUPLE_INFO ] dip set-at ; inline
+
+: tuple-info? ( assoc -- ? )
+   [ MDB_TUPLE_INFO ] dip key? ;
+
+: tuple-meta ( tuple -- assoc )
+   dup _mfd>> [ ] [ H{ } clone [ >>_mfd ] keep ] if* nip ; inline
+
+: dirty? ( tuple -- ? )
+   [ MDB_DIRTY_FLAG ] dip tuple-meta at ;
+
+: mark-dirty ( tuple -- )
+   [ t MDB_DIRTY_FLAG ] dip tuple-meta set-at ;
+
+: persistent? ( tuple -- ? )
+   [ MDB_PERSISTENT_FLAG ] dip tuple-meta at ;
+
+: mark-persistent ( tuple -- )
+   [ t MDB_PERSISTENT_FLAG ] dip tuple-meta [ set-at ] keep
+   [ f MDB_DIRTY_FLAG ] dip set-at ;
+
+: needs-store? ( tuple -- ? )
+   [ persistent? not ] [ dirty? ] bi or ;
+
diff --git a/extra/mongodb/tuple/state/summary.txt b/extra/mongodb/tuple/state/summary.txt
new file mode 100644 (file)
index 0000000..f879133
--- /dev/null
@@ -0,0 +1 @@
+client-side persistent tuple state handling
diff --git a/extra/mongodb/tuple/summary.txt b/extra/mongodb/tuple/summary.txt
new file mode 100644 (file)
index 0000000..6c79de2
--- /dev/null
@@ -0,0 +1 @@
+persist tuple instances into MongoDB
diff --git a/extra/mongodb/tuple/tuple.factor b/extra/mongodb/tuple/tuple.factor
new file mode 100644 (file)
index 0000000..19281b7
--- /dev/null
@@ -0,0 +1,82 @@
+USING: accessors assocs classes.mixin classes.tuple
+classes.tuple.parser compiler.units fry kernel sequences mongodb.driver
+mongodb.msg mongodb.tuple.collection mongodb.tuple.index
+mongodb.tuple.persistent mongodb.tuple.state strings ;
+
+IN: mongodb.tuple
+
+SYNTAX: MDBTUPLE:
+    parse-tuple-definition
+    mdb-check-slots
+    define-tuple-class ; 
+
+: define-persistent ( class collection options -- )
+    [ [ <mdb-tuple-collection> dupd link-collection ] when* ] dip 
+    [ dup '[ _ mdb-persistent add-mixin-instance ] with-compilation-unit ] dip
+    ! [ dup annotate-writers ] dip 
+    set-slot-map ;
+
+: ensure-table ( class -- )
+    tuple-collection
+    [ create-collection ]
+    [ [ tuple-index-list ] keep
+      '[ _ name>> swap [ name>> ] [ spec>> ] bi <index-spec> ensure-index ] each
+    ] bi ;
+
+: ensure-tables ( classes -- )
+    [ ensure-table ] each ; 
+
+: drop-table ( class -- )
+      tuple-collection
+      [ [ tuple-index-list ] keep
+        '[ _ name>> swap name>> drop-index ] each ]
+      [ name>> drop-collection ] bi ;
+
+: recreate-table ( class -- )
+    [ drop-table ] 
+    [ ensure-table ] bi ;
+
+<PRIVATE
+
+GENERIC: id-selector ( object -- selector )
+
+M: string id-selector ( objid -- selector )
+   "_id" H{ } clone [ set-at ] keep ; inline
+
+M: mdb-persistent id-selector ( mdb-persistent -- selector )
+   _id>> id-selector ;
+
+: (save-tuples) ( collection assoc -- )
+   swap '[ [ _ ] 2dip
+           [ id-selector ] dip
+           <update> >upsert update ] assoc-each ; inline
+PRIVATE>
+: save-tuple ( tuple -- )
+   tuple>storable [ (save-tuples) ] assoc-each ;
+: update-tuple ( tuple -- )
+   save-tuple ;
+
+: insert-tuple ( tuple -- )
+   save-tuple ;
+
+: delete-tuple ( tuple -- )
+   dup persistent?
+   [ [ tuple-collection name>> ] keep
+     id-selector delete ] [ drop ] if ;
+
+: tuple>query ( tuple -- query )
+   [ tuple-collection name>> ] keep
+   tuple>selector <query> ;
+
+: select-tuple ( tuple/query -- tuple/f )
+   dup mdb-query-msg? [ tuple>query ] unless
+   find-one [ assoc>tuple ] [ f ] if* ;
+
+: select-tuples ( tuple/query -- cursor tuples/f )
+   dup mdb-query-msg? [ tuple>query ] unless
+   find [ assoc>tuple ] map ;
+
+: count-tuples ( tuple/query -- n )
+   dup mdb-query-msg? [ tuple>query ] unless count ;
index 20989f2f2f45e4480a081d4bf7de334e5d2e1805..ddfd3c20424c98c5923d9c88db67a2bd63f68fcf 100644 (file)
@@ -3,7 +3,7 @@
 USING: accessors ascii assocs biassocs combinators hashtables kernel lists literals math namespaces make multiline openal parser sequences splitting strings synth synth.buffers ;
 IN: morse
 
-ERROR: no-morse-code ch ;
+ERROR: no-morse-ch ch ;
 
 <PRIVATE
 
@@ -11,7 +11,7 @@ CONSTANT: dot-char CHAR: .
 CONSTANT: dash-char CHAR: -
 CONSTANT: char-gap-char CHAR: \s
 CONSTANT: word-gap-char CHAR: /
-CONSTANT: unknown-char "?"
+CONSTANT: unknown-char CHAR: ?
 
 PRIVATE>
 
@@ -76,7 +76,7 @@ CONSTANT: morse-code-table $[
 ]
 
 : ch>morse ( ch -- morse )
-    ch>lower morse-code-table at unknown-char or ;
+    ch>lower morse-code-table at unknown-char 1string or ;
 
 : morse>ch ( str -- ch )
     morse-code-table value-at char-gap-char or ;
@@ -156,7 +156,8 @@ CONSTANT: beep-freq 880
             { dot-char [ dot ] }
             { dash-char [ dash ] }
             { word-gap-char [ intra-char-gap ] }
-            [ drop intra-char-gap ]
+            { unknown-char [ intra-char-gap ] }
+            [ no-morse-ch ]
         } case
     ] interleave ;
 
index e7acf1f5bbe1b87feddbc4f839434ac92f7f5f6b..eff0043ac373a9adcffc51ec78dd9aceb21ffc9e 100644 (file)
@@ -1,5 +1,6 @@
 USING: hashtables assocs sequences locals math accessors multiline delegate strings
-delegate.protocols kernel peg peg.ebnf lexer namespaces combinators parser words ;
+delegate.protocols kernel peg peg.ebnf peg.private lexer namespaces combinators parser
+words ;
 IN: peg-lexer
 
 TUPLE: lex-hash hash ;
@@ -43,12 +44,12 @@ M: lex-hash at*
 
 : parse* ( parser -- ast )
     compile
-    [ execute( -- result ) [ error-stack get first throw ] unless* ] with-global-lexer
-    ast>> ;
+    [ execute [ error-stack get first throw ] unless* ] with-global-lexer
+    ast>> ; inline
 
 : create-bnf ( name parser -- )
-    reset-tokenizer [ lexer get skip-blank parse* parsed ] curry
-    define-syntax ;
+    reset-tokenizer [ lexer get skip-blank parse* dup ignore? [ drop ] [ parsed ] if ] curry
+    define-syntax word make-inline ;
     
 SYNTAX: ON-BNF:
     CREATE-WORD reset-tokenizer ";ON-BNF" parse-multiline-string parse-ebnf
diff --git a/extra/str-fry/authors.txt b/extra/str-fry/authors.txt
new file mode 100644 (file)
index 0000000..ce0899f
--- /dev/null
@@ -0,0 +1 @@
+Sam Anklesaria
\ No newline at end of file
diff --git a/extra/str-fry/str-fry.factor b/extra/str-fry/str-fry.factor
new file mode 100644 (file)
index 0000000..aafdaa9
--- /dev/null
@@ -0,0 +1,4 @@
+USING: kernel sequences splitting strings.parser ;
+IN: str-fry
+: str-fry ( str -- quot ) "_" split unclip [ [ rot glue ] reduce ] 2curry ;
+SYNTAX: I" parse-string rest str-fry over push-all ;
\ No newline at end of file
diff --git a/extra/str-fry/summary.txt b/extra/str-fry/summary.txt
new file mode 100644 (file)
index 0000000..7755f5a
--- /dev/null
@@ -0,0 +1 @@
+String Frying
\ No newline at end of file
index 7f71e08e836b84e60eff6a4ad649766ac070a47a..5be2dc89e2fbbc96f120901d512f5c58e0c9abaa 100755 (executable)
@@ -3,7 +3,7 @@
 USING: alien alien.c-types alien.strings
 kernel libc math namespaces system-info.backend
 system-info.windows windows windows.advapi32
-windows.kernel32 system byte-arrays ;
+windows.kernel32 system byte-arrays windows.errors ;
 IN: system-info.windows.nt
 
 M: winnt cpus ( -- n )
@@ -41,6 +41,6 @@ M: winnt available-virtual-mem ( -- n )
     GetComputerName win32-error=0/f alien>native-string ;
  
 : username ( -- string )
-    UNLEN 1+
+    UNLEN 1 +
     [ <byte-array> dup ] keep <uint>
     GetUserName win32-error=0/f alien>native-string ;
index 66abb59ee9aca43c5a5f179b368d6530c3b29b2c..4d2343013125567d4c873bfc7ba93df57acf77e7 100755 (executable)
@@ -3,7 +3,7 @@
 USING: alien alien.c-types kernel libc math namespaces
 windows windows.kernel32 windows.advapi32
 words combinators vocabs.loader system-info.backend
-system alien.strings ;
+system alien.strings windows.errors ;
 IN: system-info.windows
 
 : system-info ( -- SYSTEM_INFO )
index 297157c08bd88248d8d2bd71c8b1a6549ef90b8b..e28187125231155aefe93ff6f5fa1dab95207f85 100755 (executable)
@@ -13,7 +13,7 @@ CONSTANT: block-size 512
 TUPLE: tar-header name mode uid gid size mtime checksum typeflag
 linkname magic version uname gname devmajor devminor prefix ;
 
-ERROR: checksum-error ;
+ERROR: checksum-error header ;
 
 : trim-string ( seq -- newseq ) [ "\0 " member? ] trim ;
 
@@ -60,14 +60,16 @@ ERROR: checksum-error ;
     ] if ;
 
 : parse-tar-header ( seq -- obj )
-    [ checksum-header ] keep over zero-checksum = [
+    dup checksum-header dup zero-checksum = [
         2drop
         \ tar-header new
             0 >>size
             0 >>checksum
     ] [
-        binary [ read-tar-header ] with-byte-reader
-        [ checksum>> = [ checksum-error ] unless ] keep
+        [
+            binary [ read-tar-header ] with-byte-reader
+            dup checksum>>
+        ] dip = [ checksum-error ] unless
     ] if ;
 
 ERROR: unknown-typeflag ch ;
@@ -90,7 +92,8 @@ M: unknown-typeflag summary ( obj -- str )
     ] if ;
 
 ! Hard link
-: typeflag-1 ( header -- ) unknown-typeflag ;
+: typeflag-1 ( header -- )
+    [ name>> ] [ linkname>> ] bi make-hard-link ;
 
 ! Symlink
 : typeflag-2 ( header -- )
@@ -141,7 +144,8 @@ M: unknown-typeflag summary ( obj -- str )
 
 ! Long file name
 : typeflag-L ( header -- )
-    drop ;
+    drop
+    ;
     ! <string-writer> [ read-data-blocks ] keep
     ! >string [ zero? ] trim-tail filename set
     ! filename get prepend-current-directory make-directories ;
@@ -161,7 +165,7 @@ M: unknown-typeflag summary ( obj -- str )
 ! Vendor extended header type
 : typeflag-X ( header -- ) unknown-typeflag ;
 
-: (parse-tar) ( -- )
+: parse-tar ( -- )
     block-size read dup length block-size = [
         parse-tar-header
         dup typeflag>>
@@ -182,19 +186,19 @@ M: unknown-typeflag summary ( obj -- str )
             ! { CHAR: E [ typeflag-E ] }
             ! { CHAR: I [ typeflag-I ] }
             ! { CHAR: K [ typeflag-K ] }
-            { CHAR: L [ typeflag-L ] }
+            { CHAR: L [ typeflag-L ] }
             ! { CHAR: M [ typeflag-M ] }
             ! { CHAR: N [ typeflag-N ] }
             ! { CHAR: S [ typeflag-S ] }
             ! { CHAR: V [ typeflag-V ] }
             ! { CHAR: X [ typeflag-X ] }
             { f [ drop ] }
-        } case (parse-tar)
+        } case parse-tar
     ] [
         drop
     ] if ;
 
 : untar ( path -- )
-    normalize-path [ ] [ parent-directory ] bi [
-         binary [ (parse-tar) ] with-file-reader
+    normalize-path dup parent-directory [
+         binary [ parse-tar ] with-file-reader
     ] with-directory ;
diff --git a/extra/ui/frp/authors.txt b/extra/ui/frp/authors.txt
new file mode 100644 (file)
index 0000000..2300f69
--- /dev/null
@@ -0,0 +1 @@
+Sam Anklesaria
diff --git a/extra/ui/frp/frp-docs.factor b/extra/ui/frp/frp-docs.factor
new file mode 100644 (file)
index 0000000..af44567
--- /dev/null
@@ -0,0 +1,46 @@
+USING: help.markup help.syntax models monads sequences
+ui.gadgets.buttons ui.gadgets.tracks ;
+IN: ui.frp
+
+! Layout utilities
+
+HELP: ,
+{ $values { "uiitem" "a gadget or model" } }
+{ $description "Used in a series of gadgets created by a box, accumulating the gadget" } ;
+HELP: ->
+{ $values { "uiitem" "a gadget or model" } { "model" model } }
+{ $description "Like " { $link , } "but passes its model on for further use." } ;
+HELP: <hbox>
+{ $values { "gadgets" "a list of gadgets" } { "track" track } }
+{ $syntax "[ gadget , gadget , ... ] <hbox>" }
+{ $description "Creates an horizontal track containing the gadgets listed in the quotation" } ;
+HELP: <vbox>
+{ $values { "gadgets" "a list of gadgets" } { "track" track } }
+{ $syntax "[ gadget , gadget , ... ] <hbox>" }
+{ $description "Creates an vertical track containing the gadgets listed in the quotation" } ;
+
+! Gadgets
+HELP: <frp-button>
+{ $values { "text" "the button's label" } { "button" button } }
+{ $description "Creates an button whose model updates on clicks" } ;
+
+HELP: <merge>
+{ $values { "models" "a list of models" } { "model" merge-model } }
+{ $description "Creates a model that merges the updates of others" } ;
+
+HELP: <filter>
+{ $values { "model" model } { "quot" "quotation with stack effect ( a b -- c )" } { "filter-model" filter-model } }
+{ $description "Creates a model that uses the updates of another model when they satisfy a given predicate" } ;
+
+HELP: <fold>
+{ $values { "oldval" "starting value" } { "quot" "applied to update and previous values" } { "model" model } { "model'" model } }
+{ $description "Similar to " { $link reduce } " but works on models, applying a quotation to the previous and new values at each update" } ;
+
+HELP: switch
+{ $values { "signal1" model } { "signal2" model } { "signal'" model } }
+{ $description "Creates a model that starts with the behavior of model1 and switches to the behavior of model2 on its update" } ;
+
+ARTICLE: { "frp" "instances" } "FRP Instances"
+"Models are all functors, as " { $link fmap } " corresponds directly to the " { $link "models.arrow" } " vocabulary. "
+"Also, a gadget is a monad. Binding recieves a model and creates a new gadget." ;
+
diff --git a/extra/ui/frp/frp.factor b/extra/ui/frp/frp.factor
new file mode 100644 (file)
index 0000000..aa7c44e
--- /dev/null
@@ -0,0 +1,90 @@
+USING: accessors arrays colors fonts fry kernel models
+models.product monads sequences ui.gadgets ui.gadgets.buttons
+ui.gadgets.editors ui.gadgets.line-support ui.gadgets.tables
+ui.gadgets.tracks ui.render ;
+QUALIFIED: make
+IN: ui.frp
+
+! Gadgets
+: <frp-button> ( text -- button ) [ t swap set-control-value ] <border-button> f <model> >>model ;
+TUPLE: frp-table < table quot val-quot color-quot column-titles column-alignment ;
+M: frp-table column-titles column-titles>> ;
+M: frp-table column-alignment column-alignment>> ;
+M: frp-table row-columns quot>> [ call( a -- b ) ] [ drop f ] if* ;
+M: frp-table row-value val-quot>> [ call( a -- b ) ]  [ drop f ] if* ;
+M: frp-table row-color color-quot>> [ call( a -- b ) ]  [ drop f ] if* ;
+
+: <frp-table> ( model -- table )
+    frp-table new-line-gadget dup >>renderer [ ] >>quot swap >>model
+    f <model> >>selected-value sans-serif-font >>font
+    focus-border-color >>focus-border-color
+    transparent >>column-line-color ;
+: <frp-list> ( model -- table ) <frp-table> [ 1array ] >>quot ;
+: <frp-field> ( -- field ) f <model> <model-field> ;
+
+! Layout utilities
+
+GENERIC: output-model ( gadget -- model )
+M: gadget output-model model>> ;
+M: frp-table output-model selected-value>> ;
+
+GENERIC: , ( uiitem -- )
+M: gadget , make:, ;
+M: model , activate-model ;
+
+GENERIC: -> ( uiitem -- model )
+M: gadget -> dup make:, output-model ;
+M: model -> dup , ;
+M: table -> dup , selected-value>> ;
+
+: <box> ( gadgets type -- track )
+   [ { } make:make ] dip <track> swap [ f track-add ] each ; inline
+: <box*> ( gadgets type -- track ) [ <box> ] [ [ model>> ] map <product> ] bi >>model ; inline
+: <hbox> ( gadgets -- track ) horizontal <box> ; inline
+: <vbox> ( gadgets -- track ) vertical <box> ; inline
+
+! Model utilities
+TUPLE: multi-model < model ;
+! M: multi-model model-activated dup model-changed ;
+: <multi-model> ( models kind -- model ) f swap new-model [ [ add-dependency ] curry each ] keep ;
+
+TUPLE: merge-model < multi-model ;
+M: merge-model model-changed [ value>> ] dip set-model ;
+: <merge> ( models -- model ) merge-model <multi-model> ;
+
+TUPLE: filter-model < multi-model quot ;
+M: filter-model model-changed [ value>> ] dip [ quot>> call( val -- bool ) ] 2keep
+   [ set-model ] [ 2drop ] if ;
+: <filter> ( model quot -- filter-model ) [ 1array filter-model <multi-model> ] dip >>quot ;
+
+TUPLE: fold-model < multi-model oldval quot ;
+M: fold-model model-changed [ [ value>> ] [ [ oldval>> ] [ quot>> ] bi ] bi*
+   call( val oldval -- newval ) ] keep set-model ;
+: <fold> ( oldval quot model -- model' ) 1array fold-model <multi-model> swap >>quot swap >>oldval ;
+
+TUPLE: switch-model < multi-model switcher on ;
+M: switch-model model-changed tuck [ switcher>> = ] 2keep
+   '[ on>> [ _ value>> _ set-model ] when ] [ t swap (>>on) ] if ;
+: switch ( signal1 signal2 -- signal' ) [ 2array switch-model <multi-model> ] keep >>switcher ;
+
+TUPLE: mapped < model model quot ;
+
+: <mapped> ( model quot -- arrow )
+    f mapped new-model
+        swap >>quot
+        over >>model
+        [ add-dependency ] keep ;
+
+M: mapped model-changed
+    [ [ value>> ] [ quot>> ] bi* call( old -- new ) ] [ nip ] 2bi
+    set-model ;
+
+! Instances
+M: model fmap <mapped> ;
+
+SINGLETON: gadget-monad
+INSTANCE: gadget-monad monad
+INSTANCE: gadget monad
+M: gadget monad-of drop gadget-monad ;
+M: gadget-monad return drop <gadget> swap >>model ;
+M: gadget >>= model>> '[ _ swap call( x -- y ) ] ; 
\ No newline at end of file
diff --git a/extra/ui/frp/summary.txt b/extra/ui/frp/summary.txt
new file mode 100644 (file)
index 0000000..3b49d34
--- /dev/null
@@ -0,0 +1 @@
+Utilities for functional reactive programming in user interfaces
index 04c6b013dff8c83f5c6dc9409a47699090101243..03d60957fa19a16e7221d9701d522ea550334c73 100644 (file)
@@ -1,4 +1,4 @@
-USING: accessors ui ui.gadgets ui.gadgets.labels ui.gadgets.buttons ui.gadgets.packs locals sequences io.styles ;
+USING: accessors ui ui.gadgets ui.gadgets.labels ui.gadgets.buttons ui.gadgets.packs locals sequences fonts io.styles ;
 IN: ui.gadgets.alerts
-:: alert ( quot string -- ) <pile> { 10 10 } >>gap 1 >>align string <label> { "sans-serif" plain 18 } >>font { 200 100 } >>pref-dim add-gadget 
+:: alert ( quot string -- ) <pile> { 10 10 } >>gap 1 >>align string <label> T{ font { name "sans-serif" } { size 18 } } >>font { 200 100 } >>pref-dim add-gadget 
    "okay" [ close-window ] quot append <border-button> add-gadget "" open-window ;
\ No newline at end of file
diff --git a/extra/ui/gadgets/alerts/authors.txt b/extra/ui/gadgets/alerts/authors.txt
new file mode 100644 (file)
index 0000000..ce0899f
--- /dev/null
@@ -0,0 +1 @@
+Sam Anklesaria
\ No newline at end of file
diff --git a/extra/ui/gadgets/alerts/summary.txt b/extra/ui/gadgets/alerts/summary.txt
new file mode 100644 (file)
index 0000000..f1cd420
--- /dev/null
@@ -0,0 +1 @@
+Really simple dialog boxes
\ No newline at end of file
diff --git a/extra/ui/gadgets/book-extras/authors.txt b/extra/ui/gadgets/book-extras/authors.txt
new file mode 100644 (file)
index 0000000..ce0899f
--- /dev/null
@@ -0,0 +1 @@
+Sam Anklesaria
\ No newline at end of file
diff --git a/extra/ui/gadgets/book-extras/summary.txt b/extra/ui/gadgets/book-extras/summary.txt
new file mode 100644 (file)
index 0000000..5a221ab
--- /dev/null
@@ -0,0 +1 @@
+Easily switch between pages of book views
\ No newline at end of file
diff --git a/extra/ui/gadgets/comboboxes/authors.txt b/extra/ui/gadgets/comboboxes/authors.txt
new file mode 100644 (file)
index 0000000..ce0899f
--- /dev/null
@@ -0,0 +1 @@
+Sam Anklesaria
\ No newline at end of file
diff --git a/extra/ui/gadgets/comboboxes/comboboxes.factor b/extra/ui/gadgets/comboboxes/comboboxes.factor
new file mode 100644 (file)
index 0000000..b0dbe34
--- /dev/null
@@ -0,0 +1,22 @@
+USING: accessors arrays kernel math.rectangles models sequences
+ui.frp ui.gadgets ui.gadgets.glass ui.gadgets.labels
+ui.gadgets.tables ui.gestures ;
+IN: ui.gadgets.comboboxes
+
+TUPLE: combo-table < table spawner ;
+
+M: combo-table handle-gesture [ call-next-method ] 2keep swap
+   T{ button-up } = [
+      [ spawner>> ]
+      [ selected-value>> value>> [ swap set-control-value ] [ drop ] if* ]
+      [ hide-glass ] tri drop t
+   ] [ drop ] if ;
+
+TUPLE: combobox < label-control table ;
+combobox H{
+   { T{ button-down } [ dup table>> over >>spawner <zero-rect> show-glass ] }
+} set-gestures
+
+: <combobox> ( options -- combobox ) [ first [ combobox new-label ] keep <model> >>model ] keep
+   [ 1array ] map <model> trivial-renderer combo-table new-table
+   >>table ;
\ No newline at end of file
diff --git a/extra/ui/gadgets/comboboxes/summary.txt b/extra/ui/gadgets/comboboxes/summary.txt
new file mode 100644 (file)
index 0000000..0f2ce2b
--- /dev/null
@@ -0,0 +1 @@
+Combo boxes have a model choosen from a list of options
\ No newline at end of file
index 11a1e325c3f857961c350fadae02c20c6e98c0b3..e02701b6909674772ca6b92b514c929f25f18ffb 100644 (file)
@@ -56,9 +56,6 @@ SYMBOL: *calling*
 : subtract-overhead ( {oldtime,n} overhead -- {newtime,n} )
   [ first2 ] dip
   swap [ * - ] keep 2array ;
-  
-: change-global ( variable quot -- )
-  global swap change-at ; inline
 
 : (correct-for-timing-overhead) ( timingshash -- timingshash )
   time-dummy-word [ subtract-overhead ] curry assoc-map ;  
index 4842f960d1787ebcbf8c9a3755601a0a46c2ae9d..8b25744011446094083f6156277639d355b95b1c 100644 (file)
         fuel-debug--uses nil
         fuel-debug--uses-restarts nil))
 
+(defun fuel-debug--current-usings (file)
+  (with-current-buffer (find-file-noselect file)
+    (sort (fuel-syntax--find-usings t) 'string<)))
+
 (defun fuel-debug--uses-for-file (file)
   (let* ((lines (fuel-debug--file-lines file))
-         (cmd `(:fuel ((V{ ,@lines } fuel-get-uses)) t t)))
+         (old-usings (fuel-debug--current-usings file))
+         (cmd `(:fuel ((V{ ,@old-usings }
+                           [ V{ ,@lines } fuel-get-uses ]
+                           fuel-use-suggested-vocabs)) t t)))
     (fuel-debug--uses-prepare file)
     (fuel--with-popup (fuel-debug--uses-buffer)
       (insert "Asking Factor. Please, wait ...\n")
 
 (defun fuel-debug--uses-display (uses)
   (let* ((inhibit-read-only t)
-         (old (with-current-buffer (find-file-noselect fuel-debug--uses-file)
-                (sort (fuel-syntax--find-usings t) 'string<)))
+         (old (fuel-debug--current-usings fuel-debug--uses-file))
          (new (sort uses 'string<)))
     (erase-buffer)
     (fuel-debug--uses-insert-title)
index aa9a7d944e17f2de75089370ec86fc2299a49e15..0186392f3445736e830dbb8764c1e9df549a52c7 100644 (file)
@@ -140,7 +140,7 @@ for details."
   (interactive)
   (message "Loading all vocabularies in USING: form ...")
   (let ((err (fuel-eval--retort-error
-              (fuel-eval--send/wait '(:fuel* (t) t :usings) 120000))))
+              (fuel-eval--send/wait '(:fuel* (t .) t :usings) 120000))))
     (message (if err "Warning: some vocabularies failed to load"
                "All vocabularies loaded"))))
 
index 6b646511ca0794887d2170321cbc8abc80d9f0b6..61aa2b7cdd1bd187200560a7d84e185a1802615d 100644 (file)
     table))
 
 (defconst fuel-syntax--syntactic-keywords
-  `(;; Comments
-    ("\\_<\\(#?!\\) .*\\(\n\\|$\\)" (1 "<") (2 ">"))
-    ("\\_<\\(#?!\\)\\(\n\\|$\\)" (1 "<") (2 ">"))
-    ;; Strings and chars
-    ("CHAR: \\(\"\\) [^\\\"]*?\\(\"\\)\\([^\\\"]\\|\\\\.\\)*?\\(\"\\)"
-     (1 "w") (2 "\"") (4 "\""))
-    ("\\(CHAR:\\|\\\\\\) \\(.\\)\\( \\|$\\)" (2 "w"))
-    ("\\( \\|^\\)\\(DLL\\|P\\|SBUF\\)\\(\"\\)\\([^\n\r\f\\\"]\\|\\\\.\\)*?\\(\"\\)"
-     (3 "\"") (5 "\""))
-    ("\\_<\\(\"\\)\\([^\n\r\f\\\"]\\|\\\\.\\)*?\\(\"\\)" (1 "\"") (3 "\""))
+  `(;; Strings and chars
     ("\\_<<\\(\"\\)\\_>" (1 "<b"))
     ("\\_<\\(\"\\)>\\_>" (1 ">b"))
+    ("\\( \\|^\\)\\(DLL\\|P\\|SBUF\\)?\\(\"\\)\\(\\([^\n\r\f\"\\]\\|\\\\.\\)*\\)\\(\"\\)"
+     (3 "\"") (6 "\""))
+    ("CHAR: \\(\"\\) [^\\\"]*?\\(\"\\)\\([^\\\"]\\|\\\\.\\)*?\\(\"\\)"
+     (1 "w") (2 "<b") (4 ">b"))
+    ("\\(CHAR:\\|\\\\\\) \\(\\w\\|!\\)\\( \\|$\\)" (2 "w"))
+    ;; Comments
+    ("\\_<\\(#?!\\) .*\\(\n\\|$\\)" (1 "<") (2 ">"))
+    ("\\_<\\(#?!\\)\\(\n\\|$\\)" (1 "<") (2 ">"))
     ;; postpone
     ("\\_<POSTPONE:\\( \\).*\\(\n\\)" (1 "<b") (2 ">b"))
     ;; Multiline constructs
old mode 100644 (file)
new mode 100755 (executable)
index 1f48847..d7214a6
@@ -18,6 +18,7 @@ else
 endif
 
 # CFLAGS += -fPIC
+FFI_TEST_CFLAGS = -fPIC
 
 # LINKER = gcc -shared -o
 # LINK_WITH_ENGINE = '-Wl,-rpath,$$ORIGIN' -lfactor
index bbd26e8e11d5fef69543419b10fb12679e09ec22..e060ef7019eb7acc2fe991a859538a28d9abbde3 100644 (file)
@@ -2,4 +2,4 @@ BOOT_ARCH = x86
 PLAF_DLL_OBJS += vm/cpu-x86.32.o
 
 # gcc bug workaround
-CFLAGS += -fno-builtin-strlen -fno-builtin-strcat -mtune=pentium4
+CFLAGS += -fno-builtin-strlen -fno-builtin-strcat
diff --git a/vm/arrays.c b/vm/arrays.c
new file mode 100644 (file)
index 0000000..4d5dc67
--- /dev/null
@@ -0,0 +1,159 @@
+#include "master.h"
+
+/* the array is full of undefined data, and must be correctly filled before the
+next GC. size is in cells */
+F_ARRAY *allot_array_internal(CELL type, CELL capacity)
+{
+       F_ARRAY *array = allot_object(type,array_size(capacity));
+       array->capacity = tag_fixnum(capacity);
+       return array;
+}
+
+/* make a new array with an initial element */
+F_ARRAY *allot_array(CELL type, CELL capacity, CELL fill)
+{
+       int i;
+       REGISTER_ROOT(fill);
+       F_ARRAY* array = allot_array_internal(type, capacity);
+       UNREGISTER_ROOT(fill);
+       if(fill == 0)
+               memset((void*)AREF(array,0),'\0',capacity * CELLS);
+       else
+       {
+               /* No need for write barrier here. Either the object is in
+               the nursery, or it was allocated directly in tenured space
+               and the write barrier is already hit for us in that case. */
+               for(i = 0; i < capacity; i++)
+                       put(AREF(array,i),fill);
+       }
+       return array;
+}
+
+/* push a new array on the stack */
+void primitive_array(void)
+{
+       CELL initial = dpop();
+       CELL size = unbox_array_size();
+       dpush(tag_array(allot_array(ARRAY_TYPE,size,initial)));
+}
+
+CELL allot_array_1(CELL obj)
+{
+       REGISTER_ROOT(obj);
+       F_ARRAY *a = allot_array_internal(ARRAY_TYPE,1);
+       UNREGISTER_ROOT(obj);
+       set_array_nth(a,0,obj);
+       return tag_array(a);
+}
+
+CELL allot_array_2(CELL v1, CELL v2)
+{
+       REGISTER_ROOT(v1);
+       REGISTER_ROOT(v2);
+       F_ARRAY *a = allot_array_internal(ARRAY_TYPE,2);
+       UNREGISTER_ROOT(v2);
+       UNREGISTER_ROOT(v1);
+       set_array_nth(a,0,v1);
+       set_array_nth(a,1,v2);
+       return tag_array(a);
+}
+
+CELL allot_array_4(CELL v1, CELL v2, CELL v3, CELL v4)
+{
+       REGISTER_ROOT(v1);
+       REGISTER_ROOT(v2);
+       REGISTER_ROOT(v3);
+       REGISTER_ROOT(v4);
+       F_ARRAY *a = allot_array_internal(ARRAY_TYPE,4);
+       UNREGISTER_ROOT(v4);
+       UNREGISTER_ROOT(v3);
+       UNREGISTER_ROOT(v2);
+       UNREGISTER_ROOT(v1);
+       set_array_nth(a,0,v1);
+       set_array_nth(a,1,v2);
+       set_array_nth(a,2,v3);
+       set_array_nth(a,3,v4);
+       return tag_array(a);
+}
+
+static bool reallot_array_in_place_p(F_ARRAY *array, CELL capacity)
+{
+       return in_zone(&nursery,(CELL)array) && capacity <= array_capacity(array);
+}
+
+F_ARRAY *reallot_array(F_ARRAY *array, CELL capacity)
+{
+#ifdef FACTOR_DEBUG
+       CELL header = untag_header(array->header);
+       assert(header == ARRAY_TYPE || header == BIGNUM_TYPE);
+#endif
+
+       if(reallot_array_in_place_p(array,capacity))
+       {
+               array->capacity = tag_fixnum(capacity);
+               return array;
+       }
+       else
+       {
+               CELL to_copy = array_capacity(array);
+               if(capacity < to_copy)
+               to_copy = capacity;
+
+               REGISTER_UNTAGGED(array);
+               F_ARRAY* new_array = allot_array_internal(untag_header(array->header),capacity);
+               UNREGISTER_UNTAGGED(array);
+       
+               memcpy(new_array + 1,array + 1,to_copy * CELLS);
+               memset((char *)AREF(new_array,to_copy),'\0',(capacity - to_copy) * CELLS);
+
+               return new_array;
+       }
+}
+
+void primitive_resize_array(void)
+{
+       F_ARRAY* array = untag_array(dpop());
+       CELL capacity = unbox_array_size();
+       dpush(tag_array(reallot_array(array,capacity)));
+}
+
+void growable_array_add(F_GROWABLE_ARRAY *array, CELL elt)
+{
+       F_ARRAY *underlying = untag_object(array->array);
+       REGISTER_ROOT(elt);
+
+       if(array->count == array_capacity(underlying))
+       {
+               underlying = reallot_array(underlying,array->count * 2);
+               array->array = tag_array(underlying);
+       }
+
+       UNREGISTER_ROOT(elt);
+       set_array_nth(underlying,array->count++,elt);
+}
+
+void growable_array_append(F_GROWABLE_ARRAY *array, F_ARRAY *elts)
+{
+       REGISTER_UNTAGGED(elts);
+
+       F_ARRAY *underlying = untag_object(array->array);
+
+       CELL elts_size = array_capacity(elts);
+       CELL new_size = array->count + elts_size;
+
+       if(new_size >= array_capacity(underlying))
+       {
+               underlying = reallot_array(underlying,new_size * 2);
+               array->array = tag_array(underlying);
+       }
+
+       UNREGISTER_UNTAGGED(elts);
+
+       write_barrier(array->array);
+
+       memcpy((void *)AREF(underlying,array->count),
+              (void *)AREF(elts,0),
+              elts_size * CELLS);
+
+       array->count += elts_size;
+}
diff --git a/vm/arrays.h b/vm/arrays.h
new file mode 100644 (file)
index 0000000..3b2a065
--- /dev/null
@@ -0,0 +1,95 @@
+DEFINE_UNTAG(F_ARRAY,ARRAY_TYPE,array)
+
+INLINE CELL tag_array(F_ARRAY *array)
+{
+       return RETAG(array,ARRAY_TYPE);
+}
+
+/* Inline functions */
+INLINE CELL array_size(CELL size)
+{
+       return sizeof(F_ARRAY) + size * CELLS;
+}
+
+INLINE CELL array_capacity(F_ARRAY* array)
+{
+#ifdef FACTOR_DEBUG
+       CELL header = untag_header(array->header);
+       assert(header == ARRAY_TYPE || header == BIGNUM_TYPE || header == BYTE_ARRAY_TYPE);
+#endif
+       return array->capacity >> TAG_BITS;
+}
+
+#define AREF(array,index) ((CELL)(array) + sizeof(F_ARRAY) + (index) * CELLS)
+#define UNAREF(array,ptr) (((CELL)(ptr)-(CELL)(array)-sizeof(F_ARRAY)) / CELLS)
+
+INLINE CELL array_nth(F_ARRAY *array, CELL slot)
+{
+#ifdef FACTOR_DEBUG
+       assert(slot < array_capacity(array));
+       assert(untag_header(array->header) == ARRAY_TYPE);
+#endif
+       return get(AREF(array,slot));
+}
+
+INLINE void set_array_nth(F_ARRAY *array, CELL slot, CELL value)
+{
+#ifdef FACTOR_DEBUG
+       assert(slot < array_capacity(array));
+       assert(untag_header(array->header) == ARRAY_TYPE);
+#endif
+       put(AREF(array,slot),value);
+       write_barrier((CELL)array);
+}
+
+F_ARRAY *allot_array_internal(CELL type, CELL capacity);
+F_ARRAY *allot_array(CELL type, CELL capacity, CELL fill);
+F_BYTE_ARRAY *allot_byte_array(CELL size);
+
+CELL allot_array_1(CELL obj);
+CELL allot_array_2(CELL v1, CELL v2);
+CELL allot_array_4(CELL v1, CELL v2, CELL v3, CELL v4);
+
+void primitive_array(void);
+
+F_ARRAY *reallot_array(F_ARRAY* array, CELL capacity);
+void primitive_resize_array(void);
+
+/* Macros to simulate a vector in C */
+typedef struct {
+       CELL count;
+       CELL array;
+} F_GROWABLE_ARRAY;
+
+/* Allocates memory */
+INLINE F_GROWABLE_ARRAY make_growable_array(void)
+{
+       F_GROWABLE_ARRAY result;
+       result.count = 0;
+       result.array = tag_array(allot_array(ARRAY_TYPE,100,F));
+       return result;
+}
+
+#define GROWABLE_ARRAY(result) F_GROWABLE_ARRAY result##_g = make_growable_array(); \
+       REGISTER_ROOT(result##_g.array)
+
+void growable_array_add(F_GROWABLE_ARRAY *result, CELL elt);
+
+#define GROWABLE_ARRAY_ADD(result,elt) \
+       growable_array_add(&result##_g,elt)
+
+void growable_array_append(F_GROWABLE_ARRAY *result, F_ARRAY *elts);
+
+#define GROWABLE_ARRAY_APPEND(result,elts) \
+       growable_array_append(&result##_g,elts)
+
+INLINE void growable_array_trim(F_GROWABLE_ARRAY *array)
+{
+       array->array = tag_array(reallot_array(untag_object(array->array),array->count));
+}
+
+#define GROWABLE_ARRAY_TRIM(result) growable_array_trim(&result##_g)
+
+#define GROWABLE_ARRAY_DONE(result) \
+       UNREGISTER_ROOT(result##_g.array); \
+       CELL result = result##_g.array;
index a101473fc64f370849cca35b6c1af74564281ee9..7c835686c2e9f111f8d5493f5f4c5a4570b8aeff 100644 (file)
@@ -64,7 +64,7 @@ typedef F_FIXNUM bignum_length_type;
 
 #define BIGNUM_LENGTH(bignum) (untag_fixnum_fast((bignum)->capacity) - 1)
 
-#define BIGNUM_NEGATIVE_P(bignum) (array_nth(bignum,0) != 0)
+#define BIGNUM_NEGATIVE_P(bignum) (get(AREF(bignum,0)) != 0)
 #define BIGNUM_SET_NEGATIVE_P(bignum,neg) put(AREF(bignum,0),neg)
 
 #define BIGNUM_ZERO_P(bignum)                                          \
diff --git a/vm/booleans.c b/vm/booleans.c
new file mode 100644 (file)
index 0000000..1132658
--- /dev/null
@@ -0,0 +1,13 @@
+#include "master.h"
+
+/* FFI calls this */
+void box_boolean(bool value)
+{
+       dpush(value ? T : F);
+}
+
+/* FFI calls this */
+bool to_boolean(CELL value)
+{
+       return value != F;
+}
diff --git a/vm/booleans.h b/vm/booleans.h
new file mode 100644 (file)
index 0000000..ae49652
--- /dev/null
@@ -0,0 +1,7 @@
+INLINE CELL tag_boolean(CELL untagged)
+{
+       return (untagged == false ? F : T);
+}
+
+DLLEXPORT void box_boolean(bool value);
+DLLEXPORT bool to_boolean(CELL value);
diff --git a/vm/byte_arrays.c b/vm/byte_arrays.c
new file mode 100644 (file)
index 0000000..480b4d7
--- /dev/null
@@ -0,0 +1,85 @@
+#include "master.h"
+
+/* must fill out array before next GC */
+F_BYTE_ARRAY *allot_byte_array_internal(CELL size)
+{
+       F_BYTE_ARRAY *array = allot_object(BYTE_ARRAY_TYPE,
+               byte_array_size(size));
+       array->capacity = tag_fixnum(size);
+       return array;
+}
+
+/* size is in bytes this time */
+F_BYTE_ARRAY *allot_byte_array(CELL size)
+{
+       F_BYTE_ARRAY *array = allot_byte_array_internal(size);
+       memset(array + 1,0,size);
+       return array;
+}
+
+/* push a new byte array on the stack */
+void primitive_byte_array(void)
+{
+       CELL size = unbox_array_size();
+       dpush(tag_object(allot_byte_array(size)));
+}
+
+void primitive_uninitialized_byte_array(void)
+{
+       CELL size = unbox_array_size();
+       dpush(tag_object(allot_byte_array_internal(size)));
+}
+
+static bool reallot_byte_array_in_place_p(F_BYTE_ARRAY *array, CELL capacity)
+{
+       return in_zone(&nursery,(CELL)array) && capacity <= array_capacity(array);
+}
+
+F_BYTE_ARRAY *reallot_byte_array(F_BYTE_ARRAY *array, CELL capacity)
+{
+#ifdef FACTOR_DEBUG
+       assert(untag_header(array->header) == BYTE_ARRAY_TYPE);
+#endif
+       if(reallot_byte_array_in_place_p(array,capacity))
+       {
+               array->capacity = tag_fixnum(capacity);
+               return array;
+       }
+       else
+       {
+               CELL to_copy = array_capacity(array);
+               if(capacity < to_copy)
+               to_copy = capacity;
+
+               REGISTER_UNTAGGED(array);
+               F_BYTE_ARRAY *new_array = allot_byte_array_internal(capacity);
+               UNREGISTER_UNTAGGED(array);
+
+               memcpy(new_array + 1,array + 1,to_copy);
+
+               return new_array;
+       }
+}
+
+void primitive_resize_byte_array(void)
+{
+       F_BYTE_ARRAY* array = untag_byte_array(dpop());
+       CELL capacity = unbox_array_size();
+       dpush(tag_object(reallot_byte_array(array,capacity)));
+}
+
+void growable_byte_array_append(F_GROWABLE_BYTE_ARRAY *array, void *elts, CELL len)
+{
+       CELL new_size = array->count + len;
+       F_BYTE_ARRAY *underlying = untag_object(array->array);
+
+       if(new_size >= byte_array_capacity(underlying))
+       {
+               underlying = reallot_byte_array(underlying,new_size * 2);
+               array->array = tag_object(underlying);
+       }
+
+       memcpy((void *)BREF(underlying,array->count),elts,len);
+
+       array->count += len;
+}
diff --git a/vm/byte_arrays.h b/vm/byte_arrays.h
new file mode 100644 (file)
index 0000000..65c9731
--- /dev/null
@@ -0,0 +1,40 @@
+DEFINE_UNTAG(F_BYTE_ARRAY,BYTE_ARRAY_TYPE,byte_array)
+
+INLINE CELL byte_array_capacity(F_BYTE_ARRAY *array)
+{
+       return untag_fixnum_fast(array->capacity);
+}
+
+INLINE CELL byte_array_size(CELL size)
+{
+       return sizeof(F_BYTE_ARRAY) + size;
+}
+
+F_BYTE_ARRAY *allot_byte_array(CELL size);
+F_BYTE_ARRAY *allot_byte_array_internal(CELL size);
+F_BYTE_ARRAY *reallot_byte_array(F_BYTE_ARRAY *array, CELL capacity);
+
+void primitive_byte_array(void);
+void primitive_uninitialized_byte_array(void);
+void primitive_resize_byte_array(void);
+
+/* Macros to simulate a byte vector in C */
+typedef struct {
+       CELL count;
+       CELL array;
+} F_GROWABLE_BYTE_ARRAY;
+
+INLINE F_GROWABLE_BYTE_ARRAY make_growable_byte_array(void)
+{
+       F_GROWABLE_BYTE_ARRAY result;
+       result.count = 0;
+       result.array = tag_object(allot_byte_array(100));
+       return result;
+}
+
+void growable_byte_array_append(F_GROWABLE_BYTE_ARRAY *result, void *elts, CELL len);
+
+INLINE void growable_byte_array_trim(F_GROWABLE_BYTE_ARRAY *byte_array)
+{
+       byte_array->array = tag_object(reallot_byte_array(untag_object(byte_array->array),byte_array->count));
+}
index b7e6b946bb4ec0c123ab70f5a6f3080ec86aca2d..26f8589c295f90856ffed83b0a8ec60cb52aa7ea 100755 (executable)
@@ -170,7 +170,7 @@ void primitive_callstack_to_array(void)
        frame_index = 0;
        iterate_callstack_object(stack,stack_frame_to_array);
 
-       dpush(tag_object(array));
+       dpush(tag_array(array));
 }
 
 F_STACK_FRAME *innermost_stack_frame(F_CALLSTACK *callstack)
@@ -214,7 +214,7 @@ void primitive_set_innermost_stack_frame_quot(void)
        REGISTER_UNTAGGED(callstack);
        REGISTER_UNTAGGED(quot);
 
-       jit_compile(tag_object(quot),true);
+       jit_compile(tag_quotation(quot),true);
 
        UNREGISTER_UNTAGGED(quot);
        UNREGISTER_UNTAGGED(callstack);
index 3c13e7b1cdf39d47473872f40c8803c3eabf291b..8b693c451cdbcd46c680235898327ab0d4be03cb 100755 (executable)
@@ -1,3 +1,10 @@
+INLINE CELL callstack_size(CELL size)
+{
+       return sizeof(F_CALLSTACK) + size;
+}
+
+DEFINE_UNTAG(F_CALLSTACK,CALLSTACK_TYPE,callstack)
+
 F_FASTCALL void save_callstack_bottom(F_STACK_FRAME *callstack_bottom);
 
 #define FIRST_STACK_FRAME(stack) (F_STACK_FRAME *)((stack) + 1)
index 1ce440c9aba0de70507265f292dbb20d71169fbb..f2ddc717f7b41f8890f1fa01ebd73eaab3dae707 100644 (file)
@@ -24,8 +24,10 @@ void iterate_relocations(F_CODE_BLOCK *compiled, RELOCATION_ITERATOR iter)
                        {
                        case RT_PRIMITIVE:
                        case RT_XT:
+                       case RT_XT_DIRECT:
                        case RT_IMMEDIATE:
                        case RT_HERE:
+                       case RT_UNTAGGED:
                                index++;
                                break;
                        case RT_DLSYM:
@@ -152,19 +154,55 @@ void copy_literal_references(F_CODE_BLOCK *compiled)
 
 CELL object_xt(CELL obj)
 {
-       if(type_of(obj) == WORD_TYPE)
-               return (CELL)untag_word(obj)->xt;
+       if(TAG(obj) == QUOTATION_TYPE)
+       {
+               F_QUOTATION *quot = untag_object(obj);
+               return (CELL)quot->xt;
+       }
        else
-               return (CELL)untag_quotation(obj)->xt;
+       {
+               F_WORD *word = untag_object(obj);
+               return (CELL)word->xt;
+       }
+}
+
+CELL word_direct_xt(CELL obj)
+{
+#ifdef FACTOR_DEBUG
+       type_check(WORD_TYPE,obj);
+#endif
+       F_WORD *word = untag_object(obj);
+       CELL quot = word->direct_entry_def;
+       if(quot == F || max_pic_size == 0)
+               return (CELL)word->xt;
+       else
+       {
+               F_QUOTATION *untagged = untag_object(quot);
+#ifdef FACTOR_DEBUG
+               type_check(QUOTATION_TYPE,quot);
+#endif
+               if(untagged->compiledp == F)
+                       return (CELL)word->xt;
+               else
+                       return (CELL)untagged->xt;
+       }
 }
 
 void update_word_references_step(F_REL rel, CELL index, F_CODE_BLOCK *compiled)
 {
-       if(REL_TYPE(rel) == RT_XT)
+       F_RELTYPE type = REL_TYPE(rel);
+       if(type == RT_XT || type == RT_XT_DIRECT)
        {
                CELL offset = REL_OFFSET(rel) + (CELL)(compiled + 1);
                F_ARRAY *literals = untag_object(compiled->literals);
-               CELL xt = object_xt(array_nth(literals,index));
+               CELL obj = array_nth(literals,index);
+
+               CELL xt;
+               if(type == RT_XT)
+                       xt = object_xt(obj);
+               else
+                       xt = word_direct_xt(obj);
+
                store_address_in_code_block(REL_CLASS(rel),offset,xt);
        }
 }
@@ -177,6 +215,18 @@ void update_word_references(F_CODE_BLOCK *compiled)
 {
        if(compiled->block.needs_fixup)
                relocate_code_block(compiled);
+       /* update_word_references() is always applied to every block in
+          the code heap. Since it resets all call sites to point to
+          their canonical XT (cold entry point for non-tail calls,
+          standard entry point for tail calls), it means that no PICs
+          are referenced after this is done. So instead of polluting
+          the code heap with dead PICs that will be freed on the next
+          GC, we add them to the free list immediately. */
+       else if(compiled->block.type == PIC_TYPE)
+       {
+               fflush(stdout);
+               heap_free(&code_heap,&compiled->block);
+       }
        else
        {
                iterate_relocations(compiled,update_word_references_step);
@@ -184,6 +234,19 @@ void update_word_references(F_CODE_BLOCK *compiled)
        }
 }
 
+void update_literal_and_word_references(F_CODE_BLOCK *compiled)
+{
+       update_literal_references(compiled);
+       update_word_references(compiled);
+}
+
+INLINE void check_code_address(CELL address)
+{
+#ifdef FACTOR_DEBUG
+       assert(address >= code_heap.segment->start && address < code_heap.segment->end);
+#endif
+}
+
 /* Update references to words. This is done after a new code block
 is added to the heap. */
 
@@ -191,6 +254,8 @@ is added to the heap. */
 collections */
 void mark_code_block(F_CODE_BLOCK *compiled)
 {
+       check_code_address((CELL)compiled);
+
        mark_block(&compiled->block);
 
        copy_handle(&compiled->literals);
@@ -220,12 +285,12 @@ void mark_object_code_block(CELL scan)
        F_QUOTATION *quot;
        F_CALLSTACK *stack;
 
-       switch(object_type(scan))
+       switch(hi_tag(scan))
        {
        case WORD_TYPE:
                word = (F_WORD *)scan;
                if(word->code)
-                 mark_code_block(word->code);
+                       mark_code_block(word->code);
                if(word->profiling)
                        mark_code_block(word->profiling);
                break;
@@ -287,6 +352,11 @@ void *get_rel_symbol(F_ARRAY *literals, CELL index)
 /* Compute an address to store at a relocation */
 void relocate_code_block_step(F_REL rel, CELL index, F_CODE_BLOCK *compiled)
 {
+#ifdef FACTOR_DEBUG
+       type_check(ARRAY_TYPE,compiled->literals);
+       type_check(BYTE_ARRAY_TYPE,compiled->relocation);
+#endif
+
        CELL offset = REL_OFFSET(rel) + (CELL)(compiled + 1);
        F_ARRAY *literals = untag_object(compiled->literals);
        F_FIXNUM absolute_value;
@@ -305,6 +375,9 @@ void relocate_code_block_step(F_REL rel, CELL index, F_CODE_BLOCK *compiled)
        case RT_XT:
                absolute_value = object_xt(array_nth(literals,index));
                break;
+       case RT_XT_DIRECT:
+               absolute_value = word_direct_xt(array_nth(literals,index));
+               break;
        case RT_HERE:
                absolute_value = offset + (short)to_fixnum(array_nth(literals,index));
                break;
@@ -314,6 +387,9 @@ void relocate_code_block_step(F_REL rel, CELL index, F_CODE_BLOCK *compiled)
        case RT_STACK_CHAIN:
                absolute_value = (CELL)&stack_chain;
                break;
+       case RT_UNTAGGED:
+               absolute_value = to_fixnum(array_nth(literals,index));
+               break;
        default:
                critical_error("Bad rel type",rel);
                return; /* Can't happen */
@@ -332,7 +408,7 @@ void relocate_code_block(F_CODE_BLOCK *compiled)
 }
 
 /* Fixup labels. This is done at compile time, not image load time */
-void fixup_labels(F_ARRAY *labels, CELL code_format, F_CODE_BLOCK *compiled)
+void fixup_labels(F_ARRAY *labels, F_CODE_BLOCK *compiled)
 {
        CELL i;
        CELL size = array_capacity(labels);
@@ -349,31 +425,6 @@ void fixup_labels(F_ARRAY *labels, CELL code_format, F_CODE_BLOCK *compiled)
        }
 }
 
-/* Write a sequence of integers to memory, with 'format' bytes per integer */
-void deposit_integers(CELL here, F_ARRAY *array, CELL format)
-{
-       CELL count = array_capacity(array);
-       CELL i;
-
-       for(i = 0; i < count; i++)
-       {
-               F_FIXNUM value = to_fixnum(array_nth(array,i));
-               if(format == 1)
-                       bput(here + i,value);
-               else if(format == sizeof(unsigned int))
-                       *(unsigned int *)(here + format * i) = value;
-               else if(format == sizeof(CELL))
-                       *(CELL *)(here + format * i) = value;
-               else
-                       critical_error("Bad format in deposit_integers()",format);
-       }
-}
-
-CELL compiled_code_format(void)
-{
-       return untag_fixnum_fast(userenv[JIT_CODE_FORMAT]);
-}
-
 /* Might GC */
 F_CODE_BLOCK *allot_code_block(CELL size)
 {
@@ -405,13 +456,18 @@ F_CODE_BLOCK *allot_code_block(CELL size)
 /* Might GC */
 F_CODE_BLOCK *add_code_block(
        CELL type,
-       F_ARRAY *code,
+       F_BYTE_ARRAY *code,
        F_ARRAY *labels,
        CELL relocation,
        CELL literals)
 {
-       CELL code_format = compiled_code_format();
-       CELL code_length = align8(array_capacity(code) * code_format);
+#ifdef FACTOR_DEBUG
+       type_check(ARRAY_TYPE,literals);
+       type_check(BYTE_ARRAY_TYPE,relocation);
+       assert(untag_header(code->header) == BYTE_ARRAY_TYPE);
+#endif
+
+       CELL code_length = align8(array_capacity(code));
 
        REGISTER_ROOT(literals);
        REGISTER_ROOT(relocation);
@@ -437,10 +493,10 @@ F_CODE_BLOCK *add_code_block(
        compiled->relocation = relocation;
 
        /* code */
-       deposit_integers((CELL)(compiled + 1),code,code_format);
+       memcpy(compiled + 1,code + 1,code_length);
 
        /* fixup labels */
-       if(labels) fixup_labels(labels,code_format,compiled);
+       if(labels) fixup_labels(labels,compiled);
 
        /* next time we do a minor GC, we have to scan the code heap for
        literals */
index cb8ebf5e19ea1d078aa03dcd03ed6fb0812d8232..385f414f88bf2b59f72a33a422818ba066822186 100644 (file)
@@ -5,8 +5,10 @@ typedef enum {
        RT_DLSYM,
        /* a pointer to a compiled word reference */
        RT_DISPATCH,
-       /* a compiled word reference */
+       /* a word's general entry point XT */
        RT_XT,
+       /* a word's direct entry point XT */
+       RT_XT_DIRECT,
        /* current offset */
        RT_HERE,
        /* current code block */
@@ -14,7 +16,9 @@ typedef enum {
        /* immediate literal */
        RT_IMMEDIATE,
        /* address of stack_chain var */
-       RT_STACK_CHAIN
+       RT_STACK_CHAIN,
+       /* untagged fixnum literal */
+       RT_UNTAGGED,
 } F_RELTYPE;
 
 typedef enum {
@@ -65,6 +69,8 @@ void copy_literal_references(F_CODE_BLOCK *compiled);
 
 void update_word_references(F_CODE_BLOCK *compiled);
 
+void update_literal_and_word_references(F_CODE_BLOCK *compiled);
+
 void mark_code_block(F_CODE_BLOCK *compiled);
 
 void mark_active_blocks(F_CONTEXT *stacks);
@@ -73,8 +79,6 @@ void mark_object_code_block(CELL scan);
 
 void relocate_code_block(F_CODE_BLOCK *relocating);
 
-CELL compiled_code_format(void);
-
 INLINE bool stack_traces_p(void)
 {
        return userenv[STACK_TRACES_ENV] != F;
@@ -82,7 +86,7 @@ INLINE bool stack_traces_p(void)
 
 F_CODE_BLOCK *add_code_block(
        CELL type,
-       F_ARRAY *code,
+       F_BYTE_ARRAY *code,
        F_ARRAY *labels,
        CELL relocation,
        CELL literals);
index 1405daa93fb83a5e674f0e90c747918072fcd1dd..c7ab02c6e613948b05a0b6c6bcc6be411f581d93 100755 (executable)
@@ -17,7 +17,7 @@ void new_heap(F_HEAP *heap, CELL size)
        clear_free_list(heap);
 }
 
-void add_to_free_list(F_HEAP *heap, F_FREE_BLOCK *block)
+static void add_to_free_list(F_HEAP *heap, F_FREE_BLOCK *block)
 {
        if(block->block.size < FREE_LIST_COUNT * BLOCK_SIZE_INCREMENT)
        {
@@ -94,7 +94,7 @@ static void assert_free_block(F_FREE_BLOCK *block)
                critical_error("Invalid block in free list",(CELL)block);
 }
                
-F_FREE_BLOCK *find_free_block(F_HEAP *heap, CELL size)
+static F_FREE_BLOCK *find_free_block(F_HEAP *heap, CELL size)
 {
        CELL attempt = size;
 
@@ -134,7 +134,7 @@ F_FREE_BLOCK *find_free_block(F_HEAP *heap, CELL size)
        return NULL;
 }
 
-F_FREE_BLOCK *split_free_block(F_HEAP *heap, F_FREE_BLOCK *block, CELL size)
+static F_FREE_BLOCK *split_free_block(F_HEAP *heap, F_FREE_BLOCK *block, CELL size)
 {
        if(block->block.size != size )
        {
@@ -167,6 +167,13 @@ F_BLOCK *heap_allot(F_HEAP *heap, CELL size)
                return NULL;
 }
 
+/* Deallocates a block manually */
+void heap_free(F_HEAP *heap, F_BLOCK *block)
+{
+       block->status = B_FREE;
+       add_to_free_list(heap,(F_FREE_BLOCK *)block);
+}
+
 void mark_block(F_BLOCK *block)
 {
        /* If already marked, do nothing */
@@ -212,6 +219,9 @@ void free_unmarked(F_HEAP *heap, HEAP_ITERATOR iter)
                switch(scan->status)
                {
                case B_ALLOCATED:
+                       if(secure_gc)
+                               memset(scan + 1,0,scan->size - sizeof(F_BLOCK));
+
                        if(prev && prev->status == B_FREE)
                                prev->size += scan->size;
                        else
index d71dee29c5ce85f1816ac16121ad6b46a3c2d079..35f8d66d903dd3d675913cf9821fd33cc0185b69 100755 (executable)
@@ -16,6 +16,7 @@ typedef void (*HEAP_ITERATOR)(F_BLOCK *compiled);
 void new_heap(F_HEAP *heap, CELL size);
 void build_free_list(F_HEAP *heap, CELL size);
 F_BLOCK *heap_allot(F_HEAP *heap, CELL size);
+void heap_free(F_HEAP *heap, F_BLOCK *block);
 void mark_block(F_BLOCK *block);
 void unmark_marked(F_HEAP *heap);
 void free_unmarked(F_HEAP *heap, HEAP_ITERATOR iter);
index 1901c592e65a6a98ea8370b6ba3a620922ea32b5..0a174903b68e358e9324e1bbba4f7003a6eb2f09 100755 (executable)
@@ -12,15 +12,6 @@ bool in_code_heap_p(CELL ptr)
                && ptr <= code_heap.segment->end);
 }
 
-void set_word_code(F_WORD *word, F_CODE_BLOCK *compiled)
-{
-       if(compiled->block.type != WORD_TYPE)
-               critical_error("bad param to set_word_xt",(CELL)compiled);
-
-       word->code = compiled;
-       word->optimizedp = T;
-}
-
 /* Compile a word definition with the non-optimizing compiler. Allocates memory */
 void jit_compile_word(F_WORD *word, CELL def, bool relocate)
 {
@@ -31,7 +22,9 @@ void jit_compile_word(F_WORD *word, CELL def, bool relocate)
        UNREGISTER_ROOT(def);
 
        word->code = untag_quotation(def)->code;
-       word->optimizedp = F;
+
+       if(word->direct_entry_def != F)
+               jit_compile(word->direct_entry_def,relocate);
 }
 
 /* Apply a function to every code block */
@@ -54,13 +47,6 @@ void copy_code_heap_roots(void)
        iterate_code_heap(copy_literal_references);
 }
 
-/* Update literals referenced from all code blocks. Only for tenured
-collections, done at the end. */
-void update_code_heap_roots(void)
-{
-       iterate_code_heap(update_literal_references);
-}
-
 /* Update pointers to words referenced from all code blocks. Only after
 defining a new word. */
 void update_code_heap_words(void)
@@ -97,10 +83,10 @@ void primitive_modify_code_heap(void)
                {
                        F_ARRAY *compiled_code = untag_array(data);
 
-                       F_ARRAY *literals = untag_array(array_nth(compiled_code,0));
+                       CELL literals = array_nth(compiled_code,0);
                        CELL relocation = array_nth(compiled_code,1);
                        F_ARRAY *labels = untag_array(array_nth(compiled_code,2));
-                       F_ARRAY *code = untag_array(array_nth(compiled_code,3));
+                       F_BYTE_ARRAY *code = untag_byte_array(array_nth(compiled_code,3));
 
                        REGISTER_UNTAGGED(alist);
                        REGISTER_UNTAGGED(word);
@@ -110,12 +96,12 @@ void primitive_modify_code_heap(void)
                                code,
                                labels,
                                relocation,
-                               tag_object(literals));
+                               literals);
 
                        UNREGISTER_UNTAGGED(word);
                        UNREGISTER_UNTAGGED(alist);
 
-                       set_word_code(word,compiled);
+                       word->code = compiled;
                }
                else
                        critical_error("Expected a quotation or an array",data);
index 4c5aafcddd46ba6f263f10e392ea932c5f5e05c3..01d282acfac3ae01265c1d39c1e713c3bb32a492 100755 (executable)
@@ -7,18 +7,21 @@ bool in_code_heap_p(CELL ptr);
 
 void jit_compile_word(F_WORD *word, CELL def, bool relocate);
 
-void set_word_code(F_WORD *word, F_CODE_BLOCK *compiled);
-
 typedef void (*CODE_HEAP_ITERATOR)(F_CODE_BLOCK *compiled);
 
 void iterate_code_heap(CODE_HEAP_ITERATOR iter);
 
 void copy_code_heap_roots(void);
 
-void update_code_heap_roots(void);
-
 void primitive_modify_code_heap(void);
 
 void primitive_code_room(void);
 
 void compact_code_heap(void);
+
+INLINE void check_code_pointer(CELL pointer)
+{
+#ifdef FACTOR_DEBUG
+       assert(pointer >= code_heap.segment->start && pointer < code_heap.segment->end);
+#endif
+}
index 8b3141218b0d0fb7cdf53118d71d36b9c4ad08f4..5e77c004aa7e0897413838752fac8c58479cd6ad 100755 (executable)
@@ -45,7 +45,7 @@ multiply_overflow:
        
 /* Note that the XT is passed to the quotation in r11 */
 #define CALL_OR_JUMP_QUOT \
-       lwz r11,17(r3)     /* load quotation-xt slot */ XX \
+       lwz r11,14(r3)     /* load quotation-xt slot */ XX \
 
 #define CALL_QUOT \
        CALL_OR_JUMP_QUOT XX \
index 7a8e579c6227a282e9fb684b7b537f3a6a6bacdf..3c0db3693543f352dca557aeeaea664fc3af5116 100755 (executable)
@@ -29,7 +29,8 @@ and the callstack top is passed in EDX */
        pop %ebp ; \
        pop %ebx
 
-#define QUOT_XT_OFFSET 17
+#define QUOT_XT_OFFSET 16
+#define WORD_XT_OFFSET 30
 
 /* We pass a function pointer to memcpy to work around a Mac OS X
 ABI limitation which would otherwise require us to do a bizzaro PC-relative
@@ -59,6 +60,14 @@ DEF(bool,check_sse2,(void)):
        mov %edx,%eax
        ret
 
+DEF(F_FASTCALL void,primitive_inline_cache_miss,(void)):
+       mov (%esp),%eax
+       sub $8,%esp
+       push %eax
+       call MANGLE(inline_cache_miss)
+       add $12,%esp
+       jmp *%eax
+
 #include "cpu-x86.S"
 
 #ifdef WINDOWS
index 8cf8fb9ae71ff0718761654a6f7dd9fa1bfbb8bf..a110bf1d51277fc09a9c180a58b4edf7d2ee2542 100644 (file)
@@ -61,7 +61,8 @@
 
 #endif
 
-#define QUOT_XT_OFFSET 37
+#define QUOT_XT_OFFSET 36
+#define WORD_XT_OFFSET 66
 
 /* We pass a function pointer to memcpy to work around a Mac OS X
 ABI limitation which would otherwise require us to do a bizzaro PC-relative
@@ -72,4 +73,11 @@ DEF(void,set_callstack,(F_STACK_FRAME *to, F_STACK_FRAME *from, CELL length, voi
        call *ARG3                         /* call memcpy */
        ret                                /* return _with new stack_ */
 
+DEF(F_FASTCALL void,primitive_inline_cache_miss,(void)):
+       mov (%rsp),ARG0
+       sub $STACK_PADDING,%rsp
+       call MANGLE(inline_cache_miss)
+       add $STACK_PADDING,%rsp
+       jmp *%rax
+
 #include "cpu-x86.S"
index 7a0d738fe063b279fbd66ed66a9f14507afbdee5..e83bb0fd7d97e9ab2860dec5086fe933fa7df8a5 100755 (executable)
@@ -60,7 +60,7 @@ DEF(F_FASTCALL void,throw_impl,(CELL quot, F_STACK_FRAME *rewind_to)):
        mov ARG1,STACK_REG                    
        jmp *QUOT_XT_OFFSET(ARG0)
 
-DEF(FASTCALL void,lazy_jit_compile,(CELL quot)):
+DEF(F_FASTCALL void,lazy_jit_compile,(CELL quot)):
        mov STACK_REG,ARG1           /* Save stack pointer */
        sub $STACK_PADDING,STACK_REG
        call MANGLE(lazy_jit_compile_impl)
index 3b08479e4b0e2dd417d7a451922ddc7d159920ef..0888ec57fddc24d9962f80d8148a4826a36f4b8c 100755 (executable)
@@ -1,3 +1,5 @@
+#include <assert.h>
+
 #define FRAME_RETURN_ADDRESS(frame) *(XT *)(frame_successor(frame) + 1)
 
 INLINE void flush_icache(CELL start, CELL len) {}
@@ -7,3 +9,27 @@ F_FASTCALL void throw_impl(CELL quot, F_STACK_FRAME *rewind_to);
 F_FASTCALL void lazy_jit_compile(CELL quot);
 
 void set_callstack(F_STACK_FRAME *to, F_STACK_FRAME *from, CELL length, void *memcpy);
+
+INLINE void check_call_site(CELL return_address)
+{
+       /* An x86 CALL instruction looks like so:
+          |e8|..|..|..|..|
+          where the ... are a PC-relative jump address.
+          The return_address points to right after the
+          instruction. */
+#ifdef FACTOR_DEBUG
+       assert(*(unsigned char *)(return_address - 5) == 0xe8);
+#endif
+}
+
+INLINE CELL get_call_target(CELL return_address)
+{
+       check_call_site(return_address);
+       return *(int *)(return_address - 4) + return_address;
+}
+
+INLINE void set_call_target(CELL return_address, CELL target)
+{
+       check_call_site(return_address);
+       *(int *)(return_address - 4) = (target - return_address);
+}
index a1a86e7789c27d90119025c9578691b0f1cad1ee..1662fc9a4da5db60ec82a8ffeb20a3c8f7be123a 100755 (executable)
@@ -211,6 +211,8 @@ INLINE CELL copy_object_impl(CELL pointer)
 /* Follow a chain of forwarding pointers */
 CELL resolve_forwarding(CELL untagged, CELL tag)
 {
+       check_data_pointer(untagged);
+
        CELL header = get(untagged);
        /* another forwarding pointer */
        if(TAG(header) == GC_COLLECTED)
@@ -218,6 +220,7 @@ CELL resolve_forwarding(CELL untagged, CELL tag)
        /* we've found the destination */
        else
        {
+               check_header(header);
                CELL pointer = RETAG(untagged,tag);
                if(should_copy(untagged))
                        pointer = RETAG(copy_object_impl(pointer),tag);
@@ -231,21 +234,30 @@ pointer address without copying anything; otherwise, install
 a new forwarding pointer. */
 INLINE CELL copy_object(CELL pointer)
 {
+       check_data_pointer(pointer);
+
        CELL tag = TAG(pointer);
        CELL header = get(UNTAG(pointer));
 
        if(TAG(header) == GC_COLLECTED)
                return resolve_forwarding(UNTAG(header),tag);
        else
+       {
+               check_header(header);
                return RETAG(copy_object_impl(pointer),tag);
+       }
 }
 
 void copy_handle(CELL *handle)
 {
        CELL pointer = *handle;
 
-       if(!immediate_p(pointer) && should_copy(pointer))
-               *handle = copy_object(pointer);
+       if(!immediate_p(pointer))
+       {
+               check_data_pointer(pointer);
+               if(should_copy(pointer))
+                       *handle = copy_object(pointer);
+       }
 }
 
 CELL copy_next_from_nursery(CELL scan)
@@ -264,9 +276,12 @@ CELL copy_next_from_nursery(CELL scan)
                {
                        CELL pointer = *obj;
 
-                       if(!immediate_p(pointer)
-                               && (pointer >= nursery_start && pointer < nursery_end))
-                               *obj = copy_object(pointer);
+                       if(!immediate_p(pointer))
+                       {
+                               check_data_pointer(pointer);
+                               if(pointer >= nursery_start && pointer < nursery_end)
+                                       *obj = copy_object(pointer);
+                       }
                }
        }
 
@@ -292,10 +307,13 @@ CELL copy_next_from_aging(CELL scan)
                {
                        CELL pointer = *obj;
 
-                       if(!immediate_p(pointer)
-                               && !(pointer >= newspace_start && pointer < newspace_end)
-                               && !(pointer >= tenured_start && pointer < tenured_end))
-                               *obj = copy_object(pointer);
+                       if(!immediate_p(pointer))
+                       {
+                               check_data_pointer(pointer);
+                               if(!(pointer >= newspace_start && pointer < newspace_end)
+                                  && !(pointer >= tenured_start && pointer < tenured_end))
+                                       *obj = copy_object(pointer);
+                       }
                }
        }
 
@@ -318,8 +336,12 @@ CELL copy_next_from_tenured(CELL scan)
                {
                        CELL pointer = *obj;
 
-                       if(!immediate_p(pointer) && !(pointer >= newspace_start && pointer < newspace_end))
-                               *obj = copy_object(pointer);
+                       if(!immediate_p(pointer))
+                       {
+                               check_data_pointer(pointer);
+                               if(!(pointer >= newspace_start && pointer < newspace_end))
+                                       *obj = copy_object(pointer);
+                       }
                }
        }
 
@@ -474,6 +496,7 @@ void garbage_collection(CELL gen,
        copy_roots();
        /* collect objects referenced from older generations */
        copy_cards();
+
        /* do some tracing */
        copy_reachable_objects(scan,&newspace->here);
 
@@ -484,7 +507,7 @@ void garbage_collection(CELL gen,
                code_heap_scans++;
 
                if(collecting_gen == TENURED)
-                       free_unmarked(&code_heap,(HEAP_ITERATOR)update_literal_references);
+                       free_unmarked(&code_heap,(HEAP_ITERATOR)update_literal_and_word_references);
                else
                        copy_code_heap_roots();
 
@@ -543,6 +566,7 @@ void primitive_gc_stats(void)
        GROWABLE_ARRAY_ADD(stats,allot_cell(code_heap_scans));
 
        GROWABLE_ARRAY_TRIM(stats);
+       GROWABLE_ARRAY_DONE(stats);
        dpush(stats);
 }
 
index afa45c5522e38a1003d26156bd2a03c3b002b280..50f87ce0bede979076eeb89495cf7ec7cb0ccafb 100755 (executable)
@@ -80,21 +80,20 @@ registers) does not run out of memory */
 
 /* If this is defined, we GC every 100 allocations. This catches missing local roots */
 #ifdef GC_DEBUG
-static int count;
+int gc_count;
 #endif
 
 /*
  * It is up to the caller to fill in the object's fields in a meaningful
  * fashion!
  */
+int count;
 INLINE void *allot_object(CELL type, CELL a)
 {
-
 #ifdef GC_DEBUG
-
        if(!gc_off)
        {
-               if(count++ % 1000 == 0)
+               if(gc_count++ % 100 == 0)
                        gc();
 
        }
@@ -154,3 +153,14 @@ void primitive_gc_stats(void);
 void clear_gc_stats(void);
 void primitive_clear_gc_stats(void);
 void primitive_become(void);
+
+INLINE void check_data_pointer(CELL pointer)
+{
+#ifdef FACTOR_DEBUG
+       if(!growing_data_heap)
+       {
+               assert(pointer >= data_heap->segment->start
+                      && pointer < data_heap->segment->end);
+       }
+#endif
+}
index c5aa42aebed5e4eb295fbbe85f5a6b167a1e5321..cab9114089808b590ea8e9bb73bd86dcca3014a1 100644 (file)
@@ -216,12 +216,8 @@ CELL unaligned_object_size(CELL pointer)
                return sizeof(F_QUOTATION);
        case WORD_TYPE:
                return sizeof(F_WORD);
-       case RATIO_TYPE:
-               return sizeof(F_RATIO);
        case FLOAT_TYPE:
                return sizeof(F_FLOAT);
-       case COMPLEX_TYPE:
-               return sizeof(F_COMPLEX);
        case DLL_TYPE:
                return sizeof(F_DLL);
        case ALIEN_TYPE:
@@ -276,10 +272,6 @@ CELL binary_payload_start(CELL pointer)
                tuple = untag_object(pointer);
                layout = untag_object(tuple->layout);
                return tuple_size(layout);
-       case RATIO_TYPE:
-               return sizeof(F_RATIO);
-       case COMPLEX_TYPE:
-               return sizeof(F_COMPLEX);
        case WRAPPER_TYPE:
                return sizeof(F_WRAPPER);
        default:
@@ -291,20 +283,22 @@ CELL binary_payload_start(CELL pointer)
 /* Push memory usage statistics in data heap */
 void primitive_data_room(void)
 {
-       F_ARRAY *a = allot_array(ARRAY_TYPE,data_heap->gen_count * 2,F);
-       int gen;
-
        dpush(tag_fixnum((data_heap->cards_end - data_heap->cards) >> 10));
        dpush(tag_fixnum((data_heap->decks_end - data_heap->decks) >> 10));
 
+       GROWABLE_ARRAY(a);
+
+       int gen;
        for(gen = 0; gen < data_heap->gen_count; gen++)
        {
                F_ZONE *z = (gen == NURSERY ? &nursery : &data_heap->generations[gen]);
-               set_array_nth(a,gen * 2,tag_fixnum((z->end - z->here) >> 10));
-               set_array_nth(a,gen * 2 + 1,tag_fixnum((z->size) >> 10));
+               GROWABLE_ARRAY_ADD(a,tag_fixnum((z->end - z->here) >> 10));
+               GROWABLE_ARRAY_ADD(a,tag_fixnum((z->size) >> 10));
        }
 
-       dpush(tag_object(a));
+       GROWABLE_ARRAY_TRIM(a);
+       GROWABLE_ARRAY_DONE(a);
+       dpush(a);
 }
 
 /* Disables GC and activates next-object ( -- obj ) primitive */
@@ -334,7 +328,7 @@ CELL next_object(void)
        type = untag_header(value);
        heap_scan_ptr += untagged_object_size(heap_scan_ptr);
 
-       return RETAG(obj,type <= HEADER_TYPE ? type : OBJECT_TYPE);
+       return RETAG(obj,type < HEADER_TYPE ? type : OBJECT_TYPE);
 }
 
 /* Push object at heap scan cursor and advance; pushes f when done */
@@ -366,6 +360,7 @@ CELL find_all_words(void)
        gc_off = false;
 
        GROWABLE_ARRAY_TRIM(words);
+       GROWABLE_ARRAY_DONE(words);
 
        return words;
 }
index 583696729573223c5bcd49ed2ca8046dd489eafa..4a86367208ef40a28c1e82da5d2b65f116d20665 100644 (file)
@@ -135,3 +135,4 @@ INLINE void do_slots(CELL obj, void (* iter)(CELL *))
                scan += CELLS;
        }
 }
+
index 6f7e883785f092f4befba49cdf1271d10b01350c..a9afd2c3c0754042a8a3dcc62987bb8ebd2a1544 100755 (executable)
@@ -414,7 +414,7 @@ void factorbug(void)
                if(strcmp(cmd,"d") == 0)
                {
                        CELL addr = read_cell_hex();
-                       scanf(" ");
+                       if(scanf(" ") < 0) break;
                        CELL count = read_cell_hex();
                        dump_memory(addr,addr+count);
                }
diff --git a/vm/dispatch.c b/vm/dispatch.c
new file mode 100644 (file)
index 0000000..68ef192
--- /dev/null
@@ -0,0 +1,202 @@
+#include "master.h"
+
+static CELL search_lookup_alist(CELL table, CELL class)
+{
+       F_ARRAY *pairs = untag_object(table);
+       F_FIXNUM index = array_capacity(pairs) - 1;
+       while(index >= 0)
+       {
+               F_ARRAY *pair = untag_object(array_nth(pairs,index));
+               if(array_nth(pair,0) == class)
+                       return array_nth(pair,1);
+               else
+                       index--;
+       }
+
+       return F;
+}
+
+static CELL search_lookup_hash(CELL table, CELL class, CELL hashcode)
+{
+       F_ARRAY *buckets = untag_object(table);
+       CELL bucket = array_nth(buckets,hashcode & (array_capacity(buckets) - 1));
+       if(type_of(bucket) == WORD_TYPE || bucket == F)
+               return bucket;
+       else
+               return search_lookup_alist(bucket,class);
+}
+
+static CELL nth_superclass(F_TUPLE_LAYOUT *layout, F_FIXNUM echelon)
+{
+       CELL *ptr = (CELL *)(layout + 1);
+       return ptr[echelon * 2];
+}
+
+static CELL nth_hashcode(F_TUPLE_LAYOUT *layout, F_FIXNUM echelon)
+{
+       CELL *ptr = (CELL *)(layout + 1);
+       return ptr[echelon * 2 + 1];
+}
+
+static CELL lookup_tuple_method(CELL object, CELL methods)
+{
+       F_TUPLE *tuple = untag_object(object);
+       F_TUPLE_LAYOUT *layout = untag_object(tuple->layout);
+
+       F_ARRAY *echelons = untag_object(methods);
+
+       F_FIXNUM echelon = untag_fixnum_fast(layout->echelon);
+       F_FIXNUM max_echelon = array_capacity(echelons) - 1;
+       if(echelon > max_echelon) echelon = max_echelon;
+       
+       while(echelon >= 0)
+       {
+               CELL echelon_methods = array_nth(echelons,echelon);
+
+               if(type_of(echelon_methods) == WORD_TYPE)
+                       return echelon_methods;
+               else if(echelon_methods != F)
+               {
+                       CELL class = nth_superclass(layout,echelon);
+                       CELL hashcode = untag_fixnum_fast(nth_hashcode(layout,echelon));
+                       CELL result = search_lookup_hash(echelon_methods,class,hashcode);
+                       if(result != F)
+                               return result;
+               }
+
+               echelon--;
+       }
+
+       critical_error("Cannot find tuple method",methods);
+       return F;
+}
+
+static CELL lookup_hi_tag_method(CELL object, CELL methods)
+{
+       F_ARRAY *hi_tag_methods = untag_object(methods);
+       CELL tag = hi_tag(object) - HEADER_TYPE;
+#ifdef FACTOR_DEBUG
+       assert(tag < TYPE_COUNT - HEADER_TYPE);
+#endif
+       return array_nth(hi_tag_methods,tag);
+}
+
+static CELL lookup_hairy_method(CELL object, CELL methods)
+{
+       CELL method = array_nth(untag_object(methods),TAG(object));
+       if(type_of(method) == WORD_TYPE)
+               return method;
+       else
+       {
+               switch(TAG(object))
+               {
+               case TUPLE_TYPE:
+                       return lookup_tuple_method(object,method);
+                       break;
+               case OBJECT_TYPE:
+                       return lookup_hi_tag_method(object,method);
+                       break;
+               default:
+                       critical_error("Bad methods array",methods);
+                       return -1;
+               }
+       }
+}
+
+CELL lookup_method(CELL object, CELL methods)
+{
+       if(!HI_TAG_OR_TUPLE_P(object))
+               return array_nth(untag_object(methods),TAG(object));
+       else
+               return lookup_hairy_method(object,methods);
+}
+
+void primitive_lookup_method(void)
+{
+       CELL methods = dpop();
+       CELL object = dpop();
+       dpush(lookup_method(object,methods));
+}
+
+CELL object_class(CELL object)
+{
+       if(!HI_TAG_OR_TUPLE_P(object))
+               return tag_fixnum(TAG(object));
+       else
+               return get(HI_TAG_HEADER(object));
+}
+
+static CELL method_cache_hashcode(CELL class, F_ARRAY *array)
+{
+       CELL capacity = (array_capacity(array) >> 1) - 1;
+       return ((class >> TAG_BITS) & capacity) << 1;
+}
+
+static void update_method_cache(CELL cache, CELL class, CELL method)
+{
+       F_ARRAY *array = untag_object(cache);
+       CELL hashcode = method_cache_hashcode(class,array);
+       set_array_nth(array,hashcode,class);
+       set_array_nth(array,hashcode + 1,method);
+}
+
+void primitive_mega_cache_miss(void)
+{
+       megamorphic_cache_misses++;
+
+       CELL cache = dpop();
+       F_FIXNUM index = untag_fixnum_fast(dpop());
+       CELL methods = dpop();
+
+       CELL object = get(ds - index * CELLS);
+       CELL class = object_class(object);
+       CELL method = lookup_method(object,methods);
+
+       update_method_cache(cache,class,method);
+
+       dpush(method);
+}
+
+void primitive_reset_dispatch_stats(void)
+{
+       megamorphic_cache_hits = megamorphic_cache_misses = 0;
+}
+
+void primitive_dispatch_stats(void)
+{
+       GROWABLE_ARRAY(stats);
+       GROWABLE_ARRAY_ADD(stats,allot_cell(megamorphic_cache_hits));
+       GROWABLE_ARRAY_ADD(stats,allot_cell(megamorphic_cache_misses));
+       GROWABLE_ARRAY_TRIM(stats);
+       GROWABLE_ARRAY_DONE(stats);
+       dpush(stats);
+}
+
+void jit_emit_class_lookup(F_JIT *jit, F_FIXNUM index, CELL type)
+{
+       jit_emit_with(jit,userenv[PIC_LOAD],tag_fixnum(-index * CELLS));
+       jit_emit(jit,userenv[type]);
+}
+
+void jit_emit_mega_cache_lookup(F_JIT *jit, CELL methods, F_FIXNUM index, CELL cache)
+{
+       /* Generate machine code to determine the object's class. */
+       jit_emit_class_lookup(jit,index,PIC_HI_TAG_TUPLE);
+
+       /* Do a cache lookup. */
+       jit_emit_with(jit,userenv[MEGA_LOOKUP],cache);
+       
+       /* If we end up here, the cache missed. */
+       jit_emit(jit,userenv[JIT_PROLOG]);
+
+       /* Push index, method table and cache on the stack. */
+       jit_push(jit,methods);
+       jit_push(jit,tag_fixnum(index));
+       jit_push(jit,cache);
+       jit_word_call(jit,userenv[MEGA_MISS_WORD]);
+
+       /* Now the new method has been stored into the cache, and its on
+          the stack. */
+       jit_emit(jit,userenv[JIT_EPILOG]);
+       jit_emit(jit,userenv[JIT_EXECUTE_JUMP]);
+}
diff --git a/vm/dispatch.h b/vm/dispatch.h
new file mode 100644 (file)
index 0000000..1aac242
--- /dev/null
@@ -0,0 +1,16 @@
+CELL megamorphic_cache_hits;
+CELL megamorphic_cache_misses;
+
+CELL lookup_method(CELL object, CELL methods);
+void primitive_lookup_method(void);
+
+CELL object_class(CELL object);
+
+void primitive_mega_cache_miss(void);
+
+void primitive_reset_dispatch_stats(void);
+void primitive_dispatch_stats(void);
+
+void jit_emit_class_lookup(F_JIT *jit, F_FIXNUM index, CELL type);
+
+void jit_emit_mega_cache_lookup(F_JIT *jit, CELL methods, F_FIXNUM index, CELL cache);
index 9b5d3de6020bce406b977b227e72c31c56cdfa27..0a652f7aabc6caa922a5637d65b00fb3e9f51670 100755 (executable)
@@ -26,6 +26,8 @@ void default_parameters(F_PARAMETERS *p)
        p->tenured_size = 4 * CELLS;
 #endif
 
+       p->max_pic_size = 3;
+
        p->secure_gc = false;
        p->fep = false;
 
@@ -66,6 +68,7 @@ void init_parameters_from_args(F_PARAMETERS *p, int argc, F_CHAR **argv)
                else if(factor_arg(argv[i],STRING_LITERAL("-aging=%d"),&p->aging_size));
                else if(factor_arg(argv[i],STRING_LITERAL("-tenured=%d"),&p->tenured_size));
                else if(factor_arg(argv[i],STRING_LITERAL("-codeheap=%d"),&p->code_size));
+               else if(factor_arg(argv[i],STRING_LITERAL("-pic=%d"),&p->max_pic_size));
                else if(STRCMP(argv[i],STRING_LITERAL("-securegc")) == 0) p->secure_gc = true;
                else if(STRCMP(argv[i],STRING_LITERAL("-fep")) == 0) p->fep = true;
                else if(STRNCMP(argv[i],STRING_LITERAL("-i="),3) == 0) p->image_path = argv[i] + 3;
@@ -118,7 +121,11 @@ void init_factor(F_PARAMETERS *p)
        init_stacks(p->ds_size,p->rs_size);
        load_image(p);
        init_c_io();
+       init_inline_caching(p->max_pic_size);
+
+#ifndef FACTOR_DEBUG
        init_signals();
+#endif
 
        if(p->console)
                open_console();
@@ -160,7 +167,7 @@ void pass_args_to_factor(int argc, F_CHAR **argv)
                set_array_nth(args,i,arg);
        }
 
-       userenv[ARGS_ENV] = tag_object(args);
+       userenv[ARGS_ENV] = tag_array(args);
 }
 
 void start_factor(F_PARAMETERS *p)
index 9cc97df0d94db5eaad9dc34d1f8cb97d98943f4e..d7bf0355142b249d929f95185226e24509076f51 100755 (executable)
@@ -183,7 +183,7 @@ void primitive_save_image_and_exit(void)
        for(i = 0; i < FIRST_SAVE_ENV; i++)
                userenv[i] = F;
 
-       for(i = LAST_SAVE_ENV + 1; i < USER_ENV; i++)
+       for(i = LAST_SAVE_ENV + 1; i < STACK_TRACES_ENV; i++)
                userenv[i] = F;
 
        /* do a full GC + code heap compaction */
index e26a6bb5b4730bb86c21a2761c80ef0d43bbd5a4..de5b55f0afc2fbf1125c21a0ed8fa9232e3dc5b1 100755 (executable)
@@ -35,6 +35,7 @@ typedef struct {
        bool fep;
        bool console;
        bool stack_traces;
+       CELL max_pic_size;
 } F_PARAMETERS;
 
 void load_image(F_PARAMETERS *p);
diff --git a/vm/inline_cache.c b/vm/inline_cache.c
new file mode 100644 (file)
index 0000000..83981d2
--- /dev/null
@@ -0,0 +1,248 @@
+#include "master.h"
+
+void init_inline_caching(int max_size)
+{
+       max_pic_size = max_size;
+}
+
+void deallocate_inline_cache(CELL return_address)
+{
+       /* Find the call target. */
+       XT old_xt = (XT)get_call_target(return_address);
+       F_CODE_BLOCK *old_block = (F_CODE_BLOCK *)old_xt - 1;
+       CELL old_type = old_block->block.type;
+
+#ifdef FACTOR_DEBUG
+       /* The call target was either another PIC,
+          or a compiled quotation (megamorphic stub) */
+       assert(old_type == PIC_TYPE || old_type == QUOTATION_TYPE);
+#endif
+
+       if(old_type == PIC_TYPE)
+               heap_free(&code_heap,&old_block->block);
+}
+
+/* Figure out what kind of type check the PIC needs based on the methods
+it contains */
+static CELL determine_inline_cache_type(CELL cache_entries)
+{
+       F_ARRAY *array = untag_object(cache_entries);
+
+       bool  seen_hi_tag = false, seen_tuple = false;
+
+       CELL i;
+       for(i = 0; i < array_capacity(array); i += 2)
+       {
+               CELL class = array_nth(array,i);
+               F_FIXNUM type;
+
+               /* Is it a tuple layout? */
+               switch(type_of(class))
+               {
+               case FIXNUM_TYPE:
+                       type = untag_fixnum_fast(class);
+                       if(type >= HEADER_TYPE)
+                               seen_hi_tag = true;
+                       break;
+               case ARRAY_TYPE:
+                       seen_tuple = true;
+                       break;
+               default:
+                       critical_error("Expected a fixnum or array",class);
+                       break;
+               }
+       }
+
+       if(seen_hi_tag && seen_tuple) return PIC_HI_TAG_TUPLE;
+       if(seen_hi_tag && !seen_tuple) return PIC_HI_TAG;
+       if(!seen_hi_tag && seen_tuple) return PIC_TUPLE;
+       if(!seen_hi_tag && !seen_tuple) return PIC_TAG;
+
+       critical_error("Oops",0);
+       return -1;
+}
+
+static void update_pic_count(CELL type)
+{
+       pic_counts[type - PIC_TAG]++;
+}
+
+static void jit_emit_check(F_JIT *jit, CELL class)
+{
+       CELL template;
+       if(TAG(class) == FIXNUM_TYPE && untag_fixnum_fast(class) < HEADER_TYPE)
+               template = userenv[PIC_CHECK_TAG];
+       else
+               template = userenv[PIC_CHECK];
+
+       jit_emit_with(jit,template,class);
+}
+
+/* index: 0 = top of stack, 1 = item underneath, etc
+   cache_entries: array of class/method pairs */
+static F_CODE_BLOCK *compile_inline_cache(F_FIXNUM index, CELL generic_word, CELL methods, CELL cache_entries)
+{
+#ifdef FACTOR_DEBUG
+       type_check(WORD_TYPE,generic_word);
+       type_check(ARRAY_TYPE,cache_entries);
+#endif
+
+       REGISTER_ROOT(generic_word);
+       REGISTER_ROOT(methods);
+       REGISTER_ROOT(cache_entries);
+
+       CELL inline_cache_type = determine_inline_cache_type(cache_entries);
+
+       update_pic_count(inline_cache_type);
+
+       F_JIT jit;
+       jit_init(&jit,PIC_TYPE,generic_word);
+
+       /* Generate machine code to determine the object's class. */
+       jit_emit_class_lookup(&jit,index,inline_cache_type);
+
+       /* Generate machine code to check, in turn, if the class is one of the cached entries. */
+       CELL i;
+       for(i = 0; i < array_capacity(untag_object(cache_entries)); i += 2)
+       {
+               /* Class equal? */
+               CELL class = array_nth(untag_object(cache_entries),i);
+               jit_emit_check(&jit,class);
+
+               /* Yes? Jump to method */
+               CELL method = array_nth(untag_object(cache_entries),i + 1);
+               jit_emit_with(&jit,userenv[PIC_HIT],method);
+       }
+
+       /* Generate machine code to handle a cache miss, which ultimately results in
+          this function being called again.
+
+          The inline-cache-miss primitive call receives enough information to
+          reconstruct the PIC. */
+       jit_push(&jit,generic_word);
+       jit_push(&jit,methods);
+       jit_push(&jit,tag_fixnum(index));
+       jit_push(&jit,cache_entries);
+       jit_word_jump(&jit,userenv[PIC_MISS_WORD]);
+
+       F_CODE_BLOCK *code = jit_make_code_block(&jit);
+       relocate_code_block(code);
+
+       jit_dispose(&jit);
+
+       UNREGISTER_ROOT(cache_entries);
+       UNREGISTER_ROOT(methods);
+       UNREGISTER_ROOT(generic_word);
+
+       return code;
+}
+
+/* A generic word's definition performs general method lookup. Allocates memory */
+static XT megamorphic_call_stub(CELL generic_word)
+{
+       return untag_word(generic_word)->xt;
+}
+
+static CELL inline_cache_size(CELL cache_entries)
+{
+       return (cache_entries == F ? 0 : array_capacity(untag_array(cache_entries)) / 2);
+}
+
+/* Allocates memory */
+static CELL add_inline_cache_entry(CELL cache_entries, CELL class, CELL method)
+{
+       if(cache_entries == F)
+               return allot_array_2(class,method);
+       else
+       {
+               F_ARRAY *cache_entries_array = untag_object(cache_entries);
+               CELL pic_size = array_capacity(cache_entries_array);
+               cache_entries_array = reallot_array(cache_entries_array,pic_size + 2);
+               set_array_nth(cache_entries_array,pic_size,class);
+               set_array_nth(cache_entries_array,pic_size + 1,method);
+               return tag_array(cache_entries_array);
+       }
+}
+
+static void update_pic_transitions(CELL pic_size)
+{
+       if(pic_size == max_pic_size)
+               pic_to_mega_transitions++;
+       else if(pic_size == 0)
+               cold_call_to_ic_transitions++;
+       else if(pic_size == 1)
+               ic_to_pic_transitions++;
+}
+
+/* The cache_entries parameter is either f (on cold call site) or an array (on cache miss).
+Called from assembly with the actual return address */
+XT inline_cache_miss(CELL return_address)
+{
+       check_code_pointer(return_address);
+
+       /* Since each PIC is only referenced from a single call site,
+          if the old call target was a PIC, we can deallocate it immediately,
+          instead of leaving dead PICs around until the next GC. */
+       deallocate_inline_cache(return_address);
+
+       CELL cache_entries = dpop();
+       F_FIXNUM index = untag_fixnum_fast(dpop());
+       CELL methods = dpop();
+       CELL generic_word = dpop();
+       CELL object = get(ds - index * CELLS);
+
+       XT xt;
+
+       CELL pic_size = inline_cache_size(cache_entries);
+
+       update_pic_transitions(pic_size);
+
+       if(pic_size >= max_pic_size)
+               xt = megamorphic_call_stub(generic_word);
+       else
+       {
+               REGISTER_ROOT(generic_word);
+               REGISTER_ROOT(cache_entries);
+               REGISTER_ROOT(methods);
+
+               CELL class = object_class(object);
+               CELL method = lookup_method(object,methods);
+
+               cache_entries = add_inline_cache_entry(cache_entries,class,method);
+               xt = compile_inline_cache(index,generic_word,methods,cache_entries) + 1;
+
+               UNREGISTER_ROOT(methods);
+               UNREGISTER_ROOT(cache_entries);
+               UNREGISTER_ROOT(generic_word);
+       }
+
+       /* Install the new stub. */
+       set_call_target(return_address,(CELL)xt);
+
+#ifdef PIC_DEBUG
+       printf("Updated call site 0x%lx with 0x%lx\n",return_address,(CELL)xt);
+#endif
+
+       return xt;
+}
+
+void primitive_reset_inline_cache_stats(void)
+{
+       cold_call_to_ic_transitions = ic_to_pic_transitions = pic_to_mega_transitions = 0;
+       CELL i;
+       for(i = 0; i < 4; i++) pic_counts[i] = 0;
+}
+
+void primitive_inline_cache_stats(void)
+{
+       GROWABLE_ARRAY(stats);
+       GROWABLE_ARRAY_ADD(stats,allot_cell(cold_call_to_ic_transitions));
+       GROWABLE_ARRAY_ADD(stats,allot_cell(ic_to_pic_transitions));
+       GROWABLE_ARRAY_ADD(stats,allot_cell(pic_to_mega_transitions));
+       CELL i;
+       for(i = 0; i < 4; i++)
+               GROWABLE_ARRAY_ADD(stats,allot_cell(pic_counts[i]));
+       GROWABLE_ARRAY_TRIM(stats);
+       GROWABLE_ARRAY_DONE(stats);
+       dpush(stats);
+}
diff --git a/vm/inline_cache.h b/vm/inline_cache.h
new file mode 100644 (file)
index 0000000..83f2644
--- /dev/null
@@ -0,0 +1,17 @@
+CELL max_pic_size;
+
+CELL cold_call_to_ic_transitions;
+CELL ic_to_pic_transitions;
+CELL pic_to_mega_transitions;
+
+/* PIC_TAG, PIC_HI_TAG, PIC_TUPLE, PIC_HI_TAG_TUPLE */
+CELL pic_counts[4];
+
+void init_inline_caching(int max_size);
+
+void primitive_inline_cache_miss(void);
+
+XT inline_cache_miss(CELL return_address);
+
+void primitive_reset_inline_cache_stats(void);
+void primitive_inline_cache_stats(void);
diff --git a/vm/jit.c b/vm/jit.c
new file mode 100644 (file)
index 0000000..8d7dcd6
--- /dev/null
+++ b/vm/jit.c
@@ -0,0 +1,119 @@
+#include "master.h"
+
+/* Simple code generator used by:
+- profiler (profiler.c),
+- quotation compiler (quotations.c),
+- megamorphic caches (dispatch.c),
+- polymorphic inline caches (inline_cache.c) */
+
+/* Allocates memory */
+void jit_init(F_JIT *jit, CELL jit_type, CELL owner)
+{
+       jit->owner = owner;
+       REGISTER_ROOT(jit->owner);
+
+       jit->type = jit_type;
+
+       jit->code = make_growable_byte_array();
+       REGISTER_ROOT(jit->code.array);
+       jit->relocation = make_growable_byte_array();
+       REGISTER_ROOT(jit->relocation.array);
+       jit->literals = make_growable_array();
+       REGISTER_ROOT(jit->literals.array);
+
+       if(stack_traces_p())
+               growable_array_add(&jit->literals,jit->owner);
+
+       jit->computing_offset_p = false;
+}
+
+/* Facility to convert compiled code offsets to quotation offsets.
+Call jit_compute_offset() with the compiled code offset, then emit
+code, and at the end jit->position is the quotation position. */
+void jit_compute_position(F_JIT *jit, CELL offset)
+{
+       jit->computing_offset_p = true;
+       jit->position = 0;
+       jit->offset = offset;
+}
+
+/* Allocates memory */
+F_CODE_BLOCK *jit_make_code_block(F_JIT *jit)
+{
+       growable_byte_array_trim(&jit->code);
+       growable_byte_array_trim(&jit->relocation);
+       growable_array_trim(&jit->literals);
+
+       F_CODE_BLOCK *code = add_code_block(
+               jit->type,
+               untag_object(jit->code.array),
+               NULL, /* no labels */
+               jit->relocation.array,
+               jit->literals.array);
+
+       return code;
+}
+
+void jit_dispose(F_JIT *jit)
+{
+       UNREGISTER_ROOT(jit->literals.array);
+       UNREGISTER_ROOT(jit->relocation.array);
+       UNREGISTER_ROOT(jit->code.array);
+       UNREGISTER_ROOT(jit->owner);
+}
+
+static F_REL rel_to_emit(F_JIT *jit, CELL template, bool *rel_p)
+{
+       F_ARRAY *quadruple = untag_object(template);
+       CELL rel_class = array_nth(quadruple,1);
+       CELL rel_type = array_nth(quadruple,2);
+       CELL offset = array_nth(quadruple,3);
+
+       if(rel_class == F)
+       {
+               *rel_p = false;
+               return 0;
+       }
+       else
+       {
+               *rel_p = true;
+               return (untag_fixnum_fast(rel_type) << 28)
+                       | (untag_fixnum_fast(rel_class) << 24)
+                       | ((jit->code.count + untag_fixnum_fast(offset)));
+       }
+}
+
+/* Allocates memory */
+void jit_emit(F_JIT *jit, CELL template)
+{
+       REGISTER_ROOT(template);
+
+       bool rel_p;
+       F_REL rel = rel_to_emit(jit,template,&rel_p);
+       if(rel_p) growable_byte_array_append(&jit->relocation,&rel,sizeof(F_REL));
+
+       F_BYTE_ARRAY *code = code_to_emit(template);
+
+       if(jit->computing_offset_p)
+       {
+               CELL size = array_capacity(code);
+
+               if(jit->offset == 0)
+               {
+                       jit->position--;
+                       jit->computing_offset_p = false;
+               }
+               else if(jit->offset < size)
+               {
+                       jit->position++;
+                       jit->computing_offset_p = false;
+               }
+               else
+                       jit->offset -= size;
+       }
+
+       growable_byte_array_append(&jit->code,code + 1,array_capacity(code));
+
+       UNREGISTER_ROOT(template);
+}
+
diff --git a/vm/jit.h b/vm/jit.h
new file mode 100644 (file)
index 0000000..4ea72ee
--- /dev/null
+++ b/vm/jit.h
@@ -0,0 +1,87 @@
+typedef struct {
+       CELL type;
+       CELL owner;
+       F_GROWABLE_BYTE_ARRAY code;
+       F_GROWABLE_BYTE_ARRAY relocation;
+       F_GROWABLE_ARRAY literals;
+       bool computing_offset_p;
+       F_FIXNUM position;
+       CELL offset;
+} F_JIT;
+
+void jit_init(F_JIT *jit, CELL jit_type, CELL owner);
+
+void jit_compute_position(F_JIT *jit, CELL offset);
+
+F_CODE_BLOCK *jit_make_code_block(F_JIT *jit);
+
+void jit_dispose(F_JIT *jit);
+
+INLINE F_BYTE_ARRAY *code_to_emit(CELL template)
+{
+       return untag_object(array_nth(untag_object(template),0));
+}
+
+void jit_emit(F_JIT *jit, CELL template);
+
+/* Allocates memory */
+INLINE void jit_add_literal(F_JIT *jit, CELL literal)
+{
+       growable_array_add(&jit->literals,literal);
+}
+
+/* Allocates memory */
+INLINE void jit_emit_with(F_JIT *jit, CELL template, CELL argument)
+{
+       REGISTER_ROOT(template);
+       jit_add_literal(jit,argument);
+       UNREGISTER_ROOT(template);
+       jit_emit(jit,template);
+}
+
+/* Allocates memory */
+INLINE void jit_push(F_JIT *jit, CELL literal)
+{
+       jit_emit_with(jit,userenv[JIT_PUSH_IMMEDIATE],literal);
+}
+
+/* Allocates memory */
+INLINE void jit_word_jump(F_JIT *jit, CELL word)
+{
+       jit_emit_with(jit,userenv[JIT_WORD_JUMP],word);
+}
+
+/* Allocates memory */
+INLINE void jit_word_call(F_JIT *jit, CELL word)
+{
+       jit_emit_with(jit,userenv[JIT_WORD_CALL],word);
+}
+
+/* Allocates memory */
+INLINE void jit_emit_subprimitive(F_JIT *jit, F_WORD *word)
+{
+       REGISTER_UNTAGGED(word);
+       if(array_nth(untag_object(word->subprimitive),1) != F)
+               jit_add_literal(jit,T);
+       UNREGISTER_UNTAGGED(word);
+
+       jit_emit(jit,word->subprimitive);
+}
+
+INLINE F_FIXNUM jit_get_position(F_JIT *jit)
+{
+       if(jit->computing_offset_p)
+       {
+               /* If this is still on, jit_emit() didn't clear it,
+                  so the offset was out of bounds */
+               return -1;
+       }
+       else
+               return jit->position;
+}
+
+INLINE void jit_set_position(F_JIT *jit, F_FIXNUM position)
+{
+       if(jit->computing_offset_p)
+               jit->position = position;
+}
index e9cdef62727947fe4d1c7aecb54ec775ea98a900..f439b1f8a7d83e11d36d38b2dfbc7ced94866006 100755 (executable)
@@ -32,32 +32,36 @@ typedef signed long long s64;
 /*** Tags ***/
 #define FIXNUM_TYPE 0
 #define BIGNUM_TYPE 1
-#define TUPLE_TYPE 2
-#define OBJECT_TYPE 3
-#define RATIO_TYPE 4
-#define FLOAT_TYPE 5
-#define COMPLEX_TYPE 6
+#define ARRAY_TYPE 2
+#define FLOAT_TYPE 3
+#define QUOTATION_TYPE 4
+#define F_TYPE 5
+#define OBJECT_TYPE 6
+#define TUPLE_TYPE 7
+
+#define HI_TAG_OR_TUPLE_P(cell) (((CELL)(cell) & 6) == 6)
+#define HI_TAG_HEADER(cell) (((CELL)(cell) & 1) * CELLS + UNTAG(cell))
 
 /* Canonical F object */
-#define F_TYPE 7
 #define F F_TYPE
 
-#define HEADER_TYPE 7 /* anything less than or equal to this is a tag */
+#define HEADER_TYPE 8 /* anything less than this is a tag */
 
-#define GC_COLLECTED 5 /* See gc.c */
+#define GC_COLLECTED 5 /* can be anything other than FIXNUM_TYPE */
 
 /*** Header types ***/
-#define ARRAY_TYPE 8
-#define WRAPPER_TYPE 9
-#define BYTE_ARRAY_TYPE 10
-#define CALLSTACK_TYPE 11
-#define STRING_TYPE 12
-#define WORD_TYPE 13
-#define QUOTATION_TYPE 14
-#define DLL_TYPE 15
-#define ALIEN_TYPE 16
-
-#define TYPE_COUNT 17
+#define WRAPPER_TYPE 8
+#define BYTE_ARRAY_TYPE 9
+#define CALLSTACK_TYPE 10
+#define STRING_TYPE 11
+#define WORD_TYPE 12
+#define DLL_TYPE 13
+#define ALIEN_TYPE 14
+
+#define TYPE_COUNT 15
+
+/* Not a real type, but F_CODE_BLOCK's type field can be set to this */
+#define PIC_TYPE 69
 
 INLINE bool immediate_p(CELL obj)
 {
@@ -152,9 +156,8 @@ typedef struct {
        CELL def;
        /* TAGGED property assoc for library code */
        CELL props;
-       /* TAGGED t or f, t means its compiled with the optimizing compiler,
-       f means its compiled with the non-optimizing compiler */
-       CELL optimizedp;
+       /* TAGGED alternative entry point for direct non-tail calls. Used for inline caching */
+       CELL direct_entry_def;
        /* TAGGED call count for profiling */
        CELL counter;
        /* TAGGED machine code for sub-primitive */
@@ -173,13 +176,6 @@ typedef struct {
        CELL object;
 } F_WRAPPER;
 
-/* Assembly code makes assumptions about the layout of this struct */
-typedef struct {
-       CELL header;
-       CELL numerator;
-       CELL denominator;
-} F_RATIO;
-
 /* Assembly code makes assumptions about the layout of this struct */
 typedef struct {
 /* We use a union here to force the float value to be aligned on an
@@ -208,13 +204,6 @@ typedef struct {
        F_CODE_BLOCK *code;
 } F_QUOTATION;
 
-/* Assembly code makes assumptions about the layout of this struct */
-typedef struct {
-       CELL header;
-       CELL real;
-       CELL imaginary;
-} F_COMPLEX;
-
 /* Assembly code makes assumptions about the layout of this struct */
 typedef struct {
        CELL header;
index e852f9e54d8d525ddb2b43ad00c47c7646b2e60d..bbedf4639411a3c48f11e79fe6411d6495ce9eb2 100644 (file)
@@ -19,10 +19,15 @@ CELL gc_locals;
 
 DEFPUSHPOP(gc_local_,gc_locals)
 
-#define REGISTER_ROOT(obj) gc_local_push((CELL)&obj)
+#define REGISTER_ROOT(obj) \
+       { \
+               if(!immediate_p(obj))    \
+                       check_data_pointer(obj); \
+               gc_local_push((CELL)&(obj));    \
+       }
 #define UNREGISTER_ROOT(obj) \
        { \
-               if(gc_local_pop() != (CELL)&obj) \
+               if(gc_local_pop() != (CELL)&(obj))                      \
                        critical_error("Mismatched REGISTER_ROOT/UNREGISTER_ROOT",0); \
        }
 
@@ -33,7 +38,7 @@ CELL extra_roots;
 
 DEFPUSHPOP(root_,extra_roots)
 
-#define REGISTER_UNTAGGED(obj) root_push(obj ? tag_object(obj) : 0)
+#define REGISTER_UNTAGGED(obj) root_push(obj ? RETAG(obj,OBJECT_TYPE) : 0)
 #define UNREGISTER_UNTAGGED(obj) obj = untag_object(root_pop())
 
 /* We ignore strings which point outside the data heap, but we might be given
index 86b5223eaa51e6038efdc0a85828044af9033714..9866c4aafde84b4cd3061ccbd04007a13c9ba385 100644 (file)
@@ -2,7 +2,11 @@
 #define __FACTOR_MASTER_H__
 
 #ifndef WINCE
-       #include <errno.h>
+#include <errno.h>
+#endif
+
+#ifdef FACTOR_DEBUG
+#include <assert.h>
 #endif
 
 #include <fcntl.h>
 #include "bignum.h"
 #include "write_barrier.h"
 #include "data_heap.h"
-#include "local_roots.h"
 #include "data_gc.h"
+#include "local_roots.h"
 #include "debug.h"
-#include "types.h"
+#include "arrays.h"
+#include "strings.h"
+#include "booleans.h"
+#include "byte_arrays.h"
+#include "tuples.h"
+#include "words.h"
 #include "math.h"
 #include "float_bits.h"
 #include "io.h"
@@ -41,6 +50,9 @@
 #include "callstack.h"
 #include "alien.h"
 #include "quotations.h"
+#include "jit.h"
+#include "dispatch.h"
+#include "inline_cache.h"
 #include "factor.h"
 #include "utilities.h"
 
index 7bff0de387327bf0228ff31868b7bdfee4d530cf..25180abdd6becc45a75f9031c3b653fba18b2305 100644 (file)
--- a/vm/math.c
+++ b/vm/math.c
@@ -375,18 +375,6 @@ CELL unbox_array_size(void)
        return 0; /* can't happen */
 }
 
-/* Ratios */
-
-/* Does not reduce to lowest terms, so should only be used by math
-library implementation, to avoid breaking invariants. */
-void primitive_from_fraction(void)
-{
-       F_RATIO* ratio = allot_object(RATIO_TYPE,sizeof(F_RATIO));
-       ratio->denominator = dpop();
-       ratio->numerator = dpop();
-       dpush(RETAG(ratio,RATIO_TYPE));
-}
-
 /* Floats */
 void primitive_fixnum_to_float(void)
 {
@@ -525,13 +513,3 @@ void box_double(double flo)
 {
         dpush(allot_float(flo));
 }
-
-/* Complex numbers */
-
-void primitive_from_rect(void)
-{
-       F_COMPLEX* z = allot_object(COMPLEX_TYPE,sizeof(F_COMPLEX));
-       z->imaginary = dpop();
-       z->real = dpop();
-       dpush(RETAG(z,COMPLEX_TYPE));
-}
index f94f12b76d40e047f30164bb864477d2e1ad06ae..4a18888549dea814dadaea194208138daf80e196 100644 (file)
--- a/vm/math.h
+++ b/vm/math.h
@@ -85,8 +85,6 @@ DLLEXPORT u64 to_unsigned_8(CELL obj);
 
 CELL unbox_array_size(void);
 
-void primitive_from_fraction(void);
-
 INLINE double untag_float_fast(CELL tagged)
 {
        return ((F_FLOAT*)UNTAG(tagged))->n;
@@ -151,5 +149,3 @@ void primitive_float_bits(void);
 void primitive_bits_float(void);
 void primitive_double_bits(void);
 void primitive_bits_double(void);
-
-void primitive_from_rect(void);
index 2abc04cb3b6e0df0ad317b7c7663b13787a153ac..c917cd804d433716e3943196ae4718fe87df193c 100755 (executable)
@@ -1,39 +1,5 @@
 #include "master.h"
 
-F_STRING *get_error_message(void)
-{
-       DWORD id = GetLastError();
-       F_CHAR *msg = error_message(id);
-       F_STRING *string = from_u16_string(msg);
-       LocalFree(msg);
-       return string;
-}
-
-/* You must LocalFree() the return value! */
-F_CHAR *error_message(DWORD id)
-{
-       F_CHAR *buffer;
-       int index;
-
-       DWORD ret = FormatMessage(
-               FORMAT_MESSAGE_ALLOCATE_BUFFER |
-               FORMAT_MESSAGE_FROM_SYSTEM,
-               NULL,
-               id,
-               MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-               (LPTSTR)(void *) &buffer,
-               0, NULL);
-       if(ret == 0)
-               return error_message(GetLastError());
-
-       /* strip whitespace from end */
-       index = wcslen(buffer) - 1;
-       while(index >= 0 && isspace(buffer[index]))
-               buffer[index--] = 0;
-
-       return buffer;
-}
-
 HMODULE hFactorDll;
 
 void init_ffi(void)
index 36d350f50dc81f008008adbebb7833c430425ff3..95d41ca9a2c42147e29cfc05746cea77930694a6 100755 (executable)
@@ -42,10 +42,6 @@ typedef wchar_t F_CHAR;
 /* Difference between Jan 1 00:00:00 1601 and Jan 1 00:00:00 1970 */
 #define EPOCH_OFFSET 0x019db1ded53e8000LL
 
-F_STRING *get_error_message(void);
-DLLEXPORT F_CHAR *error_message(DWORD id);
-void windows_error(void);
-
 void init_ffi(void);
 void ffi_dlopen(F_DLL *dll);
 void *ffi_dlsym(F_DLL *dll, F_SYMBOL *symbol);
index 80b672d9d2d34d20a406bfcd4ffaf6ad6c7ef6bf..cb5161693a81ecbfd698a988fa6e24f85be1cdbd 100755 (executable)
@@ -7,14 +7,12 @@ void *primitives[] = {
        primitive_float_to_bignum,
        primitive_fixnum_to_float,
        primitive_bignum_to_float,
-       primitive_from_fraction,
        primitive_str_to_float,
        primitive_float_to_str,
        primitive_float_bits,
        primitive_double_bits,
        primitive_bits_float,
        primitive_bits_double,
-       primitive_from_rect,
        primitive_fixnum_add,
        primitive_fixnum_subtract,
        primitive_fixnum_multiply,
@@ -144,5 +142,13 @@ void *primitives[] = {
        primitive_clear_gc_stats,
        primitive_jit_compile,
        primitive_load_locals,
-       primitive_check_datastack
+       primitive_check_datastack,
+       primitive_inline_cache_miss,
+       primitive_mega_cache_miss,
+       primitive_lookup_method,
+       primitive_reset_dispatch_stats,
+       primitive_dispatch_stats,
+       primitive_reset_inline_cache_stats,
+       primitive_inline_cache_stats,
+       primitive_optimized_p,
 };
index acafecdff5d3cb20c02c811fb5f9361e1648d26a..5578854d6d42bd6f4192637e1a0ccab22df8a429 100755 (executable)
@@ -1,54 +1,20 @@
 #include "master.h"
 
 /* Allocates memory */
-F_CODE_BLOCK *compile_profiling_stub(F_WORD *word)
+F_CODE_BLOCK *compile_profiling_stub(CELL word)
 {
-       CELL literals = allot_array_2(tag_object(word),tag_object(word));
-       REGISTER_ROOT(literals);
-
-       F_ARRAY *quadruple = untag_object(userenv[JIT_PROFILING]);
-
-       CELL code = array_nth(quadruple,0);
-       REGISTER_ROOT(code);
-
-       F_REL rel = (to_fixnum(array_nth(quadruple,1)) << 24)
-               | (to_fixnum(array_nth(quadruple,2)) << 28)
-               | (to_fixnum(array_nth(quadruple,3)) * compiled_code_format());
-
-       F_BYTE_ARRAY *relocation = allot_byte_array(sizeof(F_REL));
-       memcpy(relocation + 1,&rel,sizeof(F_REL));
-
-       UNREGISTER_ROOT(code);
-       UNREGISTER_ROOT(literals);
-
-       return add_code_block(
-               WORD_TYPE,
-               untag_object(code),
-               NULL, /* no labels */
-               tag_object(relocation),
-               literals);
+       REGISTER_ROOT(word);
+       F_JIT jit;
+       jit_init(&jit,WORD_TYPE,word);
+       jit_emit_with(&jit,userenv[JIT_PROFILING],word);
+       F_CODE_BLOCK *block = jit_make_code_block(&jit);
+       jit_dispose(&jit);
+       UNREGISTER_ROOT(word);
+       return block;
 }
 
 /* Allocates memory */
-void update_word_xt(F_WORD *word)
-{
-       if(profiling_p)
-       {
-               if(!word->profiling)
-               {
-                       REGISTER_UNTAGGED(word);
-                       F_CODE_BLOCK *profiling = compile_profiling_stub(word);
-                       UNREGISTER_UNTAGGED(word);
-                       word->profiling = profiling;
-               }
-
-               word->xt = (XT)(word->profiling + 1);
-       }
-       else
-               word->xt = (XT)(word->code + 1);
-}
-
-void set_profiling(bool profiling)
+static void set_profiling(bool profiling)
 {
        if(profiling == profiling_p)
                return;
index 4a44ec3f36f31f213c25d54c36c9d50b8ca57ecc..40daab429c59fd2d49ad516e703f8dfdb95fdfba 100755 (executable)
@@ -1,4 +1,3 @@
 bool profiling_p;
+F_CODE_BLOCK *compile_profiling_stub(CELL word);
 void primitive_profiling(void);
-F_CODE_BLOCK *compile_profiling_stub(F_WORD *word);
-void update_word_xt(F_WORD *word);
index d08fecdefb3ea7ab223ecf6c486328bda13b1c8f..29ab8537d1c39ff46e868ea6d09cc071cfaae441 100755 (executable)
@@ -22,31 +22,25 @@ special words which are open-coded, see below), then no prolog/epilog is
 generated.
 
 3) When in tail position and immediately preceded by literal arguments, the
-'if' and 'dispatch' conditionals are generated inline, instead of as a call to
-the 'if' word.
+'if' is generated inline, instead of as a call to the 'if' word.
 
 4) When preceded by a quotation, calls to 'dip', '2dip' and '3dip' are
 open-coded as retain stack manipulation surrounding a subroutine call.
 
-5) When preceded by an array, calls to the 'declare' word are optimized out
-entirely. This word is only used by the optimizing compiler, and with the
-non-optimizing compiler it would otherwise just decrease performance to have to
-push the array and immediately drop it after.
-
-6) Sub-primitives are primitive words which are implemented in assembly and not
+5) Sub-primitives are primitive words which are implemented in assembly and not
 in the VM. They are open-coded and no subroutine call is generated. This
 includes stack shufflers, some fixnum arithmetic words, and words such as tag,
 slot and eq?. A primitive call is relatively expensive (two subroutine calls)
 so this results in a big speedup for relatively little effort. */
 
-bool jit_primitive_call_p(F_ARRAY *array, CELL i)
+static bool jit_primitive_call_p(F_ARRAY *array, CELL i)
 {
        return (i + 2) == array_capacity(array)
                && type_of(array_nth(array,i)) == FIXNUM_TYPE
                && array_nth(array,i + 1) == userenv[JIT_PRIMITIVE_WORD];
 }
 
-bool jit_fast_if_p(F_ARRAY *array, CELL i)
+static bool jit_fast_if_p(F_ARRAY *array, CELL i)
 {
        return (i + 3) == array_capacity(array)
                && type_of(array_nth(array,i)) == QUOTATION_TYPE
@@ -54,75 +48,37 @@ bool jit_fast_if_p(F_ARRAY *array, CELL i)
                && array_nth(array,i + 2) == userenv[JIT_IF_WORD];
 }
 
-bool jit_fast_dispatch_p(F_ARRAY *array, CELL i)
-{
-       return (i + 2) == array_capacity(array)
-               && type_of(array_nth(array,i)) == ARRAY_TYPE
-               && array_nth(array,i + 1) == userenv[JIT_DISPATCH_WORD];
-}
-
-bool jit_fast_dip_p(F_ARRAY *array, CELL i)
+static bool jit_fast_dip_p(F_ARRAY *array, CELL i)
 {
        return (i + 2) <= array_capacity(array)
                && type_of(array_nth(array,i)) == QUOTATION_TYPE
                && array_nth(array,i + 1) == userenv[JIT_DIP_WORD];
 }
 
-bool jit_fast_2dip_p(F_ARRAY *array, CELL i)
+static bool jit_fast_2dip_p(F_ARRAY *array, CELL i)
 {
        return (i + 2) <= array_capacity(array)
                && type_of(array_nth(array,i)) == QUOTATION_TYPE
                && array_nth(array,i + 1) == userenv[JIT_2DIP_WORD];
 }
 
-bool jit_fast_3dip_p(F_ARRAY *array, CELL i)
+static bool jit_fast_3dip_p(F_ARRAY *array, CELL i)
 {
        return (i + 2) <= array_capacity(array)
                && type_of(array_nth(array,i)) == QUOTATION_TYPE
                && array_nth(array,i + 1) == userenv[JIT_3DIP_WORD];
 }
 
-bool jit_ignore_declare_p(F_ARRAY *array, CELL i)
+static bool jit_mega_lookup_p(F_ARRAY *array, CELL i)
 {
-       return (i + 1) < array_capacity(array)
+       return (i + 3) < array_capacity(array)
                && type_of(array_nth(array,i)) == ARRAY_TYPE
-               && array_nth(array,i + 1) == userenv[JIT_DECLARE_WORD];
+               && type_of(array_nth(array,i + 1)) == FIXNUM_TYPE
+               && type_of(array_nth(array,i + 2)) == ARRAY_TYPE
+               && array_nth(array,i + 3) == userenv[MEGA_LOOKUP_WORD];
 }
 
-F_ARRAY *code_to_emit(CELL code)
-{
-       return untag_object(array_nth(untag_object(code),0));
-}
-
-F_REL rel_to_emit(CELL code, CELL code_format, CELL code_length, bool *rel_p)
-{
-       F_ARRAY *quadruple = untag_object(code);
-       CELL rel_class = array_nth(quadruple,1);
-       CELL rel_type = array_nth(quadruple,2);
-       CELL offset = array_nth(quadruple,3);
-
-       if(rel_class == F)
-       {
-               *rel_p = false;
-               return 0;
-       }
-       else
-       {
-               *rel_p = true;
-               return (to_fixnum(rel_type) << 28)
-                       | (to_fixnum(rel_class) << 24)
-                       | ((code_length + to_fixnum(offset)) * code_format);
-       }
-}
-
-#define EMIT(name) { \
-               bool rel_p; \
-               F_REL rel = rel_to_emit(name,code_format,code_count,&rel_p); \
-               if(rel_p) GROWABLE_BYTE_ARRAY_APPEND(relocation,&rel,sizeof(F_REL)); \
-               GROWABLE_ARRAY_APPEND(code,code_to_emit(name)); \
-       }
-
-bool jit_stack_frame_p(F_ARRAY *array)
+static bool jit_stack_frame_p(F_ARRAY *array)
 {
        F_FIXNUM length = array_capacity(array);
        F_FIXNUM i;
@@ -133,7 +89,7 @@ bool jit_stack_frame_p(F_ARRAY *array)
                if(type_of(obj) == WORD_TYPE)
                {
                        F_WORD *word = untag_object(obj);
-                       if(word->subprimitive == F && obj != userenv[JIT_DECLARE_WORD])
+                       if(word->subprimitive == F)
                                return true;
                }
                else if(type_of(obj) == QUOTATION_TYPE)
@@ -148,45 +104,22 @@ bool jit_stack_frame_p(F_ARRAY *array)
        return false;
 }
 
-void set_quot_xt(F_QUOTATION *quot, F_CODE_BLOCK *code)
-{
-       if(code->block.type != QUOTATION_TYPE)
-               critical_error("Bad param to set_quot_xt",(CELL)code);
-
-       quot->code = code;
-       quot->xt = (XT)(code + 1);
-       quot->compiledp = T;
-}
+#define TAIL_CALL { \
+               if(stack_frame) jit_emit(jit,userenv[JIT_EPILOG]); \
+               tail_call = true; \
+       }
 
-/* Might GC */
-void jit_compile(CELL quot, bool relocate)
+/* Allocates memory */
+static void jit_iterate_quotation(F_JIT *jit, CELL array, CELL compiling, CELL relocate)
 {
-       if(untag_quotation(quot)->compiledp != F)
-               return;
-
-       CELL code_format = compiled_code_format();
-
-       REGISTER_ROOT(quot);
-
-       CELL array = untag_quotation(quot)->array;
        REGISTER_ROOT(array);
 
-       GROWABLE_ARRAY(code);
-       REGISTER_ROOT(code);
-
-       GROWABLE_BYTE_ARRAY(relocation);
-       REGISTER_ROOT(relocation);
-
-       GROWABLE_ARRAY(literals);
-       REGISTER_ROOT(literals);
-
-       if(stack_traces_p())
-               GROWABLE_ARRAY_ADD(literals,quot);
-
        bool stack_frame = jit_stack_frame_p(untag_object(array));
 
+       jit_set_position(jit,0);
+
        if(stack_frame)
-               EMIT(userenv[JIT_PROLOG]);
+               jit_emit(jit,userenv[JIT_PROLOG]);
 
        CELL i;
        CELL length = array_capacity(untag_object(array));
@@ -194,7 +127,11 @@ void jit_compile(CELL quot, bool relocate)
 
        for(i = 0; i < length; i++)
        {
+               jit_set_position(jit,i);
+
                CELL obj = array_nth(untag_object(array),i);
+               REGISTER_ROOT(obj);
+
                F_WORD *word;
                F_WRAPPER *wrapper;
 
@@ -205,42 +142,40 @@ void jit_compile(CELL quot, bool relocate)
 
                        /* Intrinsics */
                        if(word->subprimitive != F)
+                               jit_emit_subprimitive(jit,word);
+                       /* The (execute) primitive is special-cased */
+                       else if(obj == userenv[JIT_EXECUTE_WORD])
                        {
-                               if(array_nth(untag_object(word->subprimitive),1) != F)
+                               if(i == length - 1)
                                {
-                                       GROWABLE_ARRAY_ADD(literals,T);
+                                       TAIL_CALL;
+                                       jit_emit(jit,userenv[JIT_EXECUTE_JUMP]);
                                }
-
-                               EMIT(word->subprimitive);
+                               else
+                                       jit_emit(jit,userenv[JIT_EXECUTE_CALL]);
                        }
+                       /* Everything else */
                        else
                        {
-                               GROWABLE_ARRAY_ADD(literals,obj);
-
                                if(i == length - 1)
                                {
-                                       if(stack_frame)
-                                               EMIT(userenv[JIT_EPILOG]);
-
-                                       EMIT(userenv[JIT_WORD_JUMP]);
-
-                                       tail_call = true;
+                                       TAIL_CALL;
+                                       jit_word_jump(jit,obj);
                                }
                                else
-                                       EMIT(userenv[JIT_WORD_CALL]);
+                                       jit_word_call(jit,obj);
                        }
                        break;
                case WRAPPER_TYPE:
                        wrapper = untag_object(obj);
-                       GROWABLE_ARRAY_ADD(literals,wrapper->object);
-                       EMIT(userenv[JIT_PUSH_IMMEDIATE]);
+                       jit_push(jit,wrapper->object);
                        break;
                case FIXNUM_TYPE:
+                       /* Primitive calls */
                        if(jit_primitive_call_p(untag_object(array),i))
                        {
-                               EMIT(userenv[JIT_SAVE_STACK]);
-                               GROWABLE_ARRAY_ADD(literals,obj);
-                               EMIT(userenv[JIT_PRIMITIVE]);
+                               jit_emit(jit,userenv[JIT_SAVE_STACK]);
+                               jit_emit_with(jit,userenv[JIT_PRIMITIVE],obj);
 
                                i++;
 
@@ -248,244 +183,136 @@ void jit_compile(CELL quot, bool relocate)
                                break;
                        }
                case QUOTATION_TYPE:
+                       /* 'if' preceeded by two literal quotations (this is why if and ? are
+                          mutually recursive in the library, but both still work) */
                        if(jit_fast_if_p(untag_object(array),i))
                        {
-                               if(stack_frame)
-                                       EMIT(userenv[JIT_EPILOG]);
+                               TAIL_CALL;
 
-                               jit_compile(array_nth(untag_object(array),i),relocate);
-                               jit_compile(array_nth(untag_object(array),i + 1),relocate);
+                               if(compiling)
+                               {
+                                       jit_compile(array_nth(untag_object(array),i),relocate);
+                                       jit_compile(array_nth(untag_object(array),i + 1),relocate);
+                               }
 
-                               GROWABLE_ARRAY_ADD(literals,array_nth(untag_object(array),i));
-                               EMIT(userenv[JIT_IF_1]);
-                               GROWABLE_ARRAY_ADD(literals,array_nth(untag_object(array),i + 1));
-                               EMIT(userenv[JIT_IF_2]);
+                               jit_emit_with(jit,userenv[JIT_IF_1],array_nth(untag_object(array),i));
+                               jit_emit_with(jit,userenv[JIT_IF_2],array_nth(untag_object(array),i + 1));
 
                                i += 2;
 
-                               tail_call = true;
                                break;
                        }
+                       /* dip */
                        else if(jit_fast_dip_p(untag_object(array),i))
                        {
-                               jit_compile(obj,relocate);
-
-                               GROWABLE_ARRAY_ADD(literals,array_nth(untag_object(array),i));
-                               EMIT(userenv[JIT_DIP]);
-
+                               if(compiling)
+                                       jit_compile(obj,relocate);
+                               jit_emit_with(jit,userenv[JIT_DIP],obj);
                                i++;
                                break;
                        }
+                       /* 2dip */
                        else if(jit_fast_2dip_p(untag_object(array),i))
                        {
-                               jit_compile(obj,relocate);
-
-                               GROWABLE_ARRAY_ADD(literals,array_nth(untag_object(array),i));
-                               EMIT(userenv[JIT_2DIP]);
-
+                               if(compiling)
+                                       jit_compile(obj,relocate);
+                               jit_emit_with(jit,userenv[JIT_2DIP],obj);
                                i++;
                                break;
                        }
+                       /* 3dip */
                        else if(jit_fast_3dip_p(untag_object(array),i))
                        {
-                               jit_compile(obj,relocate);
-
-                               GROWABLE_ARRAY_ADD(literals,array_nth(untag_object(array),i));
-                               EMIT(userenv[JIT_3DIP]);
-
+                               if(compiling)
+                                       jit_compile(obj,relocate);
+                               jit_emit_with(jit,userenv[JIT_3DIP],obj);
                                i++;
                                break;
                        }
                case ARRAY_TYPE:
-                       if(jit_fast_dispatch_p(untag_object(array),i))
+                       /* Method dispatch */
+                       if(jit_mega_lookup_p(untag_object(array),i))
                        {
-                               if(stack_frame)
-                                       EMIT(userenv[JIT_EPILOG]);
-
-                               GROWABLE_ARRAY_ADD(literals,array_nth(untag_object(array),i));
-                               EMIT(userenv[JIT_DISPATCH]);
-
-                               i++;
-
+                               jit_emit_mega_cache_lookup(jit,
+                                       array_nth(untag_object(array),i),
+                                       untag_fixnum_fast(array_nth(untag_object(array),i + 1)),
+                                       array_nth(untag_object(array),i + 2));
+                               i += 3;
                                tail_call = true;
                                break;
                        }
-                       else if(jit_ignore_declare_p(untag_object(array),i))
-                       {
-                               i++;
-                               break;
-                       }
                default:
-                       GROWABLE_ARRAY_ADD(literals,obj);
-                       EMIT(userenv[JIT_PUSH_IMMEDIATE]);
+                       jit_push(jit,obj);
                        break;
                }
+
+               UNREGISTER_ROOT(obj);
        }
 
        if(!tail_call)
        {
-               if(stack_frame)
-                       EMIT(userenv[JIT_EPILOG]);
+               jit_set_position(jit,length);
 
-               EMIT(userenv[JIT_RETURN]);
+               if(stack_frame)
+                       jit_emit(jit,userenv[JIT_EPILOG]);
+               jit_emit(jit,userenv[JIT_RETURN]);
        }
 
-       GROWABLE_ARRAY_TRIM(code);
-       GROWABLE_ARRAY_TRIM(literals);
-       GROWABLE_BYTE_ARRAY_TRIM(relocation);
-
-       F_CODE_BLOCK *compiled = add_code_block(
-               QUOTATION_TYPE,
-               untag_object(code),
-               NULL,
-               relocation,
-               literals);
-
-       set_quot_xt(untag_object(quot),compiled);
-
-       if(relocate)
-               relocate_code_block(compiled);
-
-       UNREGISTER_ROOT(literals);
-       UNREGISTER_ROOT(relocation);
-       UNREGISTER_ROOT(code);
        UNREGISTER_ROOT(array);
-       UNREGISTER_ROOT(quot);
 }
 
-/* Crappy code duplication. If C had closures (not just function pointers)
-it would be easy to get rid of, but I can't think of a good way to deal
-with it right now that doesn't involve lots of boilerplate that would be
-worse than the duplication itself (eg, putting all state in some global
-struct.) */
-#define COUNT(name,scan) \
-       { \
-               CELL size = array_capacity(code_to_emit(name)) * code_format; \
-               if(offset == 0) return scan - 1; \
-               if(offset < size) return scan + 1; \
-               offset -= size; \
-       }
-
-F_FIXNUM quot_code_offset_to_scan(CELL quot, F_FIXNUM offset)
+void set_quot_xt(F_QUOTATION *quot, F_CODE_BLOCK *code)
 {
-       CELL code_format = compiled_code_format();
-
-       CELL array = untag_quotation(quot)->array;
-
-       bool stack_frame = jit_stack_frame_p(untag_object(array));
-
-       if(stack_frame)
-               COUNT(userenv[JIT_PROLOG],0)
-
-       CELL i;
-       CELL length = array_capacity(untag_object(array));
-       bool tail_call = false;
+       if(code->block.type != QUOTATION_TYPE)
+               critical_error("Bad param to set_quot_xt",(CELL)code);
 
-       for(i = 0; i < length; i++)
-       {
-               CELL obj = array_nth(untag_object(array),i);
-               F_WORD *word;
+       quot->code = code;
+       quot->xt = (XT)(code + 1);
+       quot->compiledp = T;
+}
 
-               switch(type_of(obj))
-               {
-               case WORD_TYPE:
-                       /* Intrinsics */
-                       word = untag_object(obj);
-                       if(word->subprimitive != F)
-                               COUNT(word->subprimitive,i)
-                       else if(i == length - 1)
-                       {
-                               if(stack_frame)
-                                       COUNT(userenv[JIT_EPILOG],i);
+/* Allocates memory */
+void jit_compile(CELL quot, bool relocate)
+{
+       if(untag_quotation(quot)->compiledp != F)
+               return;
 
-                               COUNT(userenv[JIT_WORD_JUMP],i)
+       CELL array = untag_quotation(quot)->array;
 
-                               tail_call = true;
-                       }
-                       else
-                               COUNT(userenv[JIT_WORD_CALL],i)
-                       break;
-               case WRAPPER_TYPE:
-                       COUNT(userenv[JIT_PUSH_IMMEDIATE],i)
-                       break;
-               case FIXNUM_TYPE:
-                       if(jit_primitive_call_p(untag_object(array),i))
-                       {
-                               COUNT(userenv[JIT_SAVE_STACK],i);
-                               COUNT(userenv[JIT_PRIMITIVE],i);
+       REGISTER_ROOT(quot);
+       REGISTER_ROOT(array);
 
-                               i++;
+       F_JIT jit;
+       jit_init(&jit,QUOTATION_TYPE,quot);
 
-                               tail_call = true;
-                               break;
-                       }
-               case QUOTATION_TYPE:
-                       if(jit_fast_if_p(untag_object(array),i))
-                       {
-                               if(stack_frame)
-                                       COUNT(userenv[JIT_EPILOG],i)
+       jit_iterate_quotation(&jit,array,true,relocate);
 
-                               COUNT(userenv[JIT_IF_1],i)
-                               COUNT(userenv[JIT_IF_2],i)
-                               i += 2;
+       F_CODE_BLOCK *compiled = jit_make_code_block(&jit);
 
-                               tail_call = true;
-                               break;
-                       }
-                       else if(jit_fast_dip_p(untag_object(array),i))
-                       {
-                               COUNT(userenv[JIT_DIP],i)
-                               i++;
-                               break;
-                       }
-                       else if(jit_fast_2dip_p(untag_object(array),i))
-                       {
-                               COUNT(userenv[JIT_2DIP],i)
-                               i++;
-                               break;
-                       }
-                       else if(jit_fast_3dip_p(untag_object(array),i))
-                       {
-                               COUNT(userenv[JIT_3DIP],i)
-                               i++;
-                               break;
-                       }
-               case ARRAY_TYPE:
-                       if(jit_fast_dispatch_p(untag_object(array),i))
-                       {
-                               if(stack_frame)
-                                       COUNT(userenv[JIT_EPILOG],i)
-
-                               i++;
+       set_quot_xt(untag_object(quot),compiled);
 
-                               COUNT(userenv[JIT_DISPATCH],i)
+       if(relocate) relocate_code_block(compiled);
 
-                               tail_call = true;
-                               break;
-                       }
-                       if(jit_ignore_declare_p(untag_object(array),i))
-                       {
-                               if(offset == 0) return i;
+       jit_dispose(&jit);
 
-                               i++;
+       UNREGISTER_ROOT(array);
+       UNREGISTER_ROOT(quot);
+}
 
-                               break;
-                       }
-               default:
-                       COUNT(userenv[JIT_PUSH_IMMEDIATE],i)
-                       break;
-               }
-       }
+F_FIXNUM quot_code_offset_to_scan(CELL quot, CELL offset)
+{
+       CELL array = untag_quotation(quot)->array;
+       REGISTER_ROOT(array);
 
-       if(!tail_call)
-       {
-               if(stack_frame)
-                       COUNT(userenv[JIT_EPILOG],length)
+       F_JIT jit;
+       jit_init(&jit,QUOTATION_TYPE,quot);
+       jit_compute_position(&jit,offset);
+       jit_iterate_quotation(&jit,array,false,false);
+       jit_dispose(&jit);
 
-               COUNT(userenv[JIT_RETURN],length)
-       }
+       UNREGISTER_ROOT(array);
 
-       return -1;
+       return jit_get_position(&jit);
 }
 
 F_FASTCALL CELL lazy_jit_compile_impl(CELL quot, F_STACK_FRAME *stack)
@@ -511,7 +338,7 @@ void primitive_array_to_quotation(void)
        quot->compiledp = F;
        quot->cached_effect = F;
        quot->cache_counter = F;
-       drepl(tag_object(quot));
+       drepl(tag_quotation(quot));
 }
 
 void primitive_quotation_xt(void)
@@ -532,10 +359,13 @@ void compile_all_words(void)
        {
                F_WORD *word = untag_word(array_nth(untag_array(words),i));
                REGISTER_UNTAGGED(word);
-               if(word->optimizedp == F)
+
+               if(!word->code || !word_optimized_p(word))
                        jit_compile_word(word,word->def,false);
+
                UNREGISTER_UNTAGGED(word);
                update_word_xt(word);
+
        }
 
        UNREGISTER_ROOT(words);
index d571a90ed6c87f31e7aa912830df0f2fe87d94d8..6509dfe5ed2f022aef74a3614fda1a20e9b366cd 100755 (executable)
@@ -1,7 +1,14 @@
+DEFINE_UNTAG(F_QUOTATION,QUOTATION_TYPE,quotation)
+
+INLINE CELL tag_quotation(F_QUOTATION *quotation)
+{
+       return RETAG(quotation,QUOTATION_TYPE);
+}
+
 void set_quot_xt(F_QUOTATION *quot, F_CODE_BLOCK *code);
 void jit_compile(CELL quot, bool relocate);
 F_FASTCALL CELL lazy_jit_compile_impl(CELL quot, F_STACK_FRAME *stack);
-F_FIXNUM quot_code_offset_to_scan(CELL quot, F_FIXNUM offset);
+F_FIXNUM quot_code_offset_to_scan(CELL quot, CELL offset);
 void primitive_array_to_quotation(void);
 void primitive_quotation_xt(void);
 void primitive_jit_compile(void);
index e55eb904a74c9c93a768eacba40c04b10fe294c6..f5e45c2d5a480350d347ff6b45584f1277745c4a 100755 (executable)
--- a/vm/run.c
+++ b/vm/run.c
@@ -120,7 +120,7 @@ bool stack_to_array(CELL bottom, CELL top)
        {
                F_ARRAY *a = allot_array_internal(ARRAY_TYPE,depth / CELLS);
                memcpy(a + 1,(void*)bottom,depth);
-               dpush(tag_object(a));
+               dpush(tag_array(a));
                return true;
        }
 }
@@ -224,3 +224,25 @@ void primitive_load_locals(void)
        ds -= CELLS * count;
        rs += CELLS * count;
 }
+
+static CELL clone_object(CELL object)
+{
+       CELL size = object_size(object);
+       if(size == 0)
+               return object;
+       else
+       {
+               REGISTER_ROOT(object);
+               void *new_obj = allot_object(type_of(object),size);
+               UNREGISTER_ROOT(object);
+
+               CELL tag = TAG(object);
+               memcpy(new_obj,(void*)UNTAG(object),size);
+               return RETAG(new_obj,tag);
+       }
+}
+
+void primitive_clone(void)
+{
+       drepl(clone_object(dpeek()));
+}
index 2acff2cd5acd0a3ac6021f919781b0f5df03e265..b31fc3a2e17b2dc9de1b43f5bc9c6632138167ae 100755 (executable)
--- a/vm/run.h
+++ b/vm/run.h
@@ -32,9 +32,8 @@ typedef enum {
        BOOT_ENV            = 20, /* boot quotation */
        GLOBAL_ENV,               /* global namespace */
 
-       /* Used by the JIT compiler */
-       JIT_CODE_FORMAT     = 22,
-       JIT_PROLOG,
+       /* Quotation compilation in quotations.c */
+       JIT_PROLOG          = 23,
        JIT_PRIMITIVE_WORD,
        JIT_PRIMITIVE,
        JIT_WORD_JUMP,
@@ -42,22 +41,36 @@ typedef enum {
        JIT_IF_WORD,
        JIT_IF_1,
        JIT_IF_2,
-       JIT_DISPATCH_WORD,
-       JIT_DISPATCH,
-       JIT_EPILOG,
+       JIT_EPILOG          = 33,
        JIT_RETURN,
        JIT_PROFILING,
        JIT_PUSH_IMMEDIATE,
-       JIT_DECLARE_WORD    = 42,
-       JIT_SAVE_STACK,
+       JIT_SAVE_STACK = 38,
        JIT_DIP_WORD,
        JIT_DIP,
        JIT_2DIP_WORD,
        JIT_2DIP,
        JIT_3DIP_WORD,
        JIT_3DIP,
-
-       STACK_TRACES_ENV    = 59,
+       JIT_EXECUTE_WORD,
+       JIT_EXECUTE_JUMP,
+       JIT_EXECUTE_CALL,
+
+       /* Polymorphic inline cache generation in inline_cache.c */
+       PIC_LOAD            = 48,
+       PIC_TAG,
+       PIC_HI_TAG,
+       PIC_TUPLE,
+       PIC_HI_TAG_TUPLE,
+       PIC_CHECK_TAG,
+       PIC_CHECK,
+       PIC_HIT,
+       PIC_MISS_WORD,
+
+       /* Megamorphic cache generation in dispatch.c */
+       MEGA_LOOKUP         = 57,
+       MEGA_LOOKUP_WORD,
+        MEGA_MISS_WORD,
 
        UNDEFINED_ENV       = 60, /* default quotation for undefined words */
 
@@ -70,6 +83,8 @@ typedef enum {
        THREADS_ENV         = 64,
        RUN_QUEUE_ENV       = 65,
        SLEEP_QUEUE_ENV     = 66,
+
+       STACK_TRACES_ENV    = 67,
 } F_ENVTYPE;
 
 #define FIRST_SAVE_ENV BOOT_ENV
@@ -126,26 +141,37 @@ INLINE CELL tag_header(CELL cell)
        return cell << TAG_BITS;
 }
 
+INLINE void check_header(CELL cell)
+{
+#ifdef FACTOR_DEBUG
+       assert(TAG(cell) == FIXNUM_TYPE && untag_fixnum_fast(cell) < TYPE_COUNT);
+#endif
+}
+
 INLINE CELL untag_header(CELL cell)
 {
+       check_header(cell);
        return cell >> TAG_BITS;
 }
 
-INLINE CELL tag_object(void* cell)
+INLINE CELL hi_tag(CELL tagged)
 {
-       return RETAG(cell,OBJECT_TYPE);
+       return untag_header(get(UNTAG(tagged)));
 }
 
-INLINE CELL object_type(CELL tagged)
+INLINE CELL tag_object(void *cell)
 {
-       return untag_header(get(UNTAG(tagged)));
+#ifdef FACTOR_DEBUG
+       assert(hi_tag((CELL)cell) >= HEADER_TYPE);
+#endif
+       return RETAG(cell,OBJECT_TYPE);
 }
 
 INLINE CELL type_of(CELL tagged)
 {
        CELL tag = TAG(tagged);
        if(tag == OBJECT_TYPE)
-               return object_type(tagged);
+               return hi_tag(tagged);
        else
                return tag;
 }
@@ -242,14 +268,10 @@ void primitive_check_datastack(void);
 void primitive_getenv(void);
 void primitive_setenv(void);
 void primitive_exit(void);
-void primitive_os_env(void);
-void primitive_os_envs(void);
-void primitive_set_os_env(void);
-void primitive_unset_os_env(void);
-void primitive_set_os_envs(void);
 void primitive_micros(void);
 void primitive_sleep(void);
 void primitive_set_slot(void);
 void primitive_load_locals(void);
+void primitive_clone(void);
 
 bool stage2;
diff --git a/vm/strings.c b/vm/strings.c
new file mode 100644 (file)
index 0000000..f08a2e8
--- /dev/null
@@ -0,0 +1,294 @@
+#include "master.h"
+
+CELL string_nth(F_STRING* string, CELL index)
+{
+       /* If high bit is set, the most significant 16 bits of the char
+       come from the aux vector. The least significant bit of the
+       corresponding aux vector entry is negated, so that we can
+       XOR the two components together and get the original code point
+       back. */
+       CELL ch = bget(SREF(string,index));
+       if((ch & 0x80) == 0)
+               return ch;
+       else
+       {
+               F_BYTE_ARRAY *aux = untag_object(string->aux);
+               return (cget(BREF(aux,index * sizeof(u16))) << 7) ^ ch;
+       }
+}
+
+void set_string_nth_fast(F_STRING* string, CELL index, CELL ch)
+{
+       bput(SREF(string,index),ch);
+}
+
+void set_string_nth_slow(F_STRING* string, CELL index, CELL ch)
+{
+       F_BYTE_ARRAY *aux;
+
+       bput(SREF(string,index),(ch & 0x7f) | 0x80);
+
+       if(string->aux == F)
+       {
+               REGISTER_UNTAGGED(string);
+               /* We don't need to pre-initialize the
+               byte array with any data, since we
+               only ever read from the aux vector
+               if the most significant bit of a
+               character is set. Initially all of
+               the bits are clear. */
+               aux = allot_byte_array_internal(
+                       untag_fixnum_fast(string->length)
+                       * sizeof(u16));
+               UNREGISTER_UNTAGGED(string);
+
+               write_barrier((CELL)string);
+               string->aux = tag_object(aux);
+       }
+       else
+               aux = untag_object(string->aux);
+
+       cput(BREF(aux,index * sizeof(u16)),(ch >> 7) ^ 1);
+}
+
+/* allocates memory */
+void set_string_nth(F_STRING* string, CELL index, CELL ch)
+{
+       if(ch <= 0x7f)
+               set_string_nth_fast(string,index,ch);
+       else
+               set_string_nth_slow(string,index,ch);
+}
+
+/* untagged */
+F_STRING* allot_string_internal(CELL capacity)
+{
+       F_STRING *string = allot_object(STRING_TYPE,string_size(capacity));
+
+       string->length = tag_fixnum(capacity);
+       string->hashcode = F;
+       string->aux = F;
+
+       return string;
+}
+
+/* allocates memory */
+void fill_string(F_STRING *string, CELL start, CELL capacity, CELL fill)
+{
+       if(fill <= 0x7f)
+               memset((void *)SREF(string,start),fill,capacity - start);
+       else
+       {
+               CELL i;
+
+               for(i = start; i < capacity; i++)
+               {
+                       REGISTER_UNTAGGED(string);
+                       set_string_nth(string,i,fill);
+                       UNREGISTER_UNTAGGED(string);
+               }
+       }
+}
+
+/* untagged */
+F_STRING *allot_string(CELL capacity, CELL fill)
+{
+       F_STRING* string = allot_string_internal(capacity);
+       REGISTER_UNTAGGED(string);
+       fill_string(string,0,capacity,fill);
+       UNREGISTER_UNTAGGED(string);
+       return string;
+}
+
+void primitive_string(void)
+{
+       CELL initial = to_cell(dpop());
+       CELL length = unbox_array_size();
+       dpush(tag_object(allot_string(length,initial)));
+}
+
+static bool reallot_string_in_place_p(F_STRING *string, CELL capacity)
+{
+       return in_zone(&nursery,(CELL)string) && capacity <= string_capacity(string);
+}
+
+F_STRING* reallot_string(F_STRING* string, CELL capacity)
+{
+       if(reallot_string_in_place_p(string,capacity))
+       {
+               string->length = tag_fixnum(capacity);
+
+               if(string->aux != F)
+               {
+                       F_BYTE_ARRAY *aux = untag_object(string->aux);
+                       aux->capacity = tag_fixnum(capacity * 2);
+               }
+
+               return string;
+       }
+       else
+       {
+               CELL to_copy = string_capacity(string);
+               if(capacity < to_copy)
+                       to_copy = capacity;
+
+               REGISTER_UNTAGGED(string);
+               F_STRING *new_string = allot_string_internal(capacity);
+               UNREGISTER_UNTAGGED(string);
+
+               memcpy(new_string + 1,string + 1,to_copy);
+
+               if(string->aux != F)
+               {
+                       REGISTER_UNTAGGED(string);
+                       REGISTER_UNTAGGED(new_string);
+                       F_BYTE_ARRAY *new_aux = allot_byte_array(capacity * sizeof(u16));
+                       UNREGISTER_UNTAGGED(new_string);
+                       UNREGISTER_UNTAGGED(string);
+
+                       write_barrier((CELL)new_string);
+                       new_string->aux = tag_object(new_aux);
+
+                       F_BYTE_ARRAY *aux = untag_object(string->aux);
+                       memcpy(new_aux + 1,aux + 1,to_copy * sizeof(u16));
+               }
+
+               REGISTER_UNTAGGED(string);
+               REGISTER_UNTAGGED(new_string);
+               fill_string(new_string,to_copy,capacity,'\0');
+               UNREGISTER_UNTAGGED(new_string);
+               UNREGISTER_UNTAGGED(string);
+
+               return new_string;
+       }
+}
+
+void primitive_resize_string(void)
+{
+       F_STRING* string = untag_string(dpop());
+       CELL capacity = unbox_array_size();
+       dpush(tag_object(reallot_string(string,capacity)));
+}
+
+/* Some ugly macros to prevent a 2x code duplication */
+
+#define MEMORY_TO_STRING(type,utype) \
+       F_STRING *memory_to_##type##_string(const type *string, CELL length) \
+       { \
+               REGISTER_C_STRING(string); \
+               F_STRING* s = allot_string_internal(length); \
+               UNREGISTER_C_STRING(string); \
+               CELL i; \
+               for(i = 0; i < length; i++) \
+               { \
+                       REGISTER_UNTAGGED(s); \
+                       set_string_nth(s,i,(utype)*string); \
+                       UNREGISTER_UNTAGGED(s); \
+                       string++; \
+               } \
+               return s; \
+       } \
+       F_STRING *from_##type##_string(const type *str) \
+       { \
+               CELL length = 0; \
+               const type *scan = str; \
+               while(*scan++) length++; \
+               return memory_to_##type##_string(str,length); \
+       } \
+       void box_##type##_string(const type *str) \
+       { \
+               dpush(str ? tag_object(from_##type##_string(str)) : F); \
+       }
+
+MEMORY_TO_STRING(char,u8)
+MEMORY_TO_STRING(u16,u16)
+MEMORY_TO_STRING(u32,u32)
+
+bool check_string(F_STRING *s, CELL max)
+{
+       CELL capacity = string_capacity(s);
+       CELL i;
+       for(i = 0; i < capacity; i++)
+       {
+               CELL ch = string_nth(s,i);
+               if(ch == '\0' || ch >= (1 << (max * 8)))
+                       return false;
+       }
+       return true;
+}
+
+F_BYTE_ARRAY *allot_c_string(CELL capacity, CELL size)
+{
+       return allot_byte_array((capacity + 1) * size);
+}
+
+#define STRING_TO_MEMORY(type) \
+       void type##_string_to_memory(F_STRING *s, type *string) \
+       { \
+               CELL i; \
+               CELL capacity = string_capacity(s); \
+               for(i = 0; i < capacity; i++) \
+                       string[i] = string_nth(s,i); \
+       } \
+       void primitive_##type##_string_to_memory(void) \
+       { \
+               type *address = unbox_alien(); \
+               F_STRING *str = untag_string(dpop()); \
+               type##_string_to_memory(str,address); \
+       } \
+       F_BYTE_ARRAY *string_to_##type##_alien(F_STRING *s, bool check) \
+       { \
+               CELL capacity = string_capacity(s); \
+               F_BYTE_ARRAY *_c_str; \
+               if(check && !check_string(s,sizeof(type))) \
+                       general_error(ERROR_C_STRING,tag_object(s),F,NULL); \
+               REGISTER_UNTAGGED(s); \
+               _c_str = allot_c_string(capacity,sizeof(type)); \
+               UNREGISTER_UNTAGGED(s); \
+               type *c_str = (type*)(_c_str + 1); \
+               type##_string_to_memory(s,c_str); \
+               c_str[capacity] = 0; \
+               return _c_str; \
+       } \
+       type *to_##type##_string(F_STRING *s, bool check) \
+       { \
+               return (type*)(string_to_##type##_alien(s,check) + 1); \
+       } \
+       type *unbox_##type##_string(void) \
+       { \
+               return to_##type##_string(untag_string(dpop()),true); \
+       }
+
+STRING_TO_MEMORY(char);
+STRING_TO_MEMORY(u16);
+
+void primitive_string_nth(void)
+{
+       F_STRING *string = untag_object(dpop());
+       CELL index = untag_fixnum_fast(dpop());
+       dpush(tag_fixnum(string_nth(string,index)));
+}
+
+void primitive_set_string_nth(void)
+{
+       F_STRING *string = untag_object(dpop());
+       CELL index = untag_fixnum_fast(dpop());
+       CELL value = untag_fixnum_fast(dpop());
+       set_string_nth(string,index,value);
+}
+
+void primitive_set_string_nth_fast(void)
+{
+       F_STRING *string = untag_object(dpop());
+       CELL index = untag_fixnum_fast(dpop());
+       CELL value = untag_fixnum_fast(dpop());
+       set_string_nth_fast(string,index,value);
+}
+
+void primitive_set_string_nth_slow(void)
+{
+       F_STRING *string = untag_object(dpop());
+       CELL index = untag_fixnum_fast(dpop());
+       CELL value = untag_fixnum_fast(dpop());
+       set_string_nth_slow(string,index,value);
+}
diff --git a/vm/strings.h b/vm/strings.h
new file mode 100644 (file)
index 0000000..d16a85e
--- /dev/null
@@ -0,0 +1,50 @@
+INLINE CELL string_capacity(F_STRING* str)
+{
+       return untag_fixnum_fast(str->length);
+}
+
+INLINE CELL string_size(CELL size)
+{
+       return sizeof(F_STRING) + size;
+}
+
+#define BREF(byte_array,index) ((CELL)byte_array + sizeof(F_BYTE_ARRAY) + (index))
+#define SREF(string,index) ((CELL)string + sizeof(F_STRING) + (index))
+
+INLINE F_STRING* untag_string(CELL tagged)
+{
+       type_check(STRING_TYPE,tagged);
+       return untag_object(tagged);
+}
+
+F_STRING* allot_string_internal(CELL capacity);
+F_STRING* allot_string(CELL capacity, CELL fill);
+void primitive_string(void);
+F_STRING *reallot_string(F_STRING *string, CELL capacity);
+void primitive_resize_string(void);
+
+F_STRING *memory_to_char_string(const char *string, CELL length);
+F_STRING *from_char_string(const char *c_string);
+DLLEXPORT void box_char_string(const char *c_string);
+
+F_STRING *memory_to_u16_string(const u16 *string, CELL length);
+F_STRING *from_u16_string(const u16 *c_string);
+DLLEXPORT void box_u16_string(const u16 *c_string);
+
+void char_string_to_memory(F_STRING *s, char *string);
+F_BYTE_ARRAY *string_to_char_alien(F_STRING *s, bool check);
+char* to_char_string(F_STRING *s, bool check);
+DLLEXPORT char *unbox_char_string(void);
+
+void u16_string_to_memory(F_STRING *s, u16 *string);
+F_BYTE_ARRAY *string_to_u16_alien(F_STRING *s, bool check);
+u16* to_u16_string(F_STRING *s, bool check);
+DLLEXPORT u16 *unbox_u16_string(void);
+
+/* String getters and setters */
+CELL string_nth(F_STRING* string, CELL index);
+void set_string_nth(F_STRING* string, CELL index, CELL value);
+
+void primitive_string_nth(void);
+void primitive_set_string_nth_slow(void);
+void primitive_set_string_nth_fast(void);
diff --git a/vm/tuples.c b/vm/tuples.c
new file mode 100644 (file)
index 0000000..c93bdf4
--- /dev/null
@@ -0,0 +1,35 @@
+#include "master.h"
+
+/* push a new tuple on the stack */
+F_TUPLE *allot_tuple(F_TUPLE_LAYOUT *layout)
+{
+       REGISTER_UNTAGGED(layout);
+       F_TUPLE *tuple = allot_object(TUPLE_TYPE,tuple_size(layout));
+       UNREGISTER_UNTAGGED(layout);
+       tuple->layout = tag_array((F_ARRAY *)layout);
+       return tuple;
+}
+
+void primitive_tuple(void)
+{
+       F_TUPLE_LAYOUT *layout = untag_object(dpop());
+       F_FIXNUM size = untag_fixnum_fast(layout->size);
+
+       F_TUPLE *tuple = allot_tuple(layout);
+       F_FIXNUM i;
+       for(i = size - 1; i >= 0; i--)
+               put(AREF(tuple,i),F);
+
+       dpush(tag_tuple(tuple));
+}
+
+/* push a new tuple on the stack, filling its slots from the stack */
+void primitive_tuple_boa(void)
+{
+       F_TUPLE_LAYOUT *layout = untag_object(dpop());
+       F_FIXNUM size = untag_fixnum_fast(layout->size);
+       F_TUPLE *tuple = allot_tuple(layout);
+       memcpy(tuple + 1,(CELL *)(ds - CELLS * (size - 1)),CELLS * size);
+       ds -= CELLS * size;
+       dpush(tag_tuple(tuple));
+}
diff --git a/vm/tuples.h b/vm/tuples.h
new file mode 100644 (file)
index 0000000..64b62e2
--- /dev/null
@@ -0,0 +1,25 @@
+INLINE CELL tag_tuple(F_TUPLE *tuple)
+{
+       return RETAG(tuple,TUPLE_TYPE);
+}
+
+INLINE CELL tuple_size(F_TUPLE_LAYOUT *layout)
+{
+       CELL size = untag_fixnum_fast(layout->size);
+       return sizeof(F_TUPLE) + size * CELLS;
+}
+
+INLINE CELL tuple_nth(F_TUPLE *tuple, CELL slot)
+{
+       return get(AREF(tuple,slot));
+}
+
+INLINE void set_tuple_nth(F_TUPLE *tuple, CELL slot, CELL value)
+{
+       put(AREF(tuple,slot),value);
+       write_barrier((CELL)tuple);
+}
+
+void primitive_tuple(void);
+void primitive_tuple_boa(void);
+void primitive_tuple_layout(void);
diff --git a/vm/types.c b/vm/types.c
deleted file mode 100755 (executable)
index 889de38..0000000
+++ /dev/null
@@ -1,608 +0,0 @@
-#include "master.h"
-
-/* FFI calls this */
-void box_boolean(bool value)
-{
-       dpush(value ? T : F);
-}
-
-/* FFI calls this */
-bool to_boolean(CELL value)
-{
-       return value != F;
-}
-
-CELL clone_object(CELL object)
-{
-       CELL size = object_size(object);
-       if(size == 0)
-               return object;
-       else
-       {
-               REGISTER_ROOT(object);
-               void *new_obj = allot_object(type_of(object),size);
-               UNREGISTER_ROOT(object);
-
-               CELL tag = TAG(object);
-               memcpy(new_obj,(void*)UNTAG(object),size);
-               return RETAG(new_obj,tag);
-       }
-}
-
-void primitive_clone(void)
-{
-       drepl(clone_object(dpeek()));
-}
-
-F_WORD *allot_word(CELL vocab, CELL name)
-{
-       REGISTER_ROOT(vocab);
-       REGISTER_ROOT(name);
-       F_WORD *word = allot_object(WORD_TYPE,sizeof(F_WORD));
-       UNREGISTER_ROOT(name);
-       UNREGISTER_ROOT(vocab);
-
-       word->hashcode = tag_fixnum((rand() << 16) ^ rand());
-       word->vocabulary = vocab;
-       word->name = name;
-       word->def = userenv[UNDEFINED_ENV];
-       word->props = F;
-       word->counter = tag_fixnum(0);
-       word->optimizedp = F;
-       word->subprimitive = F;
-       word->profiling = NULL;
-       word->code = NULL;
-
-       REGISTER_UNTAGGED(word);
-       jit_compile_word(word,word->def,true);
-       UNREGISTER_UNTAGGED(word);
-
-       REGISTER_UNTAGGED(word);
-       update_word_xt(word);
-       UNREGISTER_UNTAGGED(word);
-
-       if(profiling_p)
-               relocate_code_block(word->profiling);
-
-       return word;
-}
-
-/* <word> ( name vocabulary -- word ) */
-void primitive_word(void)
-{
-       CELL vocab = dpop();
-       CELL name = dpop();
-       dpush(tag_object(allot_word(vocab,name)));
-}
-
-/* word-xt ( word -- start end ) */
-void primitive_word_xt(void)
-{
-       F_WORD *word = untag_word(dpop());
-       F_CODE_BLOCK *code = (profiling_p ? word->profiling : word->code);
-       dpush(allot_cell((CELL)code + sizeof(F_CODE_BLOCK)));
-       dpush(allot_cell((CELL)code + code->block.size));
-}
-
-void primitive_wrapper(void)
-{
-       F_WRAPPER *wrapper = allot_object(WRAPPER_TYPE,sizeof(F_WRAPPER));
-       wrapper->object = dpeek();
-       drepl(tag_object(wrapper));
-}
-
-/* Arrays */
-
-/* the array is full of undefined data, and must be correctly filled before the
-next GC. size is in cells */
-F_ARRAY *allot_array_internal(CELL type, CELL capacity)
-{
-       F_ARRAY *array = allot_object(type,array_size(capacity));
-       array->capacity = tag_fixnum(capacity);
-       return array;
-}
-
-/* make a new array with an initial element */
-F_ARRAY *allot_array(CELL type, CELL capacity, CELL fill)
-{
-       int i;
-       REGISTER_ROOT(fill);
-       F_ARRAY* array = allot_array_internal(type, capacity);
-       UNREGISTER_ROOT(fill);
-       if(fill == 0)
-               memset((void*)AREF(array,0),'\0',capacity * CELLS);
-       else
-       {
-               /* No need for write barrier here. Either the object is in
-               the nursery, or it was allocated directly in tenured space
-               and the write barrier is already hit for us in that case. */
-               for(i = 0; i < capacity; i++)
-                       put(AREF(array,i),fill);
-       }
-       return array;
-}
-
-/* push a new array on the stack */
-void primitive_array(void)
-{
-       CELL initial = dpop();
-       CELL size = unbox_array_size();
-       dpush(tag_object(allot_array(ARRAY_TYPE,size,initial)));
-}
-
-CELL allot_array_1(CELL obj)
-{
-       REGISTER_ROOT(obj);
-       F_ARRAY *a = allot_array_internal(ARRAY_TYPE,1);
-       UNREGISTER_ROOT(obj);
-       set_array_nth(a,0,obj);
-       return tag_object(a);
-}
-
-CELL allot_array_2(CELL v1, CELL v2)
-{
-       REGISTER_ROOT(v1);
-       REGISTER_ROOT(v2);
-       F_ARRAY *a = allot_array_internal(ARRAY_TYPE,2);
-       UNREGISTER_ROOT(v2);
-       UNREGISTER_ROOT(v1);
-       set_array_nth(a,0,v1);
-       set_array_nth(a,1,v2);
-       return tag_object(a);
-}
-
-CELL allot_array_4(CELL v1, CELL v2, CELL v3, CELL v4)
-{
-       REGISTER_ROOT(v1);
-       REGISTER_ROOT(v2);
-       REGISTER_ROOT(v3);
-       REGISTER_ROOT(v4);
-       F_ARRAY *a = allot_array_internal(ARRAY_TYPE,4);
-       UNREGISTER_ROOT(v4);
-       UNREGISTER_ROOT(v3);
-       UNREGISTER_ROOT(v2);
-       UNREGISTER_ROOT(v1);
-       set_array_nth(a,0,v1);
-       set_array_nth(a,1,v2);
-       set_array_nth(a,2,v3);
-       set_array_nth(a,3,v4);
-       return tag_object(a);
-}
-
-F_ARRAY *reallot_array(F_ARRAY* array, CELL capacity)
-{
-       CELL to_copy = array_capacity(array);
-       if(capacity < to_copy)
-               to_copy = capacity;
-
-       REGISTER_UNTAGGED(array);
-       F_ARRAY* new_array = allot_array_internal(untag_header(array->header),capacity);
-       UNREGISTER_UNTAGGED(array);
-
-       memcpy(new_array + 1,array + 1,to_copy * CELLS);
-       memset((char *)AREF(new_array,to_copy),'\0',(capacity - to_copy) * CELLS);
-
-       return new_array;
-}
-
-void primitive_resize_array(void)
-{
-       F_ARRAY* array = untag_array(dpop());
-       CELL capacity = unbox_array_size();
-       dpush(tag_object(reallot_array(array,capacity)));
-}
-
-F_ARRAY *growable_array_add(F_ARRAY *result, CELL elt, CELL *result_count)
-{
-       REGISTER_ROOT(elt);
-
-       if(*result_count == array_capacity(result))
-       {
-               result = reallot_array(result,*result_count * 2);
-       }
-
-       UNREGISTER_ROOT(elt);
-       set_array_nth(result,*result_count,elt);
-       (*result_count)++;
-
-       return result;
-}
-
-F_ARRAY *growable_array_append(F_ARRAY *result, F_ARRAY *elts, CELL *result_count)
-{
-       REGISTER_UNTAGGED(elts);
-
-       CELL elts_size = array_capacity(elts);
-       CELL new_size = *result_count + elts_size;
-
-       if(new_size >= array_capacity(result))
-               result = reallot_array(result,new_size * 2);
-
-       UNREGISTER_UNTAGGED(elts);
-
-       write_barrier((CELL)result);
-
-       memcpy((void *)AREF(result,*result_count),(void *)AREF(elts,0),elts_size * CELLS);
-
-       *result_count += elts_size;
-
-       return result;
-}
-
-/* Byte arrays */
-
-/* must fill out array before next GC */
-F_BYTE_ARRAY *allot_byte_array_internal(CELL size)
-{
-       F_BYTE_ARRAY *array = allot_object(BYTE_ARRAY_TYPE,
-               byte_array_size(size));
-       array->capacity = tag_fixnum(size);
-       return array;
-}
-
-/* size is in bytes this time */
-F_BYTE_ARRAY *allot_byte_array(CELL size)
-{
-       F_BYTE_ARRAY *array = allot_byte_array_internal(size);
-       memset(array + 1,0,size);
-       return array;
-}
-
-/* push a new byte array on the stack */
-void primitive_byte_array(void)
-{
-       CELL size = unbox_array_size();
-       dpush(tag_object(allot_byte_array(size)));
-}
-
-void primitive_uninitialized_byte_array(void)
-{
-       CELL size = unbox_array_size();
-       dpush(tag_object(allot_byte_array_internal(size)));
-}
-
-F_BYTE_ARRAY *reallot_byte_array(F_BYTE_ARRAY *array, CELL capacity)
-{
-       CELL to_copy = array_capacity(array);
-       if(capacity < to_copy)
-               to_copy = capacity;
-
-       REGISTER_UNTAGGED(array);
-       F_BYTE_ARRAY *new_array = allot_byte_array_internal(capacity);
-       UNREGISTER_UNTAGGED(array);
-
-       memcpy(new_array + 1,array + 1,to_copy);
-
-       return new_array;
-}
-
-void primitive_resize_byte_array(void)
-{
-       F_BYTE_ARRAY* array = untag_byte_array(dpop());
-       CELL capacity = unbox_array_size();
-       dpush(tag_object(reallot_byte_array(array,capacity)));
-}
-
-F_BYTE_ARRAY *growable_byte_array_append(F_BYTE_ARRAY *result, void *elts, CELL len, CELL *result_count)
-{
-       CELL new_size = *result_count + len;
-
-       if(new_size >= byte_array_capacity(result))
-               result = reallot_byte_array(result,new_size * 2);
-
-       memcpy((void *)BREF(result,*result_count),elts,len);
-
-       *result_count = new_size;
-
-       return result;
-}
-
-/* Tuples */
-
-/* push a new tuple on the stack */
-F_TUPLE *allot_tuple(F_TUPLE_LAYOUT *layout)
-{
-       REGISTER_UNTAGGED(layout);
-       F_TUPLE *tuple = allot_object(TUPLE_TYPE,tuple_size(layout));
-       UNREGISTER_UNTAGGED(layout);
-       tuple->layout = tag_object(layout);
-       return tuple;
-}
-
-void primitive_tuple(void)
-{
-       F_TUPLE_LAYOUT *layout = untag_object(dpop());
-       F_FIXNUM size = untag_fixnum_fast(layout->size);
-
-       F_TUPLE *tuple = allot_tuple(layout);
-       F_FIXNUM i;
-       for(i = size - 1; i >= 0; i--)
-               put(AREF(tuple,i),F);
-
-       dpush(tag_tuple(tuple));
-}
-
-/* push a new tuple on the stack, filling its slots from the stack */
-void primitive_tuple_boa(void)
-{
-       F_TUPLE_LAYOUT *layout = untag_object(dpop());
-       F_FIXNUM size = untag_fixnum_fast(layout->size);
-       F_TUPLE *tuple = allot_tuple(layout);
-       memcpy(tuple + 1,(CELL *)(ds - CELLS * (size - 1)),CELLS * size);
-       ds -= CELLS * size;
-       dpush(tag_tuple(tuple));
-}
-
-/* Strings */
-CELL string_nth(F_STRING* string, CELL index)
-{
-       /* If high bit is set, the most significant 16 bits of the char
-       come from the aux vector. The least significant bit of the
-       corresponding aux vector entry is negated, so that we can
-       XOR the two components together and get the original code point
-       back. */
-       CELL ch = bget(SREF(string,index));
-       if((ch & 0x80) == 0)
-               return ch;
-       else
-       {
-               F_BYTE_ARRAY *aux = untag_object(string->aux);
-               return (cget(BREF(aux,index * sizeof(u16))) << 7) ^ ch;
-       }
-}
-
-void set_string_nth_fast(F_STRING* string, CELL index, CELL ch)
-{
-       bput(SREF(string,index),ch);
-}
-
-void set_string_nth_slow(F_STRING* string, CELL index, CELL ch)
-{
-       F_BYTE_ARRAY *aux;
-
-       bput(SREF(string,index),(ch & 0x7f) | 0x80);
-
-       if(string->aux == F)
-       {
-               REGISTER_UNTAGGED(string);
-               /* We don't need to pre-initialize the
-               byte array with any data, since we
-               only ever read from the aux vector
-               if the most significant bit of a
-               character is set. Initially all of
-               the bits are clear. */
-               aux = allot_byte_array_internal(
-                       untag_fixnum_fast(string->length)
-                       * sizeof(u16));
-               UNREGISTER_UNTAGGED(string);
-
-               write_barrier((CELL)string);
-               string->aux = tag_object(aux);
-       }
-       else
-               aux = untag_object(string->aux);
-
-       cput(BREF(aux,index * sizeof(u16)),(ch >> 7) ^ 1);
-}
-
-/* allocates memory */
-void set_string_nth(F_STRING* string, CELL index, CELL ch)
-{
-       if(ch <= 0x7f)
-               set_string_nth_fast(string,index,ch);
-       else
-               set_string_nth_slow(string,index,ch);
-}
-
-/* untagged */
-F_STRING* allot_string_internal(CELL capacity)
-{
-       F_STRING *string = allot_object(STRING_TYPE,string_size(capacity));
-
-       string->length = tag_fixnum(capacity);
-       string->hashcode = F;
-       string->aux = F;
-
-       return string;
-}
-
-/* allocates memory */
-void fill_string(F_STRING *string, CELL start, CELL capacity, CELL fill)
-{
-       if(fill <= 0x7f)
-               memset((void *)SREF(string,start),fill,capacity - start);
-       else
-       {
-               CELL i;
-
-               for(i = start; i < capacity; i++)
-               {
-                       REGISTER_UNTAGGED(string);
-                       set_string_nth(string,i,fill);
-                       UNREGISTER_UNTAGGED(string);
-               }
-       }
-}
-
-/* untagged */
-F_STRING *allot_string(CELL capacity, CELL fill)
-{
-       F_STRING* string = allot_string_internal(capacity);
-       REGISTER_UNTAGGED(string);
-       fill_string(string,0,capacity,fill);
-       UNREGISTER_UNTAGGED(string);
-       return string;
-}
-
-void primitive_string(void)
-{
-       CELL initial = to_cell(dpop());
-       CELL length = unbox_array_size();
-       dpush(tag_object(allot_string(length,initial)));
-}
-
-F_STRING* reallot_string(F_STRING* string, CELL capacity)
-{
-       CELL to_copy = string_capacity(string);
-       if(capacity < to_copy)
-               to_copy = capacity;
-
-       REGISTER_UNTAGGED(string);
-       F_STRING *new_string = allot_string_internal(capacity);
-       UNREGISTER_UNTAGGED(string);
-
-       memcpy(new_string + 1,string + 1,to_copy);
-
-       if(string->aux != F)
-       {
-               REGISTER_UNTAGGED(string);
-               REGISTER_UNTAGGED(new_string);
-               F_BYTE_ARRAY *new_aux = allot_byte_array(capacity * sizeof(u16));
-               UNREGISTER_UNTAGGED(new_string);
-               UNREGISTER_UNTAGGED(string);
-
-               write_barrier((CELL)new_string);
-               new_string->aux = tag_object(new_aux);
-
-               F_BYTE_ARRAY *aux = untag_object(string->aux);
-               memcpy(new_aux + 1,aux + 1,to_copy * sizeof(u16));
-       }
-
-       REGISTER_UNTAGGED(string);
-       REGISTER_UNTAGGED(new_string);
-       fill_string(new_string,to_copy,capacity,'\0');
-       UNREGISTER_UNTAGGED(new_string);
-       UNREGISTER_UNTAGGED(string);
-
-       return new_string;
-}
-
-void primitive_resize_string(void)
-{
-       F_STRING* string = untag_string(dpop());
-       CELL capacity = unbox_array_size();
-       dpush(tag_object(reallot_string(string,capacity)));
-}
-
-/* Some ugly macros to prevent a 2x code duplication */
-
-#define MEMORY_TO_STRING(type,utype) \
-       F_STRING *memory_to_##type##_string(const type *string, CELL length) \
-       { \
-               REGISTER_C_STRING(string); \
-               F_STRING* s = allot_string_internal(length); \
-               UNREGISTER_C_STRING(string); \
-               CELL i; \
-               for(i = 0; i < length; i++) \
-               { \
-                       REGISTER_UNTAGGED(s); \
-                       set_string_nth(s,i,(utype)*string); \
-                       UNREGISTER_UNTAGGED(s); \
-                       string++; \
-               } \
-               return s; \
-       } \
-       F_STRING *from_##type##_string(const type *str) \
-       { \
-               CELL length = 0; \
-               const type *scan = str; \
-               while(*scan++) length++; \
-               return memory_to_##type##_string(str,length); \
-       } \
-       void box_##type##_string(const type *str) \
-       { \
-               dpush(str ? tag_object(from_##type##_string(str)) : F); \
-       }
-
-MEMORY_TO_STRING(char,u8)
-MEMORY_TO_STRING(u16,u16)
-MEMORY_TO_STRING(u32,u32)
-
-bool check_string(F_STRING *s, CELL max)
-{
-       CELL capacity = string_capacity(s);
-       CELL i;
-       for(i = 0; i < capacity; i++)
-       {
-               CELL ch = string_nth(s,i);
-               if(ch == '\0' || ch >= (1 << (max * 8)))
-                       return false;
-       }
-       return true;
-}
-
-F_BYTE_ARRAY *allot_c_string(CELL capacity, CELL size)
-{
-       return allot_byte_array((capacity + 1) * size);
-}
-
-#define STRING_TO_MEMORY(type) \
-       void type##_string_to_memory(F_STRING *s, type *string) \
-       { \
-               CELL i; \
-               CELL capacity = string_capacity(s); \
-               for(i = 0; i < capacity; i++) \
-                       string[i] = string_nth(s,i); \
-       } \
-       void primitive_##type##_string_to_memory(void) \
-       { \
-               type *address = unbox_alien(); \
-               F_STRING *str = untag_string(dpop()); \
-               type##_string_to_memory(str,address); \
-       } \
-       F_BYTE_ARRAY *string_to_##type##_alien(F_STRING *s, bool check) \
-       { \
-               CELL capacity = string_capacity(s); \
-               F_BYTE_ARRAY *_c_str; \
-               if(check && !check_string(s,sizeof(type))) \
-                       general_error(ERROR_C_STRING,tag_object(s),F,NULL); \
-               REGISTER_UNTAGGED(s); \
-               _c_str = allot_c_string(capacity,sizeof(type)); \
-               UNREGISTER_UNTAGGED(s); \
-               type *c_str = (type*)(_c_str + 1); \
-               type##_string_to_memory(s,c_str); \
-               c_str[capacity] = 0; \
-               return _c_str; \
-       } \
-       type *to_##type##_string(F_STRING *s, bool check) \
-       { \
-               return (type*)(string_to_##type##_alien(s,check) + 1); \
-       } \
-       type *unbox_##type##_string(void) \
-       { \
-               return to_##type##_string(untag_string(dpop()),true); \
-       }
-
-STRING_TO_MEMORY(char);
-STRING_TO_MEMORY(u16);
-
-void primitive_string_nth(void)
-{
-       F_STRING *string = untag_object(dpop());
-       CELL index = untag_fixnum_fast(dpop());
-       dpush(tag_fixnum(string_nth(string,index)));
-}
-
-void primitive_set_string_nth(void)
-{
-       F_STRING *string = untag_object(dpop());
-       CELL index = untag_fixnum_fast(dpop());
-       CELL value = untag_fixnum_fast(dpop());
-       set_string_nth(string,index,value);
-}
-
-void primitive_set_string_nth_fast(void)
-{
-       F_STRING *string = untag_object(dpop());
-       CELL index = untag_fixnum_fast(dpop());
-       CELL value = untag_fixnum_fast(dpop());
-       set_string_nth_fast(string,index,value);
-}
-
-void primitive_set_string_nth_slow(void)
-{
-       F_STRING *string = untag_object(dpop());
-       CELL index = untag_fixnum_fast(dpop());
-       CELL value = untag_fixnum_fast(dpop());
-       set_string_nth_slow(string,index,value);
-}
diff --git a/vm/types.h b/vm/types.h
deleted file mode 100755 (executable)
index 2775f57..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-/* Inline functions */
-INLINE CELL array_size(CELL size)
-{
-       return sizeof(F_ARRAY) + size * CELLS;
-}
-
-INLINE CELL string_capacity(F_STRING* str)
-{
-       return untag_fixnum_fast(str->length);
-}
-
-INLINE CELL string_size(CELL size)
-{
-       return sizeof(F_STRING) + size;
-}
-
-DEFINE_UNTAG(F_BYTE_ARRAY,BYTE_ARRAY_TYPE,byte_array)
-
-INLINE CELL byte_array_capacity(F_BYTE_ARRAY *array)
-{
-       return untag_fixnum_fast(array->capacity);
-}
-
-INLINE CELL byte_array_size(CELL size)
-{
-       return sizeof(F_BYTE_ARRAY) + size;
-}
-
-INLINE CELL callstack_size(CELL size)
-{
-       return sizeof(F_CALLSTACK) + size;
-}
-
-DEFINE_UNTAG(F_CALLSTACK,CALLSTACK_TYPE,callstack)
-
-INLINE CELL tag_boolean(CELL untagged)
-{
-       return (untagged == false ? F : T);
-}
-
-DEFINE_UNTAG(F_ARRAY,ARRAY_TYPE,array)
-
-#define AREF(array,index) ((CELL)(array) + sizeof(F_ARRAY) + (index) * CELLS)
-#define UNAREF(array,ptr) (((CELL)(ptr)-(CELL)(array)-sizeof(F_ARRAY)) / CELLS)
-
-INLINE CELL array_nth(F_ARRAY *array, CELL slot)
-{
-       return get(AREF(array,slot));
-}
-
-INLINE void set_array_nth(F_ARRAY *array, CELL slot, CELL value)
-{
-       put(AREF(array,slot),value);
-       write_barrier((CELL)array);
-}
-
-INLINE CELL array_capacity(F_ARRAY* array)
-{
-       return array->capacity >> TAG_BITS;
-}
-
-#define BREF(byte_array,index) ((CELL)byte_array + sizeof(F_BYTE_ARRAY) + (index))
-#define SREF(string,index) ((CELL)string + sizeof(F_STRING) + (index))
-
-INLINE F_STRING* untag_string(CELL tagged)
-{
-       type_check(STRING_TYPE,tagged);
-       return untag_object(tagged);
-}
-
-DEFINE_UNTAG(F_QUOTATION,QUOTATION_TYPE,quotation)
-
-DEFINE_UNTAG(F_WORD,WORD_TYPE,word)
-
-INLINE CELL tag_tuple(F_TUPLE *tuple)
-{
-       return RETAG(tuple,TUPLE_TYPE);
-}
-
-INLINE F_TUPLE *untag_tuple(CELL object)
-{
-       type_check(TUPLE_TYPE,object);
-       return untag_object(object);
-}
-
-INLINE CELL tuple_size(F_TUPLE_LAYOUT *layout)
-{
-       CELL size = untag_fixnum_fast(layout->size);
-       return sizeof(F_TUPLE) + size * CELLS;
-}
-
-INLINE CELL tuple_nth(F_TUPLE *tuple, CELL slot)
-{
-       return get(AREF(tuple,slot));
-}
-
-INLINE void set_tuple_nth(F_TUPLE *tuple, CELL slot, CELL value)
-{
-       put(AREF(tuple,slot),value);
-       write_barrier((CELL)tuple);
-}
-
-/* Prototypes */
-DLLEXPORT void box_boolean(bool value);
-DLLEXPORT bool to_boolean(CELL value);
-
-F_ARRAY *allot_array_internal(CELL type, CELL capacity);
-F_ARRAY *allot_array(CELL type, CELL capacity, CELL fill);
-F_BYTE_ARRAY *allot_byte_array(CELL size);
-
-CELL allot_array_1(CELL obj);
-CELL allot_array_2(CELL v1, CELL v2);
-CELL allot_array_4(CELL v1, CELL v2, CELL v3, CELL v4);
-
-void primitive_array(void);
-void primitive_tuple(void);
-void primitive_tuple_boa(void);
-void primitive_tuple_layout(void);
-void primitive_byte_array(void);
-void primitive_uninitialized_byte_array(void);
-void primitive_clone(void);
-
-F_ARRAY *reallot_array(F_ARRAY* array, CELL capacity);
-F_BYTE_ARRAY *reallot_byte_array(F_BYTE_ARRAY *array, CELL capacity);
-void primitive_resize_array(void);
-void primitive_resize_byte_array(void);
-
-F_STRING* allot_string_internal(CELL capacity);
-F_STRING* allot_string(CELL capacity, CELL fill);
-void primitive_uninitialized_string(void);
-void primitive_string(void);
-F_STRING *reallot_string(F_STRING *string, CELL capacity);
-void primitive_resize_string(void);
-
-F_STRING *memory_to_char_string(const char *string, CELL length);
-F_STRING *from_char_string(const char *c_string);
-DLLEXPORT void box_char_string(const char *c_string);
-
-F_STRING *memory_to_u16_string(const u16 *string, CELL length);
-F_STRING *from_u16_string(const u16 *c_string);
-DLLEXPORT void box_u16_string(const u16 *c_string);
-
-void char_string_to_memory(F_STRING *s, char *string);
-F_BYTE_ARRAY *string_to_char_alien(F_STRING *s, bool check);
-char* to_char_string(F_STRING *s, bool check);
-DLLEXPORT char *unbox_char_string(void);
-
-void u16_string_to_memory(F_STRING *s, u16 *string);
-F_BYTE_ARRAY *string_to_u16_alien(F_STRING *s, bool check);
-u16* to_u16_string(F_STRING *s, bool check);
-DLLEXPORT u16 *unbox_u16_string(void);
-
-/* String getters and setters */
-CELL string_nth(F_STRING* string, CELL index);
-void set_string_nth(F_STRING* string, CELL index, CELL value);
-
-void primitive_string_nth(void);
-void primitive_set_string_nth_slow(void);
-void primitive_set_string_nth_fast(void);
-
-F_WORD *allot_word(CELL vocab, CELL name);
-void primitive_word(void);
-void primitive_word_xt(void);
-
-void primitive_wrapper(void);
-
-/* Macros to simulate a vector in C */
-#define GROWABLE_ARRAY(result) \
-       CELL result##_count = 0; \
-       CELL result = tag_object(allot_array(ARRAY_TYPE,100,F))
-
-F_ARRAY *growable_array_add(F_ARRAY *result, CELL elt, CELL *result_count);
-
-#define GROWABLE_ARRAY_ADD(result,elt) \
-       result = tag_object(growable_array_add(untag_object(result),elt,&result##_count))
-
-F_ARRAY *growable_array_append(F_ARRAY *result, F_ARRAY *elts, CELL *result_count);
-
-#define GROWABLE_ARRAY_APPEND(result,elts) \
-       result = tag_object(growable_array_append(untag_object(result),elts,&result##_count))
-
-#define GROWABLE_ARRAY_TRIM(result) \
-       result = tag_object(reallot_array(untag_object(result),result##_count))
-
-/* Macros to simulate a byte vector in C */
-#define GROWABLE_BYTE_ARRAY(result) \
-       CELL result##_count = 0; \
-       CELL result = tag_object(allot_byte_array(100))
-
-F_ARRAY *growable_byte_array_append(F_BYTE_ARRAY *result, void *elts, CELL len, CELL *result_count);
-
-#define GROWABLE_BYTE_ARRAY_APPEND(result,elts,len) \
-       result = tag_object(growable_byte_array_append(untag_object(result),elts,len,&result##_count))
-
-#define GROWABLE_BYTE_ARRAY_TRIM(result) \
-       result = tag_object(reallot_byte_array(untag_object(result),result##_count))
index d97b540884b8a7e3bab9a38598d4d548151e14d5..ac52772b4e4ce56f4c0d0b129beb9c275372c161 100755 (executable)
@@ -50,6 +50,6 @@ void print_fixnum(F_FIXNUM x)
 CELL read_cell_hex(void)
 {
        CELL cell;
-       scanf(CELL_HEX_FORMAT,&cell);
+       if(scanf(CELL_HEX_FORMAT,&cell) < 0) exit(1);
        return cell;
 };
diff --git a/vm/words.c b/vm/words.c
new file mode 100644 (file)
index 0000000..615c11e
--- /dev/null
@@ -0,0 +1,82 @@
+#include "master.h"
+
+F_WORD *allot_word(CELL vocab, CELL name)
+{
+       REGISTER_ROOT(vocab);
+       REGISTER_ROOT(name);
+       F_WORD *word = allot_object(WORD_TYPE,sizeof(F_WORD));
+       UNREGISTER_ROOT(name);
+       UNREGISTER_ROOT(vocab);
+
+       word->hashcode = tag_fixnum((rand() << 16) ^ rand());
+       word->vocabulary = vocab;
+       word->name = name;
+       word->def = userenv[UNDEFINED_ENV];
+       word->props = F;
+       word->counter = tag_fixnum(0);
+       word->direct_entry_def = F;
+       word->subprimitive = F;
+       word->profiling = NULL;
+       word->code = NULL;
+
+       REGISTER_UNTAGGED(word);
+       jit_compile_word(word,word->def,true);
+       UNREGISTER_UNTAGGED(word);
+
+       REGISTER_UNTAGGED(word);
+       update_word_xt(word);
+       UNREGISTER_UNTAGGED(word);
+
+       if(profiling_p)
+               relocate_code_block(word->profiling);
+
+       return word;
+}
+
+/* <word> ( name vocabulary -- word ) */
+void primitive_word(void)
+{
+       CELL vocab = dpop();
+       CELL name = dpop();
+       dpush(tag_object(allot_word(vocab,name)));
+}
+
+/* word-xt ( word -- start end ) */
+void primitive_word_xt(void)
+{
+       F_WORD *word = untag_word(dpop());
+       F_CODE_BLOCK *code = (profiling_p ? word->profiling : word->code);
+       dpush(allot_cell((CELL)code + sizeof(F_CODE_BLOCK)));
+       dpush(allot_cell((CELL)code + code->block.size));
+}
+
+/* Allocates memory */
+void update_word_xt(F_WORD *word)
+{
+       if(profiling_p)
+       {
+               if(!word->profiling)
+               {
+                       REGISTER_UNTAGGED(word);
+                       F_CODE_BLOCK *profiling = compile_profiling_stub(tag_object(word));
+                       UNREGISTER_UNTAGGED(word);
+                       word->profiling = profiling;
+               }
+
+               word->xt = (XT)(word->profiling + 1);
+       }
+       else
+               word->xt = (XT)(word->code + 1);
+}
+
+void primitive_optimized_p(void)
+{
+       drepl(tag_boolean(word_optimized_p(untag_word(dpeek()))));
+}
+
+void primitive_wrapper(void)
+{
+       F_WRAPPER *wrapper = allot_object(WRAPPER_TYPE,sizeof(F_WRAPPER));
+       wrapper->object = dpeek();
+       drepl(tag_object(wrapper));
+}
diff --git a/vm/words.h b/vm/words.h
new file mode 100644 (file)
index 0000000..aa86c87
--- /dev/null
@@ -0,0 +1,16 @@
+DEFINE_UNTAG(F_WORD,WORD_TYPE,word)
+
+F_WORD *allot_word(CELL vocab, CELL name);
+
+void primitive_word(void);
+void primitive_word_xt(void);
+void update_word_xt(F_WORD *word);
+
+INLINE bool word_optimized_p(F_WORD *word)
+{
+       return word->code->block.type == WORD_TYPE;
+}
+
+void primitive_optimized_p(void);
+
+void primitive_wrapper(void);