]> gitweb.factorcode.org Git - factor.git/commitdiff
Merge branch 'master' of http://factorcode.org/git/factor into morse
authorAlex Chapman <chapman.alex@gmail.com>
Wed, 23 Apr 2008 12:30:00 +0000 (22:30 +1000)
committerAlex Chapman <chapman.alex@gmail.com>
Wed, 23 Apr 2008 12:30:00 +0000 (22:30 +1000)
Conflicts:

extra/semantic-db/semantic-db.factor

325 files changed:
.gitignore
build-support/factor.sh
core/alien/alien.factor
core/alien/arrays/arrays-docs.factor
core/alien/arrays/arrays.factor
core/alien/c-types/c-types-docs.factor
core/alien/c-types/c-types-tests.factor
core/alien/c-types/c-types.factor
core/alien/compiler/compiler-tests.factor
core/alien/compiler/compiler.factor
core/alien/remote-control/remote-control.factor
core/alien/strings/strings-docs.factor [new file with mode: 0644]
core/alien/strings/strings-tests.factor [new file with mode: 0644]
core/alien/strings/strings.factor [new file with mode: 0644]
core/alien/structs/structs-tests.factor
core/alien/structs/structs.factor
core/alien/syntax/syntax.factor
core/bit-vectors/bit-vectors-docs.factor [deleted file]
core/bit-vectors/bit-vectors-tests.factor [deleted file]
core/bit-vectors/bit-vectors.factor [deleted file]
core/bit-vectors/summary.txt [deleted file]
core/bit-vectors/tags.txt [deleted file]
core/bootstrap/primitives.factor
core/bootstrap/stage2.factor
core/bootstrap/syntax.factor
core/byte-vectors/byte-vectors-docs.factor [deleted file]
core/byte-vectors/byte-vectors-tests.factor [deleted file]
core/byte-vectors/byte-vectors.factor [deleted file]
core/byte-vectors/summary.txt [deleted file]
core/byte-vectors/tags.txt [deleted file]
core/classes/algebra/algebra-tests.factor
core/classes/algebra/algebra.factor
core/classes/tuple/tuple-tests.factor
core/combinators/combinators.factor
core/compiler/tests/intrinsics.factor
core/compiler/tests/simple.factor
core/compiler/tests/templates-early.factor
core/compiler/tests/templates.factor
core/cpu/architecture/architecture.factor
core/cpu/ppc/allot/allot.factor
core/cpu/ppc/architecture/architecture.factor
core/cpu/ppc/intrinsics/intrinsics.factor
core/cpu/x86/32/32.factor
core/cpu/x86/64/64.factor
core/cpu/x86/allot/allot.factor
core/cpu/x86/architecture/architecture.factor
core/cpu/x86/intrinsics/intrinsics.factor
core/cpu/x86/sse2/sse2.factor
core/float-vectors/float-vectors-docs.factor [deleted file]
core/float-vectors/float-vectors-tests.factor [deleted file]
core/float-vectors/float-vectors.factor [deleted file]
core/float-vectors/summary.txt [deleted file]
core/float-vectors/tags.txt [deleted file]
core/generator/fixup/fixup-docs.factor
core/generator/fixup/fixup.factor
core/generator/generator.factor
core/generator/registers/registers.factor
core/generic/generic.factor
core/generic/standard/engines/tuple/tuple.factor
core/generic/standard/standard-tests.factor
core/inference/backend/backend-docs.factor
core/inference/backend/backend.factor
core/inference/class/class-tests.factor
core/inference/class/class.factor
core/inference/dataflow/dataflow.factor
core/inference/known-words/known-words.factor
core/io/encodings/encodings-docs.factor
core/io/encodings/utf16/.utf16.factor.swo [new file with mode: 0644]
core/io/encodings/utf16/authors.txt [new file with mode: 0644]
core/io/encodings/utf16/summary.txt [new file with mode: 0644]
core/io/encodings/utf16/tags.txt [new file with mode: 0644]
core/io/encodings/utf16/utf16-docs.factor [new file with mode: 0644]
core/io/encodings/utf16/utf16-tests.factor [new file with mode: 0755]
core/io/encodings/utf16/utf16.factor [new file with mode: 0755]
core/io/streams/memory/memory.factor [new file with mode: 0644]
core/math/integers/integers-tests.factor
core/math/intervals/intervals.factor
core/math/math-docs.factor
core/math/math.factor
core/optimizer/backend/backend.factor
core/optimizer/collect/collect.factor [new file with mode: 0644]
core/optimizer/control/control-tests.factor
core/optimizer/control/control.factor
core/optimizer/def-use/def-use-tests.factor
core/optimizer/def-use/def-use.factor
core/optimizer/inlining/inlining-tests.factor [new file with mode: 0644]
core/optimizer/inlining/inlining.factor
core/optimizer/known-words/known-words.factor
core/optimizer/math/math.factor
core/optimizer/math/partial/partial-tests.factor [new file with mode: 0644]
core/optimizer/math/partial/partial.factor [new file with mode: 0644]
core/optimizer/optimizer-tests.factor
core/optimizer/optimizer.factor
core/prettyprint/backend/backend.factor
core/prettyprint/config/config.factor
core/prettyprint/prettyprint.factor
core/prettyprint/sections/sections.factor
core/sequences/sequences-docs.factor
core/sequences/sequences-tests.factor
core/sequences/sequences.factor
core/syntax/syntax-docs.factor
core/syntax/syntax.factor
core/threads/threads-docs.factor
core/threads/threads-tests.factor
core/threads/threads.factor
extra/benchmark/binary-trees/binary-trees.factor [new file with mode: 0644]
extra/benchmark/dispatch2/dispatch2.factor
extra/benchmark/dispatch3/dispatch3.factor
extra/benchmark/recursive/recursive.factor
extra/benchmark/spectral-norm/spectral-norm.factor
extra/bit-vectors/bit-vectors-docs.factor [new file with mode: 0755]
extra/bit-vectors/bit-vectors-tests.factor [new file with mode: 0755]
extra/bit-vectors/bit-vectors.factor [new file with mode: 0755]
extra/bit-vectors/summary.txt [new file with mode: 0644]
extra/bit-vectors/tags.txt [new file with mode: 0644]
extra/builder/cleanup/cleanup.factor
extra/builder/common/common.factor
extra/builder/email/email.factor
extra/byte-vectors/byte-vectors-docs.factor [new file with mode: 0755]
extra/byte-vectors/byte-vectors-tests.factor [new file with mode: 0755]
extra/byte-vectors/byte-vectors.factor [new file with mode: 0755]
extra/byte-vectors/summary.txt [new file with mode: 0644]
extra/byte-vectors/tags.txt [new file with mode: 0644]
extra/calendar/calendar-tests.factor
extra/calendar/calendar.factor
extra/calendar/format/format-tests.factor
extra/calendar/format/format.factor
extra/cocoa/messages/messages.factor
extra/cocoa/subclassing/subclassing.factor
extra/columns/authors.txt [new file with mode: 0644]
extra/columns/columns-docs.factor [new file with mode: 0644]
extra/columns/columns-tests.factor [new file with mode: 0644]
extra/columns/columns.factor [new file with mode: 0644]
extra/columns/summary.txt [new file with mode: 0644]
extra/columns/tags.txt [new file with mode: 0644]
extra/core-foundation/core-foundation.factor
extra/core-foundation/fsevents/fsevents.factor
extra/db/db.factor
extra/db/postgresql/lib/lib.factor
extra/db/postgresql/postgresql.factor
extra/db/queries/queries.factor [new file with mode: 0644]
extra/db/sql/sql-tests.factor
extra/db/sql/sql.factor
extra/db/sqlite/ffi/ffi.factor
extra/db/sqlite/lib/lib.factor
extra/db/sqlite/sqlite.factor
extra/db/tuples/tuples-tests.factor
extra/db/tuples/tuples.factor
extra/db/types/types.factor
extra/editors/vim/generate-syntax/generate-syntax.factor
extra/editors/vim/vim.factor
extra/farkup/farkup-tests.factor
extra/farkup/farkup.factor
extra/float-vectors/float-vectors-docs.factor [new file with mode: 0755]
extra/float-vectors/float-vectors-tests.factor [new file with mode: 0755]
extra/float-vectors/float-vectors.factor [new file with mode: 0755]
extra/float-vectors/summary.txt [new file with mode: 0644]
extra/float-vectors/tags.txt [new file with mode: 0644]
extra/fry/fry-tests.factor
extra/fry/fry.factor
extra/hardware-info/macosx/macosx.factor
extra/hardware-info/windows/nt/nt.factor
extra/hardware-info/windows/windows.factor
extra/help/handbook/handbook.factor
extra/help/help.factor
extra/html/elements/elements.factor
extra/http/client/client-tests.factor
extra/http/client/client.factor
extra/http/http-tests.factor
extra/http/http.factor
extra/http/server/actions/actions-tests.factor
extra/http/server/auth/login/boilerplate.xml [new file with mode: 0644]
extra/http/server/auth/login/edit-profile.fhtml [deleted file]
extra/http/server/auth/login/edit-profile.xml [new file with mode: 0644]
extra/http/server/auth/login/login.factor
extra/http/server/auth/login/login.fhtml [deleted file]
extra/http/server/auth/login/login.xml [new file with mode: 0644]
extra/http/server/auth/login/recover-1.fhtml [deleted file]
extra/http/server/auth/login/recover-1.xml [new file with mode: 0644]
extra/http/server/auth/login/recover-2.fhtml [deleted file]
extra/http/server/auth/login/recover-2.xml [new file with mode: 0644]
extra/http/server/auth/login/recover-3.fhtml [deleted file]
extra/http/server/auth/login/recover-3.xml [new file with mode: 0644]
extra/http/server/auth/login/recover-4.fhtml [deleted file]
extra/http/server/auth/login/recover-4.xml [new file with mode: 0755]
extra/http/server/auth/login/register.fhtml [deleted file]
extra/http/server/auth/login/register.xml [new file with mode: 0644]
extra/http/server/boilerplate/boilerplate.factor [new file with mode: 0644]
extra/http/server/components/components-tests.factor
extra/http/server/components/components.factor
extra/http/server/components/farkup/farkup.factor
extra/http/server/crud/crud.factor
extra/http/server/forms/forms.factor
extra/http/server/server.factor
extra/http/server/templating/chloe/chloe-tests.factor [new file with mode: 0644]
extra/http/server/templating/chloe/chloe.factor [new file with mode: 0644]
extra/http/server/templating/chloe/test/test1.xml [new file with mode: 0644]
extra/http/server/templating/chloe/test/test2.xml [new file with mode: 0644]
extra/http/server/templating/chloe/test/test3-aux.xml [new file with mode: 0644]
extra/http/server/templating/chloe/test/test3.xml [new file with mode: 0644]
extra/http/server/templating/chloe/test/test4.xml [new file with mode: 0644]
extra/http/server/templating/chloe/test/test5.xml [new file with mode: 0644]
extra/http/server/templating/chloe/test/test6.xml [new file with mode: 0644]
extra/http/server/templating/chloe/test/test7.xml [new file with mode: 0644]
extra/http/server/templating/fhtml/fhtml-tests.factor
extra/http/server/templating/fhtml/fhtml.factor
extra/http/server/templating/templating.factor [new file with mode: 0644]
extra/http/server/validators/validators-tests.factor
extra/http/server/validators/validators.factor
extra/io/encodings/utf16/.utf16.factor.swo [deleted file]
extra/io/encodings/utf16/authors.txt [deleted file]
extra/io/encodings/utf16/summary.txt [deleted file]
extra/io/encodings/utf16/tags.txt [deleted file]
extra/io/encodings/utf16/utf16-docs.factor [deleted file]
extra/io/encodings/utf16/utf16-tests.factor [deleted file]
extra/io/encodings/utf16/utf16.factor [deleted file]
extra/io/launcher/launcher-docs.factor
extra/io/launcher/launcher.factor
extra/io/monitors/monitors-tests.factor
extra/io/monitors/recursive/recursive.factor
extra/io/sockets/impl/impl.factor
extra/io/unix/linux/monitors/monitors.factor
extra/io/unix/sockets/sockets.factor
extra/io/windows/nt/files/files.factor
extra/locals/backend/backend-tests.factor [new file with mode: 0644]
extra/locals/backend/backend.factor [new file with mode: 0644]
extra/locals/locals-tests.factor
extra/locals/locals.factor
extra/math/fft/fft.factor
extra/math/functions/functions-docs.factor
extra/math/functions/functions-tests.factor
extra/math/functions/functions.factor
extra/math/haar/haar.factor
extra/math/ranges/ranges.factor
extra/newfx/newfx.factor
extra/odbc/odbc.factor
extra/opengl/shaders/shaders.factor
extra/openssl/openssl-tests.factor
extra/openssl/openssl.factor
extra/oracle/oracle.factor
extra/project-euler/076/076.factor [new file with mode: 0644]
extra/project-euler/116/116.factor [new file with mode: 0644]
extra/project-euler/117/117.factor [new file with mode: 0644]
extra/project-euler/148/148.factor [new file with mode: 0644]
extra/project-euler/150/150.factor [new file with mode: 0644]
extra/project-euler/164/164.factor [new file with mode: 0644]
extra/project-euler/190/190.factor [new file with mode: 0644]
extra/random/blum-blum-shub/blum-blum-shub-tests.factor
extra/random/blum-blum-shub/blum-blum-shub.factor
extra/regexp/regexp-tests.factor
extra/regexp/regexp.factor
extra/rss/rss-tests.factor
extra/rss/rss.factor
extra/semantic-db/semantic-db.factor
extra/sequences/lib/lib.factor
extra/shell/parser/parser.factor [new file with mode: 0644]
extra/shell/shell.factor [new file with mode: 0644]
extra/sudoku/sudoku.factor
extra/tools/deploy/backend/backend.factor
extra/tools/deploy/deploy-docs.factor
extra/tools/deploy/deploy.factor
extra/tools/deploy/macosx/macosx.factor
extra/tools/deploy/unix/authors.txt [new file with mode: 0644]
extra/tools/deploy/unix/summary.txt [new file with mode: 0644]
extra/tools/deploy/unix/tags.txt [new file with mode: 0644]
extra/tools/deploy/unix/unix.factor [new file with mode: 0644]
extra/tools/deploy/windows/windows.factor
extra/tools/walker/walker.factor
extra/ui/cocoa/views/views.factor
extra/ui/commands/commands.factor
extra/ui/gadgets/grids/grids.factor
extra/ui/gadgets/scrollers/scrollers.factor
extra/ui/gadgets/worlds/worlds.factor
extra/ui/gestures/gestures.factor
extra/ui/tools/listener/listener.factor
extra/ui/tools/walker/walker-docs.factor
extra/ui/tools/workspace/workspace.factor
extra/ui/windows/windows.factor
extra/ui/x11/x11.factor
extra/unix/linux/ifreq/ifreq.factor
extra/unix/process/process.factor
extra/update/update.factor [new file with mode: 0644]
extra/webapps/factor-website/factor-website.factor [new file with mode: 0644]
extra/webapps/factor-website/page.xml [new file with mode: 0644]
extra/webapps/planet/admin.xml [new file with mode: 0644]
extra/webapps/planet/authors.txt [new file with mode: 0755]
extra/webapps/planet/blog-admin-link.xml [new file with mode: 0644]
extra/webapps/planet/edit-blog.xml [new file with mode: 0644]
extra/webapps/planet/entry-summary.xml [new file with mode: 0644]
extra/webapps/planet/entry.xml [new file with mode: 0644]
extra/webapps/planet/planet.css [new file with mode: 0644]
extra/webapps/planet/planet.factor [new file with mode: 0755]
extra/webapps/planet/planet.xml [new file with mode: 0644]
extra/webapps/planet/postings-summary.xml [new file with mode: 0644]
extra/webapps/planet/postings.xml [new file with mode: 0644]
extra/webapps/planet/view-blog.xml [new file with mode: 0644]
extra/webapps/todo/edit-todo.xml [new file with mode: 0644]
extra/webapps/todo/todo-list.xml [new file with mode: 0644]
extra/webapps/todo/todo-summary.xml [new file with mode: 0644]
extra/webapps/todo/todo.css [new file with mode: 0644]
extra/webapps/todo/todo.factor [new file with mode: 0755]
extra/webapps/todo/todo.xml [new file with mode: 0644]
extra/webapps/todo/view-todo.xml [new file with mode: 0644]
extra/windows/ole32/ole32.factor
extra/windows/shell32/shell32.factor
extra/windows/types/types.factor
extra/windows/windows.factor
extra/windows/winsock/winsock.factor
extra/x/x.factor
extra/x11/clipboard/clipboard.factor
extra/x11/xlib/xlib.factor
extra/xml/writer/writer.factor
extra/xmode/catalog/catalog.factor
vm/data_gc.c
vm/data_gc.h
vm/debug.c
vm/errors.c
vm/ffi_test.c
vm/ffi_test.h
vm/os-macosx-ppc.h
vm/os-macosx-x86.32.h
vm/os-macosx-x86.64.h
vm/primitives.c
vm/types.c
vm/types.h

index f2cf3de1192bd8a28d8ed4143e8658d9ed6a02bf..290f075aae67d3add4bfbf0da1b906b3a535bcac 100644 (file)
@@ -2,6 +2,7 @@
 _darcs
 *.obj
 *.o
+*.s
 *.exe
 Factor/factor
 *.a
index 4bcd9e3086222d8957db3e25eeaa1815dc82a2f6..70c522f6cd7c3079dbae951712f9c0daf83476cf 100755 (executable)
@@ -439,7 +439,7 @@ install_build_system_port() {
 }
 
 usage() {
-    echo "usage: $0 install|install-x11|install-macosx|self-update|quick-update|update|bootstrap|net-bootstrap|make-target"
+    echo "usage: $0 install|install-x11|install-macosx|self-update|quick-update|update|bootstrap|dlls|net-bootstrap|make-target"
     echo "If you are behind a firewall, invoke as:"
     echo "env GIT_PROTOCOL=http $0 <command>"
 }
index f664e1175a0ceed8dea1f2ca5ddf1647ed28ad8c..cc37b85103d2af3cafb1c6ddbc38c59ba99dba78 100755 (executable)
@@ -28,12 +28,6 @@ M: f expired? drop t ;
 : <alien> ( address -- alien )
     f <displaced-alien> { simple-c-ptr } declare ; inline
 
-: alien>native-string ( alien -- string )
-    os windows? [ alien>u16-string ] [ alien>char-string ] if ;
-
-: dll-path ( dll -- string )
-    (dll-path) alien>native-string ;
-
 M: alien equal?
     over alien? [
         2dup [ expired? ] either? [
index f3f27d073930842e66f532096b96131eb8d3ada7..09a09cdc6f97d7136053b2ea2f6dfddbe824d462 100755 (executable)
@@ -18,7 +18,6 @@ ARTICLE: "c-arrays-factor" "Converting C arrays to and from Factor arrays"
 { $subsection >c-ushort-array    }\r
 { $subsection >c-void*-array     }\r
 { $subsection c-bool-array>      }\r
-{ $subsection c-char*-array>     }\r
 { $subsection c-char-array>      }\r
 { $subsection c-double-array>    }\r
 { $subsection c-float-array>     }\r
@@ -30,7 +29,6 @@ ARTICLE: "c-arrays-factor" "Converting C arrays to and from Factor arrays"
 { $subsection c-uint-array>      }\r
 { $subsection c-ulong-array>     }\r
 { $subsection c-ulonglong-array> }\r
-{ $subsection c-ushort*-array>   }\r
 { $subsection c-ushort-array>    }\r
 { $subsection c-void*-array>     } ;\r
 \r
@@ -61,9 +59,7 @@ ARTICLE: "c-arrays-get/set" "Reading and writing elements in C arrays"
 { $subsection double-nth }\r
 { $subsection set-double-nth }\r
 { $subsection void*-nth }\r
-{ $subsection set-void*-nth }\r
-{ $subsection char*-nth }\r
-{ $subsection ushort*-nth } ;\r
+{ $subsection set-void*-nth } ;\r
 \r
 ARTICLE: "c-arrays" "C arrays"\r
 "C arrays are allocated in the same manner as other C data; see " { $link "c-byte-arrays" } " and " { $link "malloc" } "."\r
index 402b01550bb4091a31f8b56cfd028dd1682d72d1..0f756e0ad07eeaeab6eb57d1e0c3d433ab32b670 100644 (file)
@@ -1,8 +1,7 @@
-! Copyright (C) 2007 Slava Pestov.
+! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien arrays alien.c-types alien.structs
-sequences math kernel generator.registers
-namespaces libc ;
+sequences math kernel namespaces libc cpu.architecture ;
 IN: alien.arrays
 
 UNION: value-type array struct-type ;
@@ -27,7 +26,9 @@ M: array stack-size drop "void*" stack-size ;
 
 M: value-type c-type-reg-class drop int-regs ;
 
-M: value-type c-type-prep drop f ;
+M: value-type c-type-boxer-quot drop f ;
+
+M: value-type c-type-unboxer-quot drop f ;
 
 M: value-type c-type-getter
     drop [ swap <displaced-alien> ] ;
index 8d2b03467b3e0b53395252f75d8abcb6e3a951eb..3cd5afef3368f0dd82edcfe12cdc8e7facda4849 100755 (executable)
@@ -62,28 +62,6 @@ HELP: <c-object>
 
 { <c-object> malloc-object } related-words
 
-HELP: string>char-alien ( string -- array )
-{ $values { "string" string } { "array" byte-array } }
-{ $description "Copies the string to a new byte array, converting it to 8-bit ASCII and adding a trailing null byte." }
-{ $errors "Throws an error if the string contains null characters, or characters beyond the 8-bit range." } ;
-
-{ string>char-alien alien>char-string malloc-char-string } related-words
-
-HELP: alien>char-string ( c-ptr -- string )
-{ $values { "c-ptr" c-ptr } { "string" string } }
-{ $description "Reads a null-terminated 8-bit C string from the specified address." } ;
-
-HELP: string>u16-alien ( string -- array )
-{ $values { "string" string } { "array" byte-array } }
-{ $description "Copies the string to a new byte array in UCS-2 format with a trailing null byte." }
-{ $errors "Throws an error if the string contains null characters." } ;
-
-{ string>u16-alien alien>u16-string malloc-u16-string } related-words
-
-HELP: alien>u16-string ( c-ptr -- string )
-{ $values { "c-ptr" c-ptr } { "string" string } }
-{ $description "Reads a null-terminated UCS-2 string from the specified address." } ;
-
 HELP: memory>byte-array
 { $values { "alien" c-ptr } { "len" "a non-negative integer" } { "byte-array" byte-array } }
 { $description "Reads " { $snippet "len" } " bytes starting from " { $snippet "base" } " and stores them in a new byte array." } ;
@@ -111,18 +89,6 @@ HELP: malloc-byte-array
 { $warning "Don't forget to deallocate the memory with a call to " { $link free } "." }
 { $errors "Throws an error if memory allocation fails." } ;
 
-HELP: malloc-char-string
-{ $values { "string" string } { "alien" c-ptr } }
-{ $description "Allocates an unmanaged memory block, and stores a string in 8-bit ASCII encoding with a trailing null byte to the block." }
-{ $warning "Don't forget to deallocate the memory with a call to " { $link free } "." }
-{ $errors "Throws an error if memory allocation fails." } ;
-
-HELP: malloc-u16-string
-{ $values { "string" string } { "alien" c-ptr } }
-{ $description "Allocates an unmanaged memory block, and stores a string in UCS2 encoding with a trailing null character to the block." }
-{ $warning "Don't forget to deallocate the memory with a call to " { $link free } "." }
-{ $errors "Throws an error if memory allocation fails." } ;
-
 HELP: define-nth
 { $values { "name" "a word name" } { "vocab" "a vocabulary name" } }
 { $description "Defines a word " { $snippet { $emphasis "name" } "-nth" } " with stack effect " { $snippet "( n c-ptr -- value )" } " for reading the value with C type " { $snippet "name" } " stored at an alien pointer, displaced by a multiple of the C type's size." }
@@ -202,8 +168,6 @@ $nl
 { $subsection *float }
 { $subsection *double }
 { $subsection *void* }
-{ $subsection *char* }
-{ $subsection *ushort* }
 "Note that while structure and union types do not get these words defined for them, there is no loss of generality since " { $link <void*> } " and " { $link *void* } " may be used." ;
 
 ARTICLE: "c-types-specs" "C type specifiers"
@@ -267,26 +231,6 @@ $nl
 "A wrapper for temporarily allocating a block of memory:"
 { $subsection with-malloc } ;
 
-ARTICLE: "c-strings" "C strings"
-"The C library interface defines two types of C strings:"
-{ $table
-    { "C type" "Notes" }
-    { { $snippet "char*" } "8-bit per character null-terminated ASCII" }
-    { { $snippet "ushort*" } "16-bit per character null-terminated UCS-2" }
-}
-"Passing a Factor string to a C function expecting a C string allocates a " { $link byte-array } " in the Factor heap; the string is then converted to the requested format and a raw pointer is passed to the function. If the conversion fails, for example if the string contains null bytes or characters with values higher than 255, a " { $link c-string-error. } " is thrown."
-"Sometimes a C function has a parameter type of " { $snippet "void*" } ", and various data types, among them strings, can be passed in. In this case, strings are not automatically converted to aliens, and instead you must call one of these words:"
-{ $subsection string>char-alien }
-{ $subsection string>u16-alien }
-{ $subsection malloc-char-string }
-{ $subsection malloc-u16-string }
-"The first two allocate " { $link byte-array } "s, and the latter allocates manually-managed memory which is not moved by the garbage collector and has to be explicitly freed by calling " { $link free } ". See " { $link "byte-arrays-gc" } " for a discussion of the two approaches."
-$nl
-"Finally, a set of words can be used to read and write " { $snippet "char*" } " and " { $snippet "ushort*" } " strings at arbitrary addresses:"
-{ $subsection alien>char-string }
-{ $subsection alien>u16-string }
-"For example, if a C function returns a " { $snippet "char*" } " but stipulates that the caller must deallocate the memory afterward, you must define the function as returning " { $snippet "void*" } ", and call one of the above words before passing the pointer to " { $link free } "." ;
-
 ARTICLE: "c-data" "Passing data between Factor and C"
 "Two defining characteristics of Factor are dynamic typing and automatic memory management, which are somewhat incompatible with the machine-level data model exposed by C. Factor's C library interface defines its own set of C data types, distinct from Factor language types, together with automatic conversion between Factor values and C types. For example, C integer types must be declared and are fixed-width, whereas Factor supports arbitrary-precision integers."
 $nl
index 843b0a826b22696ed0e0c1b43c25419d39516bb3..5f57068bab0d68400e6312e7edfc1cfe64f2bccf 100755 (executable)
@@ -1,30 +1,6 @@
 IN: alien.c-types.tests
 USING: alien alien.syntax alien.c-types kernel tools.test
-sequences system libc ;
-
-[ "\u0000ff" ]
-[ "\u0000ff" string>char-alien alien>char-string ]
-unit-test
-
-[ "hello world" ]
-[ "hello world" string>char-alien alien>char-string ]
-unit-test
-
-[ "hello\u00abcdworld" ]
-[ "hello\u00abcdworld" string>u16-alien alien>u16-string ]
-unit-test
-
-[ t ] [ f expired? ] unit-test
-
-[ "hello world" ] [
-    "hello world" malloc-char-string
-    dup alien>char-string swap free
-] unit-test
-
-[ "hello world" ] [
-    "hello world" malloc-u16-string
-    dup alien>u16-string swap free
-] unit-test
+sequences system libc alien.strings io.encodings.utf8 ;
 
 : foo ( -- n ) "fdafd" f dlsym [ 123 ] unless* ;
 
@@ -67,7 +43,7 @@ TYPEDEF: int* MyIntArray
 
 TYPEDEF: uchar* MyLPBYTE
 
-[ t ] [ "char*" c-type "MyLPBYTE" c-type eq? ] unit-test
+[ t ] [ { "char*" utf8 } c-type "MyLPBYTE" c-type = ] unit-test
 
 [
     0 B{ 1 2 3 4 } <displaced-alien> <void*>
index c97c76069572e13d4a22ba25b9c1e440605eadb1..f67fc78259ff74e23addaee8074183e69f38b69f 100755 (executable)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2004, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: bit-arrays byte-arrays float-arrays arrays
-generator.registers assocs kernel kernel.private libc math
+assocs kernel kernel.private libc math
 namespaces parser sequences strings words assocs splitting
 math.parser cpu.architecture alien alien.accessors quotations
 layouts system compiler.units io.files io.encodings.binary
@@ -14,7 +14,7 @@ DEFER: *char
 : little-endian? ( -- ? ) 1 <int> *char 1 = ; foldable
 
 TUPLE: c-type
-boxer prep unboxer
+boxer boxer-quot unboxer unboxer-quot
 getter setter
 reg-class size align stack-align? ;
 
@@ -149,23 +149,12 @@ M: float-array byte-length length "double" heap-size * ;
 : malloc-byte-array ( byte-array -- alien )
     dup length dup malloc [ -rot memcpy ] keep ;
 
-: malloc-char-string ( string -- alien )
-    string>char-alien malloc-byte-array ;
-
-: malloc-u16-string ( string -- alien )
-    string>u16-alien malloc-byte-array ;
-
 : memory>byte-array ( alien len -- byte-array )
     dup <byte-array> [ -rot memcpy ] keep ;
 
 : byte-array>memory ( byte-array base -- )
     swap dup length memcpy ;
 
-DEFER: >c-ushort-array
-
-: string>u16-memory ( string base -- )
-    >r >c-ushort-array r> byte-array>memory ;
-
 : (define-nth) ( word type quot -- )
     >r heap-size [ rot * ] swap prefix r> append define-inline ;
 
@@ -378,7 +367,7 @@ M: long-long-type box-return ( type -- )
         "box_float" >>boxer
         "to_float" >>unboxer
         single-float-regs >>reg-class
-        [ >float ] >>prep
+        [ >float ] >>unboxer-quot
     "float" define-primitive-type
 
     <c-type>
@@ -389,30 +378,8 @@ M: long-long-type box-return ( type -- )
         "box_double" >>boxer
         "to_double" >>unboxer
         double-float-regs >>reg-class
-        [ >float ] >>prep
+        [ >float ] >>unboxer-quot
     "double" define-primitive-type
 
-    <c-type>
-        [ alien-cell alien>char-string ] >>getter
-        [ set-alien-cell ] >>setter
-        bootstrap-cell >>size
-        bootstrap-cell >>align
-        "box_char_string" >>boxer
-        "alien_offset" >>unboxer
-        [ string>char-alien ] >>prep
-    "char*" define-primitive-type
-
-    "char*" "uchar*" typedef
-
-    <c-type>
-        [ alien-cell alien>u16-string ] >>getter
-        [ set-alien-cell ] >>setter
-        4 >>size
-        4 >>align
-        "box_u16_string" >>boxer
-        "alien_offset" >>unboxer
-        [ string>u16-alien ] >>prep
-    "ushort*" define-primitive-type
-
     os winnt? cpu x86.64? and "longlong" "long" ? "ptrdiff_t" typedef
 ] with-compilation-unit
index dd2d9587cb10a8a329b43d68e0a718cb8fd5033c..3d0f36e415becc41dc3cadf83e6c33b94a59cf1b 100755 (executable)
@@ -3,7 +3,7 @@ USING: alien alien.c-types alien.syntax compiler kernel
 namespaces namespaces tools.test sequences inference words\r
 arrays parser quotations continuations inference.backend effects\r
 namespaces.private io io.streams.string memory system threads\r
-tools.test ;\r
+tools.test math ;\r
 \r
 FUNCTION: void ffi_test_0 ;\r
 [ ] [ ffi_test_0 ] unit-test\r
@@ -280,6 +280,10 @@ FUNCTION: double ffi_test_36 ( test-struct-12 x ) ;
 \r
 [ 1.23456 ] [ 1.23456 make-struct-12 ffi_test_36 ] unit-test\r
 \r
+FUNCTION: ulonglong ffi_test_38 ( ulonglong x, ulonglong y ) ;\r
+\r
+[ t ] [ 31 2^ 32 2^ ffi_test_38 63 2^ = ] unit-test\r
+\r
 ! Test callbacks\r
 \r
 : callback-1 "void" { } "cdecl" [ ] alien-callback ;\r
@@ -354,3 +358,18 @@ FUNCTION: double ffi_test_36 ( test-struct-12 x ) ;
     ] alien-callback ;\r
 \r
 [ ] [ callback-8 callback_test_1 ] unit-test\r
+\r
+: callback-9\r
+    "int" { "int" "int" "int" } "cdecl" [\r
+        + + 1+\r
+    ] alien-callback ;\r
+\r
+FUNCTION: void ffi_test_36_point_5 ( ) ;\r
+\r
+[ ] [ ffi_test_36_point_5 ] unit-test\r
+\r
+FUNCTION: int ffi_test_37 ( void* func ) ;\r
+\r
+[ 1 ] [ callback-9 ffi_test_37 ] unit-test\r
+\r
+[ 7 ] [ callback-9 ffi_test_37 ] unit-test\r
index b6fcbe6176182aefa5764597b72f2ddb1f08e485..3de4c6129121f9675cc15ca4c2bd555c48009a48 100755 (executable)
@@ -3,10 +3,11 @@
 USING: arrays generator generator.registers generator.fixup
 hashtables kernel math namespaces sequences words
 inference.state inference.backend inference.dataflow system
-math.parser classes alien.arrays alien.c-types alien.structs
-alien.syntax cpu.architecture alien inspector quotations assocs
-kernel.private threads continuations.private libc combinators
-compiler.errors continuations layouts accessors ;
+math.parser classes alien.arrays alien.c-types alien.strings
+alien.structs alien.syntax cpu.architecture alien inspector
+quotations assocs kernel.private threads continuations.private
+libc combinators compiler.errors continuations layouts accessors
+;
 IN: alien.compiler
 
 TUPLE: #alien-node < node return parameters abi ;
@@ -20,9 +21,7 @@ TUPLE: #alien-invoke < #alien-node library function ;
 : large-struct? ( ctype -- ? )
     dup c-struct? [
         heap-size struct-small-enough? not
-    ] [
-        drop f
-    ] if ;
+    ] [ drop f ] if ;
 
 : alien-node-parameters* ( node -- seq )
     dup parameters>>
@@ -162,17 +161,16 @@ M: long-long-type flatten-value-type ( type -- )
     dup return>> "void" = 0 1 ?
     swap produce-values ;
 
-: (make-prep-quot) ( parameters -- )
+: (param-prep-quot) ( parameters -- )
     dup empty? [
         drop
     ] [
-        unclip c-type c-type-prep %
-        \ >r , (make-prep-quot) \ r> ,
+        unclip c-type c-type-unboxer-quot %
+        \ >r , (param-prep-quot) \ r> ,
     ] if ;
 
-: make-prep-quot ( node -- quot )
-    parameters>>
-    [ <reversed> (make-prep-quot) ] [ ] make ;
+: param-prep-quot ( node -- quot )
+    parameters>> [ <reversed> (param-prep-quot) ] [ ] make ;
 
 : unbox-parameters ( offset node -- )
     parameters>> [
@@ -200,6 +198,20 @@ M: long-long-type flatten-value-type ( type -- )
 : box-return* ( node -- )
     return>> [ ] [ box-return ] if-void ;
 
+: (return-prep-quot) ( parameters -- )
+    dup empty? [
+        drop
+    ] [
+        unclip c-type c-type-boxer-quot %
+        \ >r , (return-prep-quot) \ r> ,
+    ] if ;
+
+: callback-prep-quot ( node -- quot )
+    parameters>> [ <reversed> (return-prep-quot) ] [ ] make ;
+
+: return-prep-quot ( node -- quot )
+    [ return>> [ ] [ 1array (return-prep-quot) ] if-void ] [ ] make ;
+
 M: alien-invoke-error summary
     drop
     "Words calling ``alien-invoke'' must be compiled with the optimizing compiler." ;
@@ -258,15 +270,15 @@ M: no-such-symbol compiler-error-type
     pop-literal nip >>library
     pop-literal nip >>return
     ! Quotation which coerces parameters to required types
-    dup make-prep-quot recursive-state get infer-quot
+    dup param-prep-quot f infer-quot
     ! Set ABI
-    dup library>>
-    library [ abi>> ] [ "cdecl" ] if*
-    >>abi
+    dup library>> library [ abi>> ] [ "cdecl" ] if* >>abi
     ! Add node to IR
     dup node,
     ! Magic #: consume exactly the number of inputs
-    0 alien-invoke-stack
+    dup 0 alien-invoke-stack
+    ! Quotation which coerces return value to required type
+    return-prep-quot f infer-quot
 ] "infer" set-word-prop
 
 M: #alien-invoke generate-node
@@ -294,11 +306,13 @@ M: alien-indirect-error summary
     pop-parameters >>parameters
     pop-literal nip >>return
     ! Quotation which coerces parameters to required types
-    dup make-prep-quot [ dip ] curry recursive-state get infer-quot
+    dup param-prep-quot [ dip ] curry f infer-quot
     ! Add node to IR
     dup node,
     ! Magic #: consume the function pointer, too
-    1 alien-invoke-stack
+    dup 1 alien-invoke-stack
+    ! Quotation which coerces return value to required type
+    return-prep-quot f infer-quot
 ] "infer" set-word-prop
 
 M: #alien-indirect generate-node
@@ -331,7 +345,7 @@ M: alien-callback-error summary
 
 : callback-bottom ( node -- )
     xt>> [ word-xt drop <alien> ] curry
-    recursive-state get infer-quot ;
+    f infer-quot ;
 
 \ alien-callback [
     4 ensure-values
@@ -371,16 +385,18 @@ TUPLE: callback-context ;
     slip
     wait-to-return ; inline
 
-: prepare-callback-return ( ctype -- quot )
+: callback-return-quot ( ctype -- quot )
     return>> {
         { [ dup "void" = ] [ drop [ ] ] }
         { [ dup large-struct? ] [ heap-size [ memcpy ] curry ] }
-        [ c-type c-type-prep ]
+        [ c-type c-type-unboxer-quot ]
     } cond ;
 
 : wrap-callback-quot ( node -- quot )
     [
-        [ quot>> ] [ prepare-callback-return ] bi append ,
+        [ callback-prep-quot ]
+        [ quot>> ]
+        [ callback-return-quot ] tri 3append ,
         [ callback-context new do-callback ] %
     ] [ ] make ;
 
@@ -403,12 +419,12 @@ TUPLE: callback-context ;
 : generate-callback ( node -- )
     dup xt>> dup [
         init-templates
-        %save-word-xt
         %prologue-later
         dup alien-stack-frame [
-            dup registers>objects
-            dup wrap-callback-quot %alien-callback
-            %callback-return
+            [ registers>objects ]
+            [ wrap-callback-quot %alien-callback ]
+            [ %callback-return ]
+            tri
         ] with-stack-frame
     ] with-generator ;
 
index b7700c0ff18830264649868552d1d4e041c67c31..1d713f6eddaa59a37aacf96ad7cf369b30b77b39 100755 (executable)
@@ -1,12 +1,12 @@
-! Copyright (C) 2007 Slava Pestov.
+! Copyright (C) 2007, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien alien.c-types parser threads words kernel.private
-kernel ;
+USING: alien alien.c-types alien.strings parser threads words
+kernel.private kernel io.encodings.utf8 ;
 IN: alien.remote-control
 
 : eval-callback
     "void*" { "char*" } "cdecl"
-    [ eval>string malloc-char-string ] alien-callback ;
+    [ eval>string utf8 malloc-string ] alien-callback ;
 
 : yield-callback
     "void" { } "cdecl" [ yield ] alien-callback ;
diff --git a/core/alien/strings/strings-docs.factor b/core/alien/strings/strings-docs.factor
new file mode 100644 (file)
index 0000000..27b0122
--- /dev/null
@@ -0,0 +1,52 @@
+USING: help.markup help.syntax strings byte-arrays alien libc
+debugger ;
+IN: alien.strings
+
+HELP: string>alien
+{ $values { "string" string } { "encoding" "an encoding descriptor" } { "byte-array" byte-array } }
+{ $description "Encodes a string together with a trailing null code point using the given encoding, and stores the resulting bytes in a freshly-allocated byte array." }
+{ $errors "Throws an error if the string contains null characters, or characters not representable in the given encoding." } ;
+
+{ string>alien alien>string malloc-string } related-words
+
+HELP: alien>string
+{ $values { "c-ptr" c-ptr } { "encoding" "an encoding descriptor" } { "string/f" "a string or " { $link f } } }
+{ $description "Reads a null-terminated C string from the specified address with the given encoding." } ;
+
+HELP: malloc-string
+{ $values { "string" string } { "encoding" "an encoding descriptor" } { "alien" c-ptr } }
+{ $description "Encodes a string together with a trailing null code point using the given encoding, and stores the resulting bytes in a freshly-allocated unmanaged memory block." }
+{ $warning "Don't forget to deallocate the memory with a call to " { $link free } "." }
+{ $errors "Throws an error if one of the following conditions occurs:"
+    { $list
+        "the string contains null code points"
+        "the string contains characters not representable using the encoding specified"
+        "memory allocation fails"
+    }
+} ;
+
+HELP: string>symbol
+{ $values { "str" string } { "alien" alien } }
+{ $description "Converts the string to a format which is a valid symbol name for the Factor VM's compiled code linker. By performing this conversion ahead of time, the image loader can run without allocating memory."
+$nl
+"On Windows CE, symbols are represented as UCS2 strings, and on all other platforms they are ASCII strings." } ;
+
+HELP: utf16n
+{ $class-description "The encoding descriptor for UTF-16 without a byte order mark in native endian order. This is useful mostly for FFI calls which take input of strings of the type wchar_t*" }
+{ $see-also "encodings-introduction" } ;
+
+ARTICLE: "c-strings" "C strings"
+"C string types are arrays with shape " { $snippet "{ \"char*\" encoding }" } ", where " { $snippet "encoding" } " is an encoding descriptor. The type " { $snippet "\"char*\"" } " is an alias for " { $snippet "{ \"char*\" utf8 }" } ". See " { $link "encodings-descriptors" } " for information about encoding descriptors."
+$nl
+"Passing a Factor string to a C function expecting a C string allocates a " { $link byte-array } " in the Factor heap; the string is then converted to the requested format and a raw pointer is passed to the function. If the conversion fails, for example if the string contains null bytes or characters with values higher than 255, a " { $link c-string-error. } " is thrown."
+$nl
+"Sometimes a C function has a parameter type of " { $snippet "void*" } ", and various data types, among them strings, can be passed in. In this case, strings are not automatically converted to aliens, and instead you must call one of these words:"
+{ $subsection string>alien }
+{ $subsection malloc-string }
+"The first allocates " { $link byte-array } "s, and the latter allocates manually-managed memory which is not moved by the garbage collector and has to be explicitly freed by calling " { $link free } ". See " { $link "byte-arrays-gc" } " for a discussion of the two approaches."
+$nl
+"A word to read strings from arbitrary addresses:"
+{ $subsection alien>string }
+"For example, if a C function returns a " { $snippet "char*" } " but stipulates that the caller must deallocate the memory afterward, you must define the function as returning " { $snippet "void*" } ", and call one of the above words before passing the pointer to " { $link free } "." ;
+
+ABOUT: "c-strings"
diff --git a/core/alien/strings/strings-tests.factor b/core/alien/strings/strings-tests.factor
new file mode 100644 (file)
index 0000000..4848094
--- /dev/null
@@ -0,0 +1,30 @@
+USING: alien.strings tools.test kernel libc
+io.encodings.8-bit io.encodings.utf8 io.encodings.utf16
+io.encodings.ascii alien ;
+IN: alien.strings.tests
+
+[ "\u0000ff" ]
+[ "\u0000ff" latin1 string>alien latin1 alien>string ]
+unit-test
+
+[ "hello world" ]
+[ "hello world" latin1 string>alien latin1 alien>string ]
+unit-test
+
+[ "hello\u00abcdworld" ]
+[ "hello\u00abcdworld" utf16le string>alien utf16le alien>string ]
+unit-test
+
+[ t ] [ f expired? ] unit-test
+
+[ "hello world" ] [
+    "hello world" ascii malloc-string
+    dup ascii alien>string swap free
+] unit-test
+
+[ "hello world" ] [
+    "hello world" utf16n malloc-string
+    dup utf16n alien>string swap free
+] unit-test
+
+[ f ] [ f utf8 alien>string ] unit-test
diff --git a/core/alien/strings/strings.factor b/core/alien/strings/strings.factor
new file mode 100644 (file)
index 0000000..d69d8e9
--- /dev/null
@@ -0,0 +1,111 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: arrays sequences kernel accessors math alien.accessors
+alien.c-types byte-arrays words io io.encodings
+io.streams.byte-array io.streams.memory io.encodings.utf8
+io.encodings.utf16 system alien strings cpu.architecture ;
+IN: alien.strings
+
+GENERIC# alien>string 1 ( c-ptr encoding -- string/f )
+
+M: c-ptr alien>string
+    >r <memory-stream> r> <decoder>
+    "\0" swap stream-read-until drop ;
+
+M: f alien>string
+    drop ;
+
+ERROR: invalid-c-string string ;
+
+: check-string ( string -- )
+    0 over memq? [ invalid-c-string ] [ drop ] if ;
+
+GENERIC# string>alien 1 ( string encoding -- byte-array )
+
+M: c-ptr string>alien drop ;
+
+M: string string>alien
+    over check-string
+    <byte-writer>
+    [ stream-write ]
+    [ 0 swap stream-write1 ]
+    [ stream>> >byte-array ]
+    tri ;
+
+: malloc-string ( string encoding -- alien )
+    string>alien malloc-byte-array ;
+
+PREDICATE: string-type < pair
+    first2 [ "char*" = ] [ word? ] bi* and ;
+
+M: string-type c-type ;
+
+M: string-type heap-size
+    drop "void*" heap-size ;
+
+M: string-type c-type-align
+    drop "void*" c-type-align ;
+
+M: string-type c-type-stack-align?
+    drop "void*" c-type-stack-align? ;
+
+M: string-type unbox-parameter
+    drop "void*" unbox-parameter ;
+
+M: string-type unbox-return
+    drop "void*" unbox-return ;
+
+M: string-type box-parameter
+    drop "void*" box-parameter ;
+
+M: string-type box-return
+    drop "void*" box-return ;
+
+M: string-type stack-size
+    drop "void*" stack-size ;
+
+M: string-type c-type-reg-class
+    drop int-regs ;
+
+M: string-type c-type-boxer
+    drop "void*" c-type-boxer ;
+
+M: string-type c-type-unboxer
+    drop "void*" c-type-unboxer ;
+
+M: string-type c-type-boxer-quot
+    second [ alien>string ] curry [ ] like ;
+
+M: string-type c-type-unboxer-quot
+    second [ string>alien ] curry [ ] like ;
+
+M: string-type c-type-getter
+    drop [ alien-cell ] ;
+
+M: string-type c-type-setter
+    drop [ set-alien-cell ] ;
+
+TUPLE: utf16n ;
+
+! Native-order UTF-16
+
+: utf16n ( -- descriptor )
+    little-endian? utf16le utf16be ? ; foldable
+
+M: utf16n <decoder> drop utf16n <decoder> ;
+
+M: utf16n <encoder> drop utf16n <encoder> ;
+
+: alien>native-string ( alien -- string )
+    os windows? [ utf16n ] [ utf8 ] if alien>string ;
+
+: dll-path ( dll -- string )
+    (dll-path) alien>native-string ;
+
+: string>symbol ( str -- alien )
+    [ os wince? [ utf16n ] [ utf8 ] if string>alien ]
+    over string? [ call ] [ map ] if ;
+
+{ "char*" utf8 } "char*" typedef
+{ "char*" utf16n } "wchar_t*" typedef
+"char*" "uchar*" typedef
index a33a86d4b54fd42e8ec593206c76b465b67c10db..bfdcd31b99ec74cc6c3f1366bae60adb80d8519f 100644 (file)
@@ -1,6 +1,6 @@
 IN: alien.structs.tests
 USING: alien alien.syntax alien.c-types kernel tools.test
-sequences system libc words vocabs namespaces ;
+sequences system libc words vocabs namespaces layouts ;
 
 C-STRUCT: bar
     { "int" "x" }
@@ -9,20 +9,20 @@ C-STRUCT: bar
 [ 36 ] [ "bar" heap-size ] unit-test
 [ t ] [ \ <displaced-alien> "bar" c-type c-type-getter memq? ] unit-test
 
-! This was actually only correct on Windows/x86:
-
-! C-STRUCT: align-test
-!     { "int" "x" }
-!     { "double" "y" } ;
-! 
-! [ 16 ] [ "align-test" heap-size ] unit-test
-! 
-! cell 4 = [
-!     C-STRUCT: one
-!     { "long" "a" } { "double" "b" } { "int" "c" } ;
-! 
-!     [ 24 ] [ "one" heap-size ] unit-test
-] when
+C-STRUCT: align-test
+    { "int" "x" }
+    { "double" "y" } ;
+
+os winnt? cpu x86? and [
+    [ 16 ] [ "align-test" heap-size ] unit-test
+    
+    cell 4 = [
+        C-STRUCT: one
+        { "long" "a" } { "double" "b" } { "int" "c" } ;
+    
+        [ 24 ] [ "one" heap-size ] unit-test
+    ] when
+] when
 
 : MAX_FOOS 30 ;
 
index 6d98d317908436fd309eae7d64227bb1b4612f3b..bc5fa5a3f18248e9eeed6dbfe67b540b9e3922c5 100755 (executable)
@@ -20,14 +20,19 @@ IN: alien.structs
 
 : define-getter ( type spec -- )
     [ set-reader-props ] keep
-    dup slot-spec-reader
-    over slot-spec-type c-getter
+    [ ]
+    [ slot-spec-reader ]
+    [
+        slot-spec-type
+        [ c-getter ] [ c-type c-type-boxer-quot ] bi append
+    ] tri
     define-struct-slot-word ;
 
 : define-setter ( type spec -- )
     [ set-writer-props ] keep
-    dup slot-spec-writer
-    over slot-spec-type c-setter
+    [ ]
+    [ slot-spec-writer ]
+    [ slot-spec-type c-setter ] tri
     define-struct-slot-word ;
 
 : define-field ( type spec -- )
index 67ea30f379f9ee330609df42517a9663cb55eaf5..f0f495cac9cfafd9ee984718b7b5d288fad424ec 100755 (executable)
@@ -1,9 +1,9 @@
 ! Copyright (C) 2005, 2008 Slava Pestov, Alex Chapman.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays alien alien.c-types alien.structs alien.arrays
-kernel math namespaces parser sequences words quotations
-math.parser splitting effects prettyprint prettyprint.sections
-prettyprint.backend assocs combinators ;
+alien.strings kernel math namespaces parser sequences words
+quotations math.parser splitting effects prettyprint
+prettyprint.sections prettyprint.backend assocs combinators ;
 IN: alien.syntax
 
 <PRIVATE
diff --git a/core/bit-vectors/bit-vectors-docs.factor b/core/bit-vectors/bit-vectors-docs.factor
deleted file mode 100755 (executable)
index f2f5c4d..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-USING: arrays bit-arrays help.markup help.syntax kernel\r
-bit-vectors.private combinators ;\r
-IN: bit-vectors\r
-\r
-ARTICLE: "bit-vectors" "Bit vectors"\r
-"A bit vector is a resizable mutable sequence of bits. The literal syntax is covered in " { $link "syntax-bit-vectors" } ". Bit vector words are found in the " { $vocab-link "bit-vectors" } " vocabulary."\r
-$nl\r
-"Bit vectors form a class:"\r
-{ $subsection bit-vector }\r
-{ $subsection bit-vector? }\r
-"Creating bit vectors:"\r
-{ $subsection >bit-vector }\r
-{ $subsection <bit-vector> }\r
-"If you don't care about initial capacity, a more elegant way to create a new bit vector is to write:"\r
-{ $code "?V{ } clone" } ;\r
-\r
-ABOUT: "bit-vectors"\r
-\r
-HELP: bit-vector\r
-{ $description "The class of resizable bit vectors. See " { $link "syntax-bit-vectors" } " for syntax and " { $link "bit-vectors" } " for general information." } ;\r
-\r
-HELP: <bit-vector>\r
-{ $values { "n" "a positive integer specifying initial capacity" } { "bit-vector" bit-vector } }\r
-{ $description "Creates a new bit vector that can hold " { $snippet "n" } " bits before resizing." } ;\r
-\r
-HELP: >bit-vector\r
-{ $values { "seq" "a sequence" } { "bit-vector" bit-vector } }\r
-{ $description "Outputs a freshly-allocated bit vector with the same elements as a given sequence." } ;\r
-\r
-HELP: bit-array>vector\r
-{ $values { "bit-array" "an array" } { "length" "a non-negative integer" } { "bit-vector" bit-vector } }\r
-{ $description "Creates a new bit vector using the array for underlying storage with the specified initial length." }\r
-{ $warning "This word is in the " { $vocab-link "bit-vectors.private" } " vocabulary because it does not perform type or bounds checks. User code should call " { $link >bit-vector } " instead." } ;\r
diff --git a/core/bit-vectors/bit-vectors-tests.factor b/core/bit-vectors/bit-vectors-tests.factor
deleted file mode 100755 (executable)
index dff9a8d..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-IN: bit-vectors.tests\r
-USING: tools.test bit-vectors vectors sequences kernel math ;\r
-\r
-[ 0 ] [ 123 <bit-vector> length ] unit-test\r
-\r
-: do-it\r
-    1234 swap [ >r even? r> push ] curry each ;\r
-\r
-[ t ] [\r
-    3 <bit-vector> dup do-it\r
-    3 <vector> dup do-it sequence=\r
-] unit-test\r
-\r
-[ t ] [ ?V{ } bit-vector? ] unit-test\r
diff --git a/core/bit-vectors/bit-vectors.factor b/core/bit-vectors/bit-vectors.factor
deleted file mode 100755 (executable)
index db941ac..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-! Copyright (C) 2008 Slava Pestov.\r
-! See http://factorcode.org/license.txt for BSD license.\r
-USING: arrays kernel kernel.private math sequences\r
-sequences.private growable bit-arrays ;\r
-IN: bit-vectors\r
-\r
-<PRIVATE\r
-\r
-: bit-array>vector ( bit-array length -- bit-vector )\r
-    bit-vector boa ; inline\r
-\r
-PRIVATE>\r
-\r
-: <bit-vector> ( n -- bit-vector )\r
-    <bit-array> 0 bit-array>vector ; inline\r
-\r
-: >bit-vector ( seq -- bit-vector ) ?V{ } clone-like ;\r
-\r
-M: bit-vector like\r
-    drop dup bit-vector? [\r
-        dup bit-array?\r
-        [ dup length bit-array>vector ] [ >bit-vector ] if\r
-    ] unless ;\r
-\r
-M: bit-vector new-sequence\r
-    drop [ <bit-array> ] keep >fixnum bit-array>vector ;\r
-\r
-M: bit-vector equal?\r
-    over bit-vector? [ sequence= ] [ 2drop f ] if ;\r
-\r
-M: bit-array new-resizable drop <bit-vector> ;\r
-\r
-INSTANCE: bit-vector growable\r
diff --git a/core/bit-vectors/summary.txt b/core/bit-vectors/summary.txt
deleted file mode 100644 (file)
index 76a7d0f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Growable bit arrays
diff --git a/core/bit-vectors/tags.txt b/core/bit-vectors/tags.txt
deleted file mode 100644 (file)
index 42d711b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-collections
index f1e41ac2b60e7a12d1563ce8487a2b4f7021ac05..dd3a4adf8bedb670e46a44aa93e87135e444e7f3 100755 (executable)
@@ -58,16 +58,13 @@ num-types get f <array> builtins set
     "alien.accessors"
     "arrays"
     "bit-arrays"
-    "bit-vectors"
     "byte-arrays"
-    "byte-vectors"
     "classes.private"
     "classes.tuple"
     "classes.tuple.private"
     "compiler.units"
     "continuations.private"
     "float-arrays"
-    "float-vectors"
     "generator"
     "growable"
     "hashtables"
@@ -455,54 +452,6 @@ tuple
     }
 } define-tuple-class
 
-"byte-vector" "byte-vectors" create
-tuple
-{
-    {
-        { "byte-array" "byte-arrays" }
-        "underlying"
-        { "underlying" "growable" }
-        { "set-underlying" "growable" }
-    } {
-        { "array-capacity" "sequences.private" }
-        "fill"
-        { "length" "sequences" }
-        { "set-fill" "growable" }
-    }
-} define-tuple-class
-
-"bit-vector" "bit-vectors" create
-tuple
-{
-    {
-        { "bit-array" "bit-arrays" }
-        "underlying"
-        { "underlying" "growable" }
-        { "set-underlying" "growable" }
-    } {
-        { "array-capacity" "sequences.private" }
-        "fill"
-        { "length" "sequences" }
-        { "set-fill" "growable" }
-    }
-} define-tuple-class
-
-"float-vector" "float-vectors" create
-tuple
-{
-    {
-        { "float-array" "float-arrays" }
-        "underlying"
-        { "underlying" "growable" }
-        { "set-underlying" "growable" }
-    } {
-        { "array-capacity" "sequences.private" }
-        "fill"
-        { "length" "sequences" }
-        { "set-fill" "growable" }
-    }
-} define-tuple-class
-
 "curry" "kernel" create
 tuple
 {
@@ -689,10 +638,6 @@ tuple
     { "set-alien-double" "alien.accessors" }
     { "alien-cell" "alien.accessors" }
     { "set-alien-cell" "alien.accessors" }
-    { "alien>char-string" "alien" }
-    { "string>char-alien" "alien" }
-    { "alien>u16-string" "alien" }
-    { "string>u16-alien" "alien" }
     { "(throw)" "kernel.private" }
     { "alien-address" "alien" }
     { "slot" "slots.private" }
index ca90587ea9113cdb789ddb03c0faba9fc411ec14..dfd2e4be6fe50186de1fcc43e289adc072dfc363 100755 (executable)
@@ -27,10 +27,6 @@ SYMBOL: bootstrap-time
     diff
     [ "bootstrap." prepend require ] each ;
 
-! : compile-remaining ( -- )
-!     "Compiling remaining words..." print flush
-!     vocabs [ words [ compiled? not ] subset compile ] each ;
-
 : count-words ( pred -- )
     all-words swap subset length number>string write ;
 
index 4d5f31dc823cc6afad526093c8991dae75dac87a..4b748047492d013cbf37770f6e5888bd5d3367a0 100755 (executable)
@@ -14,16 +14,13 @@ IN: bootstrap.syntax
     ";"
     "<PRIVATE"
     "?{"
-    "?V{"
     "BIN:"
     "B{"
-    "BV{"
     "C:"
     "CHAR:"
     "DEFER:"
     "ERROR:"
     "F{"
-    "FV{"
     "FORGET:"
     "GENERIC#"
     "GENERIC:"
diff --git a/core/byte-vectors/byte-vectors-docs.factor b/core/byte-vectors/byte-vectors-docs.factor
deleted file mode 100755 (executable)
index 0f1054e..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-USING: arrays byte-arrays help.markup help.syntax kernel\r
-byte-vectors.private combinators ;\r
-IN: byte-vectors\r
-\r
-ARTICLE: "byte-vectors" "Byte vectors"\r
-"A byte vector is a resizable mutable sequence of unsigned bytes. The literal syntax is covered in " { $link "syntax-byte-vectors" } ". Byte vector words are found in the " { $vocab-link "byte-vectors" } " vocabulary."\r
-$nl\r
-"Byte vectors form a class:"\r
-{ $subsection byte-vector }\r
-{ $subsection byte-vector? }\r
-"Creating byte vectors:"\r
-{ $subsection >byte-vector }\r
-{ $subsection <byte-vector> }\r
-"If you don't care about initial capacity, a more elegant way to create a new byte vector is to write:"\r
-{ $code "BV{ } clone" } ;\r
-\r
-ABOUT: "byte-vectors"\r
-\r
-HELP: byte-vector\r
-{ $description "The class of resizable byte vectors. See " { $link "syntax-byte-vectors" } " for syntax and " { $link "byte-vectors" } " for general information." } ;\r
-\r
-HELP: <byte-vector>\r
-{ $values { "n" "a positive integer specifying initial capacity" } { "byte-vector" byte-vector } }\r
-{ $description "Creates a new byte vector that can hold " { $snippet "n" } " bytes before resizing." } ;\r
-\r
-HELP: >byte-vector\r
-{ $values { "seq" "a sequence" } { "byte-vector" byte-vector } }\r
-{ $description "Outputs a freshly-allocated byte vector with the same elements as a given sequence." }\r
-{ $errors "Throws an error if the sequence contains elements other than integers." } ;\r
-\r
-HELP: byte-array>vector\r
-{ $values { "byte-array" "an array" } { "length" "a non-negative integer" } { "byte-vector" byte-vector } }\r
-{ $description "Creates a new byte vector using the array for underlying storage with the specified initial length." }\r
-{ $warning "This word is in the " { $vocab-link "byte-vectors.private" } " vocabulary because it does not perform type or bounds checks. User code should call " { $link >byte-vector } " instead." } ;\r
diff --git a/core/byte-vectors/byte-vectors-tests.factor b/core/byte-vectors/byte-vectors-tests.factor
deleted file mode 100755 (executable)
index d457d68..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-IN: byte-vectors.tests\r
-USING: tools.test byte-vectors vectors sequences kernel ;\r
-\r
-[ 0 ] [ 123 <byte-vector> length ] unit-test\r
-\r
-: do-it\r
-    123 [ over push ] each ;\r
-\r
-[ t ] [\r
-    3 <byte-vector> do-it\r
-    3 <vector> do-it sequence=\r
-] unit-test\r
-\r
-[ t ] [ BV{ } byte-vector? ] unit-test\r
diff --git a/core/byte-vectors/byte-vectors.factor b/core/byte-vectors/byte-vectors.factor
deleted file mode 100755 (executable)
index 206a23f..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-! Copyright (C) 2008 Slava Pestov.\r
-! See http://factorcode.org/license.txt for BSD license.\r
-USING: arrays kernel kernel.private math sequences\r
-sequences.private growable byte-arrays ;\r
-IN: byte-vectors\r
-\r
-<PRIVATE\r
-\r
-: byte-array>vector ( byte-array length -- byte-vector )\r
-    byte-vector boa ; inline\r
-\r
-PRIVATE>\r
-\r
-: <byte-vector> ( n -- byte-vector )\r
-    <byte-array> 0 byte-array>vector ; inline\r
-\r
-: >byte-vector ( seq -- byte-vector ) BV{ } clone-like ;\r
-\r
-M: byte-vector like\r
-    drop dup byte-vector? [\r
-        dup byte-array?\r
-        [ dup length byte-array>vector ] [ >byte-vector ] if\r
-    ] unless ;\r
-\r
-M: byte-vector new-sequence\r
-    drop [ <byte-array> ] keep >fixnum byte-array>vector ;\r
-\r
-M: byte-vector equal?\r
-    over byte-vector? [ sequence= ] [ 2drop f ] if ;\r
-\r
-M: byte-array new-resizable drop <byte-vector> ;\r
-\r
-INSTANCE: byte-vector growable\r
diff --git a/core/byte-vectors/summary.txt b/core/byte-vectors/summary.txt
deleted file mode 100644 (file)
index e914ebb..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Growable byte arrays
diff --git a/core/byte-vectors/tags.txt b/core/byte-vectors/tags.txt
deleted file mode 100644 (file)
index 42d711b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-collections
index d61b62af3b9e94925f36f71b2a137cdcef44aeef..dba97c16f5b97d82e4e7d377564c9ab8b30b309f 100755 (executable)
@@ -4,7 +4,7 @@ kernel math namespaces parser prettyprint sequences strings
 tools.test vectors words quotations classes classes.algebra\r
 classes.private classes.union classes.mixin classes.predicate\r
 vectors definitions source-files compiler.units growable\r
-random inference effects kernel.private ;\r
+random inference effects kernel.private sbufs ;\r
 \r
 : class= [ class< ] 2keep swap class< and ;\r
 \r
@@ -144,6 +144,48 @@ UNION: z1 b1 c1 ;
 \r
 [ f ] [ null class-not null class= ] unit-test\r
 \r
+[ t ] [\r
+    fixnum class-not\r
+    fixnum fixnum class-not class-or\r
+    class<\r
+] unit-test\r
+\r
+! Test method inlining\r
+[ f ] [ fixnum { } min-class ] unit-test\r
+\r
+[ string ] [\r
+    \ string\r
+    [ integer string array reversed sbuf\r
+    slice vector quotation ]\r
+    sort-classes min-class\r
+] unit-test\r
+\r
+[ fixnum ] [\r
+    \ fixnum\r
+    [ fixnum integer object ]\r
+    sort-classes min-class\r
+] unit-test\r
+\r
+[ integer ] [\r
+    \ fixnum\r
+    [ integer float object ]\r
+    sort-classes min-class\r
+] unit-test\r
+\r
+[ object ] [\r
+    \ word\r
+    [ integer float object ]\r
+    sort-classes min-class\r
+] unit-test\r
+\r
+[ reversed ] [\r
+    \ reversed\r
+    [ integer reversed slice ]\r
+    sort-classes min-class\r
+] unit-test\r
+\r
+[ f ] [ null { number fixnum null } min-class ] unit-test\r
+\r
 ! Test for hangs?\r
 : random-class classes random ;\r
 \r
index b7a3e074e594d231aa85e7b502c7263f3d4cd7d4..f2941e3cefbf531856938e88bfc3d844cdbcd0ba 100755 (executable)
@@ -77,10 +77,10 @@ C: <anonymous-complement> anonymous-complement
         { [ 2dup [ anonymous-complement? ] both? ] [ anonymous-complement< ] }\r
         { [ over anonymous-union? ] [ left-anonymous-union< ] }\r
         { [ over anonymous-intersection? ] [ left-anonymous-intersection< ] }\r
-        { [ over anonymous-complement? ] [ 2drop f ] }\r
         { [ over members ] [ left-union-class< ] }\r
         { [ dup anonymous-union? ] [ right-anonymous-union< ] }\r
         { [ dup anonymous-intersection? ] [ right-anonymous-intersection< ] }\r
+        { [ over anonymous-complement? ] [ 2drop f ] }\r
         { [ dup anonymous-complement? ] [ class>> classes-intersect? not ] }\r
         { [ dup members ] [ right-union-class< ] }\r
         { [ over superclass ] [ superclass< ] }\r
@@ -193,9 +193,8 @@ C: <anonymous-complement> anonymous-complement
     [ ] unfold nip ;\r
 \r
 : min-class ( class seq -- class/f )\r
-    [ dupd classes-intersect? ] subset dup empty? [\r
-        2drop f\r
-    ] [\r
+    over [ classes-intersect? ] curry subset\r
+    dup empty? [ 2drop f ] [\r
         tuck [ class< ] with all? [ peek ] [ drop f ] if\r
     ] if ;\r
 \r
index ce6fd9367c0384535a2dc6ece2f4be658ed9acbf..2932187152d4a3f20536b5ef6bccb3e069738e3e 100755 (executable)
@@ -3,7 +3,8 @@ 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 inspector ;
+calendar prettyprint io.streams.string splitting inspector
+columns ;
 IN: classes.tuple.tests
 
 TUPLE: rect x y w h ;
index e3d0f8868052ff98d490a13c79145357d4f620c2..da98a78736ac2cd5dad848577003640fd3901e8b 100755 (executable)
@@ -150,7 +150,7 @@ M: hashtable hashcode*
         drop
     ] [
         dup length 4 <=
-        over keys [ word? ] contains? or
+        over keys [ [ word? ] [ wrapper? ] bi or ] contains? or
         [
             linear-case-quot
         ] [
index fadc57dc8d2e91aca213010c952d158f6531830a..7d473871fe83629159f0cac921e9849e171c567f 100755 (executable)
@@ -4,8 +4,8 @@ math.constants math.private sequences strings tools.test words
 continuations sequences.private hashtables.private byte-arrays
 strings.private system random layouts vectors.private
 sbufs.private strings.private slots.private alien
-alien.accessors alien.c-types alien.syntax namespaces libc
-sequences.private ;
+alien.accessors alien.c-types alien.syntax alien.strings
+namespaces libc sequences.private io.encodings.ascii ;
 
 ! Make sure that intrinsic ops compile to correct code.
 [ ] [ 1 [ drop ] compile-call ] unit-test
@@ -361,11 +361,11 @@ cell 8 = [
     [ ] [ "b" get free ] unit-test
 ] when
 
-[ ] [ "hello world" malloc-char-string "s" set ] unit-test
+[ ] [ "hello world" ascii malloc-string "s" set ] unit-test
 
 "s" get [
-    [ "hello world" ] [ "s" get <void*> [ { byte-array } declare *void* ] compile-call alien>char-string ] unit-test
-    [ "hello world" ] [ "s" get <void*> [ { c-ptr } declare *void* ] compile-call alien>char-string ] unit-test
+    [ "hello world" ] [ "s" get <void*> [ { byte-array } declare *void* ] compile-call ascii alien>string ] unit-test
+    [ "hello world" ] [ "s" get <void*> [ { c-ptr } declare *void* ] compile-call ascii alien>string ] unit-test
 
     [ ] [ "s" get free ] unit-test
 ] when
index dce2ec562a2dd25cc60c31cd2c2b262e7f71d212..bc9c56864c32b722c2319eab00e905ab27ac1452 100755 (executable)
@@ -1,6 +1,6 @@
 USING: compiler.units tools.test kernel kernel.private
 sequences.private math.private math combinators strings
-alien arrays memory ;
+alien arrays memory vocabs parser ;
 IN: compiler.tests
 
 ! Test empty word
@@ -230,3 +230,11 @@ M: f single-combination-test-2 single-combination-test-4 ;
 
 ! Regression
 [ 100 ] [ [ 100 [ [ ] times ] keep ] compile-call ] unit-test
+
+! Regression
+10 [
+    [ "compiler.tests.foo" forget-vocab ] with-compilation-unit
+    [ t ] [
+        "USING: prettyprint words ; IN: compiler.tests.foo : (recursive) (  -- ) (recursive) (recursive) ; inline : recursive ( -- ) (recursive) ; \\ (recursive) compiled?" eval
+    ] unit-test
+] times
index 004d08834324aa79c0aa1ca96d159294cfc30020..5a08ed0b5b1dccbc810a03eaeb4f0ea3c81b2ff2 100755 (executable)
@@ -2,7 +2,8 @@
 IN: compiler.tests
 USING: compiler generator generator.registers
 generator.registers.private tools.test namespaces sequences
-words kernel math effects definitions compiler.units accessors ;
+words kernel math effects definitions compiler.units accessors
+cpu.architecture ;
 
 : <int-vreg> ( n -- vreg ) int-regs <vreg> ;
 
index 845189ce2c589d284cb802280ae5f60f13800c04..14d75cdc03e9b0877c2e45e932bf9a7fb8138d70 100755 (executable)
@@ -3,7 +3,7 @@ USING: arrays compiler kernel kernel.private math
 hashtables.private math.private namespaces sequences
 sequences.private tools.test namespaces.private slots.private
 sequences.private byte-arrays alien alien.accessors layouts
-words definitions compiler.units io combinators ;
+words definitions compiler.units io combinators vectors ;
 IN: compiler.tests
 
 ! Oops!
@@ -246,3 +246,12 @@ TUPLE: my-tuple ;
     } cleave ;
 
 [ t ] [ \ float-spill-bug compiled? ] unit-test
+
+! Regression
+: dispatch-alignment-regression ( -- c )
+    { tuple vector } 3 slot { word } declare
+    dup 1 slot 0 fixnum-bitand { [ ] } dispatch ;
+
+[ t ] [ \ dispatch-alignment-regression compiled? ] unit-test
+
+[ vector ] [ dispatch-alignment-regression ] unit-test
index 65d1763ea830815b79f57e7abb5b31e973410cdf..338c5341bc51724f5711854d9212c1b0bf0356f7 100755 (executable)
@@ -1,10 +1,17 @@
-! Copyright (C) 2006, 2007 Slava Pestov.
+! Copyright (C) 2006, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays generic kernel kernel.private math memory
 namespaces sequences layouts system hashtables classes alien
 byte-arrays bit-arrays float-arrays combinators words sets ;
 IN: cpu.architecture
 
+! Register classes
+SINGLETON: int-regs
+SINGLETON: single-float-regs
+SINGLETON: double-float-regs
+UNION: float-regs single-float-regs double-float-regs ;
+UNION: reg-class int-regs float-regs ;
+
 ! A pseudo-register class for parameters spilled on the stack
 SINGLETON: stack-params
 
@@ -56,7 +63,7 @@ HOOK: %call cpu ( word -- )
 HOOK: %jump-label cpu ( label -- )
 
 ! Test if vreg is 'f' or not
-HOOK: %jump-t cpu ( label -- )
+HOOK: %jump-f cpu ( label -- )
 
 HOOK: %dispatch cpu ( -- )
 
@@ -187,6 +194,9 @@ HOOK: %unbox-any-c-ptr cpu ( dst src -- )
 
 HOOK: %box-alien cpu ( dst src -- )
 
+! GC check
+HOOK: %gc cpu
+
 : operand ( var -- op ) get v>operand ; inline
 
 : unique-operands ( operands quot -- )
index 34ea82dc4ed7e2c8237f03316d9e42624c426943..49c77c65ed839aa1824cfc448558dd77d0792877 100755 (executable)
@@ -1,4 +1,4 @@
-! Copyright (C) 2006, 2007 Slava Pestov.
+! Copyright (C) 2006, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel cpu.ppc.architecture cpu.ppc.assembler
 kernel.private namespaces math sequences generic arrays
@@ -7,7 +7,7 @@ cpu.architecture alien ;
 IN: cpu.ppc.allot
 
 : load-zone-ptr ( reg -- )
-    "nursery" f pick %load-dlsym dup 0 LWZ ;
+    >r "nursery" f r> %load-dlsym ;
 
 : %allot ( header size -- )
     #! Store a pointer to 'size' bytes allocated from the
@@ -25,6 +25,19 @@ IN: cpu.ppc.allot
 : %store-tagged ( reg tag -- )
     >r dup fresh-object v>operand 11 r> tag-number ORI ;
 
+M: ppc %gc
+    "end" define-label
+    12 load-zone-ptr
+    11 12 cell LWZ ! nursery.here -> r11
+    12 12 3 cells LWZ ! nursery.end -> r12
+    11 11 1024 ADDI ! add ALLOT_BUFFER_ZONE to here
+    11 0 12 CMP ! is here >= end?
+    "end" get BLE
+    0 frame-required
+    %prepare-alien-invoke
+    "minor_gc" f %alien-invoke
+    "end" resolve-label ;
+
 : %allot-float ( reg -- )
     #! exits with tagged ptr to object in r12, untagged in r11
     float 16 %allot
index 09ffead0298782004e7c67fa46bc70f22825ea7a..179941102152fea3d421ce8f336b11c75ee0d472 100755 (executable)
@@ -106,8 +106,8 @@ M: ppc %call ( label -- ) BL ;
 
 M: ppc %jump-label ( label -- ) B ;
 
-M: ppc %jump-t ( label -- )
-    0 "flag" operand f v>operand CMPI BNE ;
+M: ppc %jump-f ( label -- )
+    0 "flag" operand f v>operand CMPI BEQ ;
 
 M: ppc %dispatch ( -- )
     [
index d092473960271ee6bfc411bb3feccb38d149da06..34e9900893521f9b04d36f1c011bbc9db1a33fa8 100755 (executable)
@@ -217,11 +217,11 @@ IN: cpu.ppc.intrinsics
     2array define-if-intrinsics ;
 
 {
-    { fixnum< BLT }
-    { fixnum<= BLE }
-    { fixnum> BGT }
-    { fixnum>= BGE }
-    { eq? BEQ }
+    { fixnum< BGE }
+    { fixnum<= BGT }
+    { fixnum> BLE }
+    { fixnum>= BLT }
+    { eq? BNE }
 } [
     first2 define-fixnum-jump
 ] each
@@ -356,11 +356,11 @@ IN: cpu.ppc.intrinsics
     { { float "x" } { float "y" } } define-if-intrinsic ;
 
 {
-    { float< BLT }
-    { float<= BLE }
-    { float> BGT }
-    { float>= BGE }
-    { float= BEQ }
+    { float< BGE }
+    { float<= BGT }
+    { float> BLE }
+    { float>= BLT }
+    { float= BNE }
 } [
     first2 define-float-jump
 ] each
index cc3fceff230ba2601c946b1cbc9d1a9526bdc740..50e38f2082e28416a9419c977cabf831efc0aef0 100755 (executable)
@@ -16,8 +16,9 @@ IN: cpu.x86.32
 M: x86.32 ds-reg ESI ;
 M: x86.32 rs-reg EDI ;
 M: x86.32 stack-reg ESP ;
-M: x86.32 xt-reg ECX ;
 M: x86.32 stack-save-reg EDX ;
+M: x86.32 temp-reg-1 EAX ;
+M: x86.32 temp-reg-2 ECX ;
 
 M: temp-reg v>operand drop EBX ;
 
@@ -267,7 +268,7 @@ os windows? [
     EDX 26 SHR
     EDX 1 AND
     { EAX EBX ECX EDX } [ POP ] each
-    JNE
+    JE
 ] { } define-if-intrinsic
 
 "-no-sse2" cli-args member? [
index 811387675a5c6e74e7fa37162f5c18e5ac035ac3..d79ce58d88852e2aef3bd714e0d92ba28b60cd65 100755 (executable)
@@ -11,8 +11,9 @@ IN: cpu.x86.64
 M: x86.64 ds-reg R14 ;
 M: x86.64 rs-reg R15 ;
 M: x86.64 stack-reg RSP ;
-M: x86.64 xt-reg RCX ;
 M: x86.64 stack-save-reg RSI ;
+M: x86.64 temp-reg-1 RAX ;
+M: x86.64 temp-reg-2 RCX ;
 
 M: temp-reg v>operand drop RBX ;
 
index f236cdcfa6698330373d900bf4571f7dd6bd2219..63870f94cddd359dd8c3834910dac989caf12b6e 100755 (executable)
@@ -16,12 +16,12 @@ IN: cpu.x86.allot
 
 : object@ ( n -- operand ) cells (object@) ;
 
-: load-zone-ptr ( -- )
+: load-zone-ptr ( reg -- )
     #! Load pointer to start of zone array
-    "nursery" f allot-reg %alien-global ;
+    0 MOV "nursery" f rc-absolute-cell rel-dlsym ;
 
 : load-allot-ptr ( -- )
-    load-zone-ptr
+    allot-reg load-zone-ptr
     allot-reg PUSH
     allot-reg dup cell [+] MOV ;
 
@@ -29,6 +29,19 @@ IN: cpu.x86.allot
     allot-reg POP
     allot-reg cell [+] swap 8 align ADD ;
 
+M: x86 %gc ( -- )
+    "end" define-label
+    temp-reg-1 load-zone-ptr
+    temp-reg-2 temp-reg-1 cell [+] MOV
+    temp-reg-2 1024 ADD
+    temp-reg-1 temp-reg-1 3 cells [+] MOV
+    temp-reg-2 temp-reg-1 CMP
+    "end" get JLE
+    0 frame-required
+    %prepare-alien-invoke
+    "minor_gc" f %alien-invoke
+    "end" resolve-label ;
+
 : store-header ( header -- )
     0 object@ swap type-number tag-fixnum MOV ;
 
index 25bb3c6e078b4ade65cba05830bc08e43a2ba347..7e7ff8a334e461b9f2ce3eb6cbb5333829e974dc 100755 (executable)
@@ -9,7 +9,6 @@ IN: cpu.x86.architecture
 HOOK: ds-reg cpu
 HOOK: rs-reg cpu
 HOOK: stack-reg cpu
-HOOK: xt-reg cpu
 HOOK: stack-save-reg cpu
 
 : stack@ stack-reg swap [+] ;
@@ -35,6 +34,10 @@ GENERIC: push-return-reg ( reg-class -- )
 GENERIC: load-return-reg ( stack@ reg-class -- )
 GENERIC: store-return-reg ( stack@ reg-class -- )
 
+! Only used by inline allocation
+HOOK: temp-reg-1 cpu
+HOOK: temp-reg-2 cpu
+
 HOOK: address-operand cpu ( address -- operand )
 
 HOOK: fixnum>slot@ cpu
@@ -47,13 +50,13 @@ M: x86 stack-frame ( n -- i )
     3 cells + 16 align cell - ;
 
 M: x86 %save-word-xt ( -- )
-    xt-reg 0 MOV rc-absolute-cell rel-this ;
+    temp-reg v>operand 0 MOV rc-absolute-cell rel-this ;
 
 : factor-area-size 4 cells ;
 
 M: x86 %prologue ( n -- )
     dup cell + PUSH
-    xt-reg PUSH
+    temp-reg v>operand PUSH
     stack-reg swap 2 cells - SUB ;
 
 M: x86 %epilogue ( n -- )
@@ -76,8 +79,8 @@ M: x86 %call ( label -- ) CALL ;
 
 M: x86 %jump-label ( label -- ) JMP ;
 
-M: x86 %jump-t ( label -- )
-    "flag" operand f v>operand CMP JNE ;
+M: x86 %jump-f ( label -- )
+    "flag" operand f v>operand CMP JE ;
 
 : code-alignment ( -- n )
     building get length dup cell align swap - ;
index 80a786c9fa69a68f4cb4387a89ca3cf736a4988f..c48f33b765083301757ce085ba4912f3864cbbca 100755 (executable)
@@ -212,11 +212,11 @@ IN: cpu.x86.intrinsics
     2array define-if-intrinsics ;
 
 {
-    { fixnum< JL }
-    { fixnum<= JLE }
-    { fixnum> JG }
-    { fixnum>= JGE }
-    { eq? JE }
+    { fixnum< JGE }
+    { fixnum<= JG }
+    { fixnum> JLE }
+    { fixnum>= JL }
+    { eq? JNE }
 } [
     first2 define-fixnum-jump
 ] each
index 9c477b413252d7f10648cf895e47385d5e7160e7..fb96649753194da746e82ff247757e24f0170adb 100755 (executable)
@@ -27,11 +27,11 @@ IN: cpu.x86.sse2
     { { float "x" } { float "y" } } define-if-intrinsic ;
 
 {
-    { float< JB }
-    { float<= JBE }
-    { float> JA }
-    { float>= JAE }
-    { float= JE }
+    { float< JAE }
+    { float<= JA }
+    { float> JBE }
+    { float>= JB }
+    { float= JNE }
 } [
     first2 define-float-jump
 ] each
diff --git a/core/float-vectors/float-vectors-docs.factor b/core/float-vectors/float-vectors-docs.factor
deleted file mode 100755 (executable)
index ef0645a..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-USING: arrays float-arrays help.markup help.syntax kernel\r
-float-vectors.private combinators ;\r
-IN: float-vectors\r
-\r
-ARTICLE: "float-vectors" "Float vectors"\r
-"A float vector is a resizable mutable sequence of unsigned floats. The literal syntax is covered in " { $link "syntax-float-vectors" } ". Float vector words are found in the " { $vocab-link "float-vectors" } " vocabulary."\r
-$nl\r
-"Float vectors form a class:"\r
-{ $subsection float-vector }\r
-{ $subsection float-vector? }\r
-"Creating float vectors:"\r
-{ $subsection >float-vector }\r
-{ $subsection <float-vector> }\r
-"If you don't care about initial capacity, a more elegant way to create a new float vector is to write:"\r
-{ $code "FV{ } clone" } ;\r
-\r
-ABOUT: "float-vectors"\r
-\r
-HELP: float-vector\r
-{ $description "The class of resizable float vectors. See " { $link "syntax-float-vectors" } " for syntax and " { $link "float-vectors" } " for general information." } ;\r
-\r
-HELP: <float-vector>\r
-{ $values { "n" "a positive integer specifying initial capacity" } { "float-vector" float-vector } }\r
-{ $description "Creates a new float vector that can hold " { $snippet "n" } " floats before resizing." } ;\r
-\r
-HELP: >float-vector\r
-{ $values { "seq" "a sequence" } { "float-vector" float-vector } }\r
-{ $description "Outputs a freshly-allocated float vector with the same elements as a given sequence." }\r
-{ $errors "Throws an error if the sequence contains elements other than real numbers." } ;\r
-\r
-HELP: float-array>vector\r
-{ $values { "float-array" "an array" } { "length" "a non-negative integer" } { "float-vector" float-vector } }\r
-{ $description "Creates a new float vector using the array for underlying storage with the specified initial length." }\r
-{ $warning "This word is in the " { $vocab-link "float-vectors.private" } " vocabulary because it does not perform type or bounds checks. User code should call " { $link >float-vector } " instead." } ;\r
diff --git a/core/float-vectors/float-vectors-tests.factor b/core/float-vectors/float-vectors-tests.factor
deleted file mode 100755 (executable)
index 383dd4b..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-IN: float-vectors.tests\r
-USING: tools.test float-vectors vectors sequences kernel ;\r
-\r
-[ 0 ] [ 123 <float-vector> length ] unit-test\r
-\r
-: do-it\r
-    12345 [ over push ] each ;\r
-\r
-[ t ] [\r
-    3 <float-vector> do-it\r
-    3 <vector> do-it sequence=\r
-] unit-test\r
-\r
-[ t ] [ FV{ } float-vector? ] unit-test\r
diff --git a/core/float-vectors/float-vectors.factor b/core/float-vectors/float-vectors.factor
deleted file mode 100755 (executable)
index 7f62f6f..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-! Copyright (C) 2008 Slava Pestov.\r
-! See http://factorcode.org/license.txt for BSD license.\r
-USING: arrays kernel kernel.private math sequences\r
-sequences.private growable float-arrays ;\r
-IN: float-vectors\r
-\r
-<PRIVATE\r
-\r
-: float-array>vector ( float-array length -- float-vector )\r
-    float-vector boa ; inline\r
-\r
-PRIVATE>\r
-\r
-: <float-vector> ( n -- float-vector )\r
-    0.0 <float-array> 0 float-array>vector ; inline\r
-\r
-: >float-vector ( seq -- float-vector ) FV{ } clone-like ;\r
-\r
-M: float-vector like\r
-    drop dup float-vector? [\r
-        dup float-array?\r
-        [ dup length float-array>vector ] [ >float-vector ] if\r
-    ] unless ;\r
-\r
-M: float-vector new-sequence\r
-    drop [ 0.0 <float-array> ] keep >fixnum float-array>vector ;\r
-\r
-M: float-vector equal?\r
-    over float-vector? [ sequence= ] [ 2drop f ] if ;\r
-\r
-M: float-array new-resizable drop <float-vector> ;\r
-\r
-INSTANCE: float-vector growable\r
diff --git a/core/float-vectors/summary.txt b/core/float-vectors/summary.txt
deleted file mode 100644 (file)
index c476f41..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Growable float arrays
diff --git a/core/float-vectors/tags.txt b/core/float-vectors/tags.txt
deleted file mode 100644 (file)
index 42d711b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-collections
index 7f4b5026da8cf46a74042a955fd7ff4efd904e2f..f5d530dccbbba9632c13c899f8fed24c3eafe57c 100644 (file)
@@ -13,12 +13,6 @@ HELP: add-literal
 { $values { "obj" object } { "n" integer } }
 { $description "Adds a literal to the " { $link literal-table } ", if it is not already there, and outputs the index of the literal in the table. This literal can then be used as an argument for a " { $link rt-literal } " relocation with " { $link rel-fixup } "." } ;
 
-HELP: string>symbol
-{ $values { "str" string } { "alien" alien } }
-{ $description "Converts the string to a format which is a valid symbol name for the Factor VM's compiled code linker. By performing this conversion ahead of time, the image loader can run without allocating memory."
-$nl
-"On Windows CE, symbols are represented as UCS2 strings, and on all other platforms they are ASCII strings." } ;
-
 HELP: rel-dlsym
 { $values { "name" string } { "dll" "a " { $link dll } " or " { $link f } } { "class" "a relocation class" } }
 { $description "Records that the most recently assembled instruction contains a reference to the " { $snippet "name" } " symbol from " { $snippet "dll" } ". The correct " { $snippet "class" } " to use depends on instruction formats."
index 920690e9d8117a1606e70b909b35cfbf864738e0..ad6cd3051c9f3409ac1d1f27f02c729097bd4700 100755 (executable)
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays generic assocs hashtables
 kernel kernel.private math namespaces sequences words
-quotations strings alien layouts system combinators
+quotations strings alien.strings layouts system combinators
 math.bitfields words.private cpu.architecture ;
 IN: generator.fixup
 
@@ -110,10 +110,6 @@ SYMBOL: literal-table
 
 : add-literal ( obj -- n ) literal-table get push-new* ;
 
-: string>symbol ( str -- alien )
-    [ os wince? [ string>u16-alien ] [ string>char-alien ] if ]
-    over string? [ call ] [ map ] if ;
-
 : add-dlsym-literals ( symbol dll -- )
     >r string>symbol r> 2array literal-table get push-all ;
 
index 919e89d3c8cdc4152b5443ee86586d5edaf1bb56..b8de9c35176bb631b3ba2cdaa9e6fb37668c5e37 100755 (executable)
@@ -40,16 +40,16 @@ SYMBOL: current-label-start
     compiled-stack-traces?
     compiling-word get f ?
     1vector literal-table set
-    f compiling-word get compiled get set-at ;
+    f compiling-label get compiled get set-at ;
 
-: finish-compiling ( literals relocation labels code -- )
+: save-machine-code ( literals relocation labels code -- )
     4array compiling-label get compiled get set-at ;
 
 : with-generator ( node word label quot -- )
     [
         >r begin-compiling r>
         { } make fixup
-        finish-compiling
+        save-machine-code
     ] with-scope ; inline
 
 GENERIC: generate-node ( node -- next )
@@ -73,6 +73,7 @@ GENERIC: generate-node ( node -- next )
 : word-dataflow ( word -- effect dataflow )
     [
         dup "no-effect" word-prop [ no-effect ] when
+        dup "no-compile" word-prop [ no-effect ] when
         dup specialized-def over dup 2array 1array infer-quot
         finish-word
     ] with-infer ;
@@ -131,14 +132,14 @@ M: #loop generate-node
 
 : generate-if ( node label -- next )
     <label> [
-        >r >r node-children first2 generate-branch
+        >r >r node-children first2 swap generate-branch
         r> r> end-false-branch resolve-label
         generate-branch
         init-templates
     ] keep resolve-label iterate-next ;
 
 M: #if generate-node
-    [ <label> dup %jump-t ]
+    [ <label> dup %jump-f ]
     H{ { +input+ { { f "flag" } } } }
     with-template
     generate-if ;
@@ -189,13 +190,13 @@ M: #dispatch generate-node
     "if-intrinsics" set-word-prop ;
 
 : if>boolean-intrinsic ( quot -- )
-    "true" define-label
+    "false" define-label
     "end" define-label
-    "true" get swap call
-    f "if-scratch" get load-literal
-    "end" get %jump-label
-    "true" resolve-label
+    "false" get swap call
     t "if-scratch" get load-literal
+    "end" get %jump-label
+    "false" resolve-label
+    f "if-scratch" get load-literal
     "end" resolve-label
     "if-scratch" get phantom-push ; inline
 
index 627f51acc2d5873a87f208f2445156a023f5ec49..6a1d9ec0f443cf618664e45833e2cd2b0173beff 100755 (executable)
@@ -13,13 +13,6 @@ SYMBOL: +scratch+
 SYMBOL: +clobber+
 SYMBOL: known-tag
 
-! Register classes
-SINGLETON: int-regs
-SINGLETON: single-float-regs
-SINGLETON: double-float-regs
-UNION: float-regs single-float-regs double-float-regs ;
-UNION: reg-class int-regs float-regs ;
-
 <PRIVATE
 
 ! Value protocol
@@ -65,9 +58,7 @@ M: float-regs move-spec drop float ;
 M: float-regs operand-class* drop float ;
 
 ! Temporary register for stack shuffling
-TUPLE: temp-reg reg-class>> ;
-
-: temp-reg T{ temp-reg f int-regs } ;
+SINGLETON: temp-reg
 
 M: temp-reg move-spec drop f ;
 
@@ -470,11 +461,6 @@ M: loc lazy-store
 : finalize-contents ( -- )
     finalize-locs finalize-vregs reset-phantoms ;
 
-: %gc ( -- )
-    0 frame-required
-    %prepare-alien-invoke
-    "simple_gc" f %alien-invoke ;
-
 ! Loading stacks to vregs
 : free-vregs? ( int# float# -- ? )
     double-float-regs free-vregs length <=
index caae16e8ed0d003cd4259f46593d783f64abf16e..6c59d76d07511269fb243b45c7546fe55dd4f5fd 100755 (executable)
@@ -29,6 +29,9 @@ PREDICATE: method-spec < pair
 : order ( generic -- seq )
     "methods" word-prop keys sort-classes ;
 
+: specific-method ( class word -- class )
+    order min-class ;
+
 GENERIC: effective-method ( ... generic -- method )
 
 : next-method-class ( class generic -- class/f )
index 0ffd953d77f5e872db9fd22496fd290efcc8691e..7639d1d49912f9f25ccb37db6d3207df41d08845 100644 (file)
@@ -1,8 +1,11 @@
-IN: generic.standard.engines.tuple
+! 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 generic generic.standard.engines
-classes.algebra math math.private quotations arrays ;
+classes.algebra math math.private kernel.private
+quotations arrays ;
+IN: generic.standard.engines.tuple
 
 TUPLE: echelon-dispatch-engine n methods ;
 
@@ -27,14 +30,7 @@ TUPLE: tuple-dispatch-engine echelons ;
 
 : <tuple-dispatch-engine> ( methods -- engine )
     echelon-sort
-    [
-        over zero? [
-            dup assoc-empty?
-            [ drop f ] [ values first ] if
-        ] [
-            dupd <echelon-dispatch-engine>
-        ] if
-    ] assoc-map [ nip ] assoc-subset
+    [ dupd <echelon-dispatch-engine> ] assoc-map
     \ tuple-dispatch-engine boa ;
 
 : convert-tuple-methods ( assoc -- assoc' )
@@ -48,52 +44,51 @@ M: trivial-tuple-dispatch-engine engine>quot
     >alist V{ } clone [ hashcode 1array ] distribute-buckets
     [ <trivial-tuple-dispatch-engine> ] map ;
 
+: word-hashcode% [ 1 slot ] % ;
+
 : class-hash-dispatch-quot ( methods -- quot )
-    #! 1 slot == word hashcode
     [
-        [ dup 1 slot ] %
+        \ dup ,
+        word-hashcode%
         hash-methods [ engine>quot ] map hash-dispatch-quot %
     ] [ ] make ;
 
-: tuple-dispatch-engine-word-name ( engine -- string )
-    [
-        generic get word-name %
-        "/tuple-dispatch-engine/" %
-        n>> #
-    ] "" make ;
+: engine-word-name ( -- string )
+    generic get word-name "/tuple-dispatch-engine" append ;
 
-PREDICATE: tuple-dispatch-engine-word < word
+PREDICATE: engine-word < word
     "tuple-dispatch-generic" word-prop generic? ;
 
-M: tuple-dispatch-engine-word stack-effect
+M: engine-word stack-effect
     "tuple-dispatch-generic" word-prop
     [ extra-values ] [ stack-effect ] bi
     dup [ clone [ length + ] change-in ] [ 2drop f ] if ;
 
-M: tuple-dispatch-engine-word compiled-crossref?
+M: engine-word compiled-crossref?
     drop t ;
 
 : remember-engine ( word -- )
     generic get "engines" word-prop push ;
 
-: <tuple-dispatch-engine-word> ( engine -- word )
-    tuple-dispatch-engine-word-name f <word>
-    [ generic get "tuple-dispatch-generic" set-word-prop ]
-    [ remember-engine ]
-    [ ]
-    tri ;
+: <engine-word> ( -- word )
+    engine-word-name f <word>
+    dup generic get "tuple-dispatch-generic" set-word-prop ;
 
-: define-tuple-dispatch-engine-word ( engine quot -- word )
-    >r <tuple-dispatch-engine-word> dup r> define ;
+: define-engine-word ( quot -- word )
+    >r <engine-word> dup r> define ;
+
+: array-nth% 2 + , [ slot { word } declare ] % ;
+
+: tuple-layout-superclasses ( obj -- array )
+    { tuple } declare
+    1 slot { tuple-layout } declare
+    4 slot { array } declare ; inline
 
 : tuple-dispatch-engine-body ( engine -- quot )
-    #! 1 slot == tuple-layout
-    #! 2 slot == 0 array-nth
-    #! 4 slot == layout-superclasses
     [
         picker %
-        [ 1 slot 4 slot ] %
-        [ n>> 2 + , [ slot ] % ]
+        [ tuple-layout-superclasses ] %
+        [ n>> array-nth% ]
         [
             methods>> [
                 <trivial-tuple-dispatch-engine> engine>quot
@@ -104,25 +99,54 @@ M: tuple-dispatch-engine-word compiled-crossref?
     ] [ ] make ;
 
 M: echelon-dispatch-engine engine>quot
-    dup tuple-dispatch-engine-body
-    define-tuple-dispatch-engine-word
-    1quotation ;
+    dup n>> zero? [
+        methods>> dup assoc-empty?
+        [ drop default get ] [ values first engine>quot ] if
+    ] [
+        [
+            picker %
+            [ tuple-layout-superclasses ] %
+            [ n>> array-nth% ]
+            [
+                methods>> [
+                    <trivial-tuple-dispatch-engine> engine>quot
+                ] [
+                    class-hash-dispatch-quot
+                ] if-small? %
+            ] bi
+        ] [ ] make
+    ] if ;
 
 : >=-case-quot ( alist -- quot )
     default get [ drop ] prepend swap
     [ >r [ dupd fixnum>= ] curry r> \ drop prefix ] assoc-map
     alist>quot ;
 
+: tuple-layout-echelon ( obj -- array )
+    { tuple } declare
+    1 slot { tuple-layout } declare
+    5 slot ; inline
+
+: unclip-last [ 1 head* ] [ peek ] bi ;
+
 M: tuple-dispatch-engine engine>quot
-    #! 1 slot == tuple-layout
-    #! 5 slot == layout-echelon
     [
         picker %
-        [ 1 slot 5 slot ] %
-        echelons>>
+        [ tuple-layout-echelon ] %
         [
             tuple assumed set
-            [ engine>quot dup default set ] assoc-map
+            echelons>> dup empty? [
+                unclip-last
+                [
+                    [
+                        engine>quot define-engine-word
+                        [ remember-engine ] [ 1quotation ] bi
+                        dup default set
+                    ] assoc-map
+                ]
+                [ first2 engine>quot 2array ] bi*
+                suffix
+            ] unless
         ] with-scope
         >=-case-quot %
     ] [ ] make ;
index 8799169445a4cb342325756dc836e2c367a60bb8..1bff9ae15d716260360639e03b8bb4e96b0aa7fe 100644 (file)
@@ -3,7 +3,7 @@ USING: tools.test math math.functions math.constants
 generic.standard strings sequences arrays kernel accessors
 words float-arrays byte-arrays bit-arrays parser namespaces
 quotations inference vectors growable hashtables sbufs
-prettyprint ;
+prettyprint byte-vectors bit-vectors float-vectors ;
 
 GENERIC: lo-tag-test
 
@@ -251,6 +251,14 @@ 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?
index 0125f04efad796ff4d124fe62a20c31484f62f39..91314d13120121507fb12027bd32ed28885520eb 100755 (executable)
@@ -48,10 +48,6 @@ HELP: no-effect
 { $description "Throws a " { $link no-effect } " error." }
 { $error-description "Thrown when inference encounters a call to a word which is already known not to have a static stack effect, due to a prior inference attempt failing." } ;
 
-HELP: collect-recursion
-{ $values { "#label" "a " { $link #label } " node" } { "seq" "a new sequence" } }
-{ $description "Collect the input stacks of all child " { $link #call-label } " nodes that call the given label." } ;
-
 HELP: inline-word
 { $values { "word" word } }
 { $description "Called during inference to infer stack effects of inline words."
index cf40944d1d01b4e7671b66df8b3b19452ebd96e5..f60748a5ac1a4ae5b9852574d583899f30701f2c 100755 (executable)
@@ -15,7 +15,7 @@ GENERIC: inline? ( word -- ? )
 M: method-body inline?
     "method-generic" word-prop inline? ;
 
-M: tuple-dispatch-engine-word inline?
+M: engine-word inline?
     "tuple-dispatch-generic" word-prop inline? ;
 
 M: word inline?
@@ -130,25 +130,27 @@ TUPLE: too-many->r ;
 
 TUPLE: too-many-r> ;
 
-: check-r> ( -- )
-    meta-r get empty?
+: check-r> ( -- )
+    meta-r get length >
     [ \ too-many-r> inference-error ] when ;
 
-: infer->r ( -- )
-    1 ensure-values
+: infer->r ( -- )
+    dup ensure-values
     #>r
-    1 0 pick node-inputs
-    pop-d push-r
-    0 1 pick node-outputs
-    node, ;
+    over 0 pick node-inputs
+    over [ drop pop-d ] map reverse [ push-r ] each
+    0 pick pick node-outputs
+    node,
+    drop ;
 
-: infer-r> ( -- )
-    check-r>
+: infer-r> ( -- )
+    dup check-r>
     #r>
-    0 1 pick node-inputs
-    pop-r push-d
-    1 0 pick node-outputs
-    node, ;
+    0 pick pick node-inputs
+    over [ drop pop-r ] map reverse [ push-d ] each
+    over 0 pick node-outputs
+    node,
+    drop ;
 
 : undo-infer ( -- )
     recorded get [ f "inferred-effect" set-word-prop ] each ;
@@ -199,18 +201,18 @@ M: object constructor drop f ;
     dup infer-uncurry
     constructor [
         peek-d reify-curry
-        infer->r
+        infer->r
         peek-d reify-curry
-        infer-r>
+        infer-r>
         2 1 <effect> swap #call consume/produce
     ] when* ;
 
 : reify-curries ( n -- )
     meta-d get reverse [
         dup special? [
-            over [ infer->r ] times
+            over infer->r
             dup reify-curry
-            over [ infer-r> ] times
+            over infer-r>
         ] when 2drop
     ] 2each ;
 
@@ -407,6 +409,25 @@ TUPLE: recursive-declare-error word ;
         \ recursive-declare-error inference-error
     ] if* ;
 
+GENERIC: collect-label-info* ( label node -- )
+
+M: node collect-label-info* 2drop ;
+
+: (collect-label-info) ( label node vector -- )
+    >r tuck [ param>> ] bi@ eq? r> [ push ] curry [ drop ] if ;
+    inline
+
+M: #call-label collect-label-info*
+    over calls>> (collect-label-info) ;
+
+M: #return collect-label-info*
+    over returns>> (collect-label-info) ;
+
+: collect-label-info ( #label -- )
+    V{ } clone >>calls
+    V{ } clone >>returns
+    dup [ collect-label-info* ] with each-node ;
+
 : nest-node ( -- ) #entry node, ;
 
 : unnest-node ( new-node -- new-node )
@@ -417,27 +438,17 @@ TUPLE: recursive-declare-error word ;
 
 : <inlined-block> gensym dup t "inlined-block" set-word-prop ;
 
-: inline-block ( word -- node-block data )
+: inline-block ( word -- #label data )
     [
         copy-inference nest-node
         dup word-def swap <inlined-block>
         [ infer-quot-recursive ] 2keep
         #label unnest-node
+        dup collect-label-info
     ] H{ } make-assoc ;
 
-GENERIC: collect-recursion* ( label node -- )
-
-M: node collect-recursion* 2drop ;
-
-M: #call-label collect-recursion*
-    tuck node-param eq? [ , ] [ drop ] if ;
-
-: collect-recursion ( #label -- seq )
-    dup node-param
-    [ [ swap collect-recursion* ] curry each-node ] { } make ;
-
-: join-values ( node -- )
-    collect-recursion [ node-in-d ] map meta-d get suffix
+: join-values ( #label -- )
+    calls>> [ node-in-d ] map meta-d get suffix
     unify-lengths unify-stacks
     meta-d [ length tail* ] change ;
 
@@ -458,7 +469,7 @@ M: #call-label collect-recursion*
         drop join-values inline-block apply-infer
         r> over set-node-in-d
         dup node,
-        collect-recursion [
+        calls>> [
             [ flatten-curries ] modify-values
         ] each
     ] [
index 038ab1d2300288681c84471d93357c4bcf5bf655..0c4ff82798bdeec478f925704c3ec4e25bbea8f1 100755 (executable)
@@ -4,7 +4,12 @@ inference.dataflow optimizer tools.test kernel.private generic
 sequences words inference.class quotations alien
 alien.c-types strings sbufs sequences.private
 slots.private combinators definitions compiler.units
-system layouts vectors ;
+system layouts vectors optimizer.math.partial accessors
+optimizer.inlining ;
+
+[ t ] [ T{ literal-constraint f 1 2 } T{ literal-constraint f 1 2 } equal? ] unit-test
+
+[ f ] [ T{ literal-constraint f 1 3 } T{ literal-constraint f 1 2 } equal? ] unit-test
 
 ! Make sure these compile even though this is invalid code
 [ ] [ [ 10 mod 3.0 /i ] dataflow optimize drop ] unit-test
@@ -13,9 +18,15 @@ system layouts vectors ;
 ! Ensure type inference works as it is supposed to by checking
 ! if various methods get inlined
 
-: inlined? ( quot word -- ? )
+: inlined? ( quot seq/word -- ? )
+    dup word? [ 1array ] when
     swap dataflow optimize
-    [ node-param eq? ] with node-exists? not ;
+    [ node-param swap member? ] with node-exists? not ;
+
+[ f ] [
+    [ { integer } declare >fixnum ]
+    \ >fixnum inlined?
+] unit-test
 
 GENERIC: mynot ( x -- y )
 
@@ -109,12 +120,17 @@ M: object xyz ;
     [ { fixnum } declare [ ] times ] \ fixnum+ inlined?
 ] unit-test
 
-[ f ] [
+[ t ] [
     [ { integer fixnum } declare dupd < [ 1 + ] when ]
     \ + inlined?
 ] unit-test
 
-[ f ] [ [ dup 0 < [ neg ] when ] \ neg inlined? ] unit-test
+[ f ] [
+    [ { integer fixnum } declare dupd < [ 1 + ] when ]
+    \ +-integer-fixnum inlined?
+] unit-test
+
+[ f ] [ [ dup 0 < [ neg ] when ] \ - inlined? ] unit-test
 
 [ f ] [
     [
@@ -137,13 +153,13 @@ M: object xyz ;
 
 DEFER: blah
 
-[ ] [
+[ ] [
     [
         \ blah
         [ dup V{ } eq? [ foo ] when ] dup second dup push define
     ] with-compilation-unit
 
-    \ blah compiled?
+    \ blah word-def dataflow optimize drop
 ] unit-test
 
 GENERIC: detect-fx ( n -- n )
@@ -158,14 +174,20 @@ M: fixnum detect-fx ;
     ] \ detect-fx inlined?
 ] unit-test
 
+[ t ] [
+    [
+        1000000000000000000000000000000000 [ ] times
+    ] \ + inlined?
+] unit-test
 [ f ] [
     [
         1000000000000000000000000000000000 [ ] times
-    ] \ 1+ inlined?
+    ] \ +-integer-fixnum inlined?
 ] unit-test
 
 [ f ] [
-    [ { bignum } declare [ ] times ] \ 1+ inlined?
+    [ { bignum } declare [ ] times ]
+    \ +-integer-fixnum inlined?
 ] unit-test
 
 
@@ -251,19 +273,24 @@ M: float detect-float ;
     [ 3 + = ] \ equal? inlined?
 ] unit-test
 
-[ t ] [
+[ f ] [
     [ { fixnum fixnum } declare 7 bitand neg shift ]
-    \ shift inlined?
+    \ fixnum-shift-fast inlined?
 ] unit-test
 
 [ t ] [
     [ { fixnum fixnum } declare 7 bitand neg shift ]
-    \ fixnum-shift inlined?
+    { shift fixnum-shift } inlined?
 ] unit-test
 
 [ t ] [
     [ { fixnum fixnum } declare 1 swap 7 bitand shift ]
-    \ fixnum-shift inlined?
+    { shift fixnum-shift } inlined?
+] unit-test
+
+[ f ] [
+    [ { fixnum fixnum } declare 1 swap 7 bitand shift ]
+    { fixnum-shift-fast } inlined?
 ] unit-test
 
 cell-bits 32 = [
@@ -278,6 +305,11 @@ cell-bits 32 = [
     ] unit-test
 ] when
 
+[ f ] [
+    [ { integer } declare -63 shift 4095 bitand ]
+    \ shift inlined?
+] unit-test
+
 [ t ] [
     [ B{ 1 0 } *short 0 number= ]
     \ number= inlined?
@@ -323,3 +355,228 @@ cell-bits 32 = [
         ] when
     ] \ + inlined?
 ] unit-test
+
+[ f ] [
+    [
+        256 mod
+    ] { mod fixnum-mod } inlined?
+] unit-test
+
+[ f ] [
+    [
+        dup 0 >= [ 256 mod ] when
+    ] { mod fixnum-mod } inlined?
+] unit-test
+
+[ t ] [
+    [
+        { integer } declare dup 0 >= [ 256 mod ] when
+    ] { mod fixnum-mod } inlined?
+] unit-test
+
+[ t ] [
+    [
+        { integer } declare 256 rem
+    ] { mod fixnum-mod } inlined?
+] unit-test
+
+[ t ] [
+    [
+        { integer } declare [ 256 rem ] map
+    ] { mod fixnum-mod rem } inlined?
+] unit-test
+
+[ t ] [
+    [ 1000 [ 1+ ] map ] { 1+ fixnum+ } inlined?
+] unit-test
+
+: rec ( a -- b )
+    dup 0 > [ 1 - rec ] when ; inline
+
+[ t ] [
+    [ { fixnum } declare rec 1 + ]
+    { > - + } inlined?
+] unit-test
+
+: fib ( m -- n )
+    dup 2 < [ drop 1 ] [ dup 1 - fib swap 2 - fib + ] if ; inline
+
+[ t ] [
+    [ 27.0 fib ] { < - + } inlined?
+] unit-test
+
+[ f ] [
+    [ 27.0 fib ] { +-integer-integer } inlined?
+] unit-test
+
+[ t ] [
+    [ 27 fib ] { < - + } inlined?
+] unit-test
+
+[ t ] [
+    [ 27 >bignum fib ] { < - + } inlined?
+] unit-test
+
+[ f ] [
+    [ 27/2 fib ] { < - } inlined?
+] unit-test
+
+: hang-regression ( m n -- x )
+    over 0 number= [
+        nip
+    ] [
+        dup [
+            drop 1 hang-regression
+        ] [
+            dupd hang-regression hang-regression
+        ] if
+    ] if ; inline
+
+[ t ] [
+    [ dup fixnum? [ 3 over hang-regression ] [ 3 over hang-regression ] if
+] { } inlined? ] unit-test
+
+: detect-null ( a -- b ) dup drop ;
+
+\ detect-null {
+    { [ dup dup in-d>> first node-class null eq? ] [ [ ] f splice-quot ] }
+} define-optimizers
+
+[ t ] [
+    [ { null } declare detect-null ] \ detect-null inlined?
+] unit-test
+
+[ t ] [
+    [ { null null } declare + detect-null ] \ detect-null inlined?
+] unit-test
+
+[ f ] [
+    [ { null fixnum } declare + detect-null ] \ detect-null inlined?
+] unit-test
+
+GENERIC: detect-integer ( a -- b )
+
+M: integer detect-integer ;
+
+[ t ] [
+    [ { null fixnum } declare + detect-integer ] \ detect-integer inlined?
+] unit-test
+
+[ t ] [
+    [ { fixnum } declare 10 [ -1 shift ] times ] \ shift inlined?
+] unit-test
+
+[ f ] [
+    [ { integer } declare 10 [ -1 shift ] times ] \ shift inlined?
+] unit-test
+
+[ f ] [
+    [ { fixnum } declare 1048575 fixnum-bitand 524288 fixnum- ]
+    \ fixnum-bitand inlined?
+] unit-test
+
+[ t ] [
+    [ { integer } declare 127 bitand 3 + ]
+    { + +-integer-fixnum +-integer-fixnum-fast bitand } inlined?
+] unit-test
+
+[ f ] [
+    [ { integer } declare 127 bitand 3 + ]
+    { >fixnum } inlined?
+] unit-test
+
+[ t ] [
+    [ { fixnum } declare [ drop ] each-integer ]
+    { < <-integer-fixnum +-integer-fixnum + } inlined?
+] unit-test
+
+[ t ] [
+    [ { fixnum } declare length [ drop ] each-integer ]
+    { < <-integer-fixnum +-integer-fixnum + } inlined?
+] unit-test
+
+[ t ] [
+    [ { fixnum } declare [ drop ] each ]
+    { < <-integer-fixnum +-integer-fixnum + } inlined?
+] unit-test
+
+[ t ] [
+    [ { fixnum } declare 0 [ + ] reduce ]
+    { < <-integer-fixnum } inlined?
+] unit-test
+
+[ f ] [
+    [ { fixnum } declare 0 [ + ] reduce ]
+    \ +-integer-fixnum inlined?
+] unit-test
+
+[ t ] [
+    [
+        { integer } declare
+        dup 0 >= [
+            615949 * 797807 + 20 2^ mod dup 19 2^ -
+        ] [ dup ] if
+    ] { * + shift mod fixnum-mod fixnum* fixnum+ fixnum- } inlined?
+] unit-test
+
+[ t ] [
+    [
+        { fixnum } declare
+        615949 * 797807 + 20 2^ mod dup 19 2^ -
+    ] { >fixnum } inlined?
+] unit-test
+
+[ f ] [
+    [
+        { integer } declare [ ] map
+    ] \ >fixnum inlined?
+] unit-test
+
+[ f ] [
+    [
+        { integer } declare { } set-nth-unsafe
+    ] \ >fixnum inlined?
+] unit-test
+
+[ f ] [
+    [
+        { integer } declare 1 + { } set-nth-unsafe
+    ] \ >fixnum inlined?
+] unit-test
+
+[ t ] [
+    [
+        { integer } declare 0 swap
+        [
+            drop 615949 * 797807 + 20 2^ rem dup 19 2^ -
+        ] map
+    ] { * + shift rem mod fixnum-mod fixnum* fixnum+ fixnum- } inlined?
+] unit-test
+
+[ t ] [
+    [
+        { fixnum } declare 0 swap
+        [
+            drop 615949 * 797807 + 20 2^ rem dup 19 2^ -
+        ] map
+    ] { * + shift rem mod fixnum-mod fixnum* fixnum+ fixnum- >fixnum } inlined?
+] unit-test
+
+[ t ] [
+    [ { integer } declare bitnot detect-integer ]
+    \ detect-integer inlined?
+] unit-test
+
+! Later
+
+! [ t ] [
+!     [
+!         { integer } declare [ 256 mod ] map
+!     ] { mod fixnum-mod } inlined?
+! ] unit-test
+! 
+! [ t ] [
+!     [
+!         { integer } declare [ 0 >= ] map
+!     ] { >= fixnum>= } inlined?
+! ] unit-test
index 033d2cce7a0728ec8ab3a3b000aff292ad8fa78b..6d5b708f346cbe395d754b9f96447eb72907a953 100755 (executable)
@@ -1,9 +1,9 @@
-! Copyright (C) 2004, 2007 Slava Pestov.
+! Copyright (C) 2004, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays generic assocs hashtables inference kernel
 math namespaces sequences words parser math.intervals
 effects classes classes.algebra inference.dataflow
-inference.backend combinators ;
+inference.backend combinators accessors ;
 IN: inference.class
 
 ! Class inference
@@ -25,12 +25,10 @@ C: <literal-constraint> literal-constraint
 
 M: literal-constraint equal?
     over literal-constraint? [
-        2dup
-        [ literal-constraint-literal ] bi@ eql? >r
-        [ literal-constraint-value ] bi@ = r> and
-    ] [
-        2drop f
-    ] if ;
+        [ [ literal>> ] bi@ eql? ]
+        [ [ value>>   ] bi@ =    ]
+        2bi and
+    ] [ 2drop f ] if ;
 
 TUPLE: class-constraint class value ;
 
@@ -43,8 +41,8 @@ C: <interval-constraint> interval-constraint
 GENERIC: apply-constraint ( constraint -- )
 GENERIC: constraint-satisfied? ( constraint -- ? )
 
-: `input node get node-in-d nth ;
-: `output node get node-out-d nth ;
+: `input node get in-d>> nth ;
+: `output node get out-d>> nth ;
 : class, <class-constraint> , ;
 : literal, <literal-constraint> , ;
 : interval, <interval-constraint> , ;
@@ -84,14 +82,12 @@ SYMBOL: value-classes
     set-value-interval* ;
 
 M: interval-constraint apply-constraint
-    dup interval-constraint-interval
-    swap interval-constraint-value intersect-value-interval ;
+    [ interval>> ] [ value>> ] bi intersect-value-interval ;
 
 : set-class-interval ( class value -- )
     over class? [
-        over "interval" word-prop [
-            >r "interval" word-prop r> set-value-interval*
-        ] [ 2drop ] if
+        >r "interval" word-prop r> over
+        [ set-value-interval* ] [ 2drop ] if
     ] [ 2drop ] if ;
 
 : value-class* ( value -- class )
@@ -110,18 +106,21 @@ M: interval-constraint apply-constraint
     [ value-class* class-and ] keep set-value-class* ;
 
 M: class-constraint apply-constraint
-    dup class-constraint-class
-    swap class-constraint-value intersect-value-class ;
+    [ class>> ] [ value>> ] bi intersect-value-class ;
+
+: literal-interval ( value -- interval/f )
+    dup real? [ [a,a] ] [ drop f ] if ;
 
 : set-value-literal* ( literal value -- )
-    over class over set-value-class*
-    over real? [ over [a,a] over set-value-interval* ] when
-    2dup <literal-constraint> assume
-    value-literals get set-at ;
+    {
+        [ >r class r> set-value-class* ]
+        [ >r literal-interval r> set-value-interval* ]
+        [ <literal-constraint> assume ]
+        [ value-literals get set-at ]
+    } 2cleave ;
 
 M: literal-constraint apply-constraint
-    dup literal-constraint-literal
-    swap literal-constraint-value set-value-literal* ;
+    [ literal>> ] [ value>> ] bi set-value-literal* ;
 
 ! For conditionals, an assoc of child node # --> constraint
 GENERIC: child-constraints ( node -- seq )
@@ -133,19 +132,18 @@ GENERIC: infer-classes-around ( node -- )
 M: node infer-classes-before drop ;
 
 M: node child-constraints
-    node-children length
+    children>> length
     dup zero? [ drop f ] [ f <repetition> ] if ;
 
 : value-literal* ( value -- obj ? )
     value-literals get at* ;
 
 M: literal-constraint constraint-satisfied?
-    dup literal-constraint-value value-literal*
-    [ swap literal-constraint-literal eql? ] [ 2drop f ] if ;
+    dup value>> value-literal*
+    [ swap literal>> eql? ] [ 2drop f ] if ;
 
 M: class-constraint constraint-satisfied?
-    dup class-constraint-value value-class*
-    swap class-constraint-class class< ;
+    [ value>> value-class* ] [ class>> ] bi class< ;
 
 M: pair apply-constraint
     first2 2dup constraints get set-at
@@ -154,19 +152,18 @@ M: pair apply-constraint
 M: pair constraint-satisfied?
     first constraint-satisfied? ;
 
-: extract-keys ( assoc seq -- newassoc )
-    dup length <hashtable> swap [
-        dup >r pick at* [ r> pick set-at ] [ r> 2drop ] if
-    ] each nip f assoc-like ;
+: extract-keys ( seq assoc -- newassoc )
+    [ dupd at ] curry H{ } map>assoc [ nip ] assoc-subset f assoc-like ;
 
 : annotate-node ( node -- )
     #! Annotate the node with the currently-inferred set of
     #! value classes.
-    dup node-values
-    value-intervals get over extract-keys pick set-node-intervals
-    value-classes get over extract-keys pick set-node-classes
-    value-literals get over extract-keys pick set-node-literals
-    2drop ;
+    dup node-values {
+        [ value-intervals get extract-keys >>intervals ]
+        [ value-classes   get extract-keys >>classes   ]
+        [ value-literals  get extract-keys >>literals  ]
+        [ 2drop ]
+    } cleave ;
 
 : intersect-classes ( classes values -- )
     [ intersect-value-class ] 2each ;
@@ -190,31 +187,29 @@ M: pair constraint-satisfied?
     ] 2bi ;
 
 : compute-constraints ( #call -- )
-    dup node-param "constraints" word-prop [
+    dup param>> "constraints" word-prop [
         call
     ] [
-        dup node-param "predicating" word-prop dup
+        dup param>> "predicating" word-prop dup
         [ swap predicate-constraints ] [ 2drop ] if
     ] if* ;
 
 : compute-output-classes ( node word -- classes intervals )
-    dup node-param "output-classes" word-prop
+    dup param>> "output-classes" word-prop
     dup [ call ] [ 2drop f f ] if ;
 
 : output-classes ( node -- classes intervals )
     dup compute-output-classes >r
-    [ ] [ node-param "default-output-classes" word-prop ] ?if
+    [ ] [ param>> "default-output-classes" word-prop ] ?if
     r> ;
 
 M: #call infer-classes-before
-    dup compute-constraints
-    dup node-out-d swap output-classes
-    >r over intersect-classes
-    r> swap intersect-intervals ;
+    [ compute-constraints ] keep
+    [ output-classes ] [ out-d>> ] bi
+    tuck [ intersect-classes ] [ intersect-intervals ] 2bi* ;
 
 M: #push infer-classes-before
-    node-out-d
-    [ [ value-literal ] keep set-value-literal* ] each ;
+    out-d>> [ [ value-literal ] keep set-value-literal* ] each ;
 
 M: #if child-constraints
     [
@@ -224,19 +219,17 @@ M: #if child-constraints
 
 M: #dispatch child-constraints
     dup [
-        node-children length [
-            0 `input literal,
-        ] each
+        children>> length [ 0 `input literal, ] each
     ] make-constraints ;
 
 M: #declare infer-classes-before
-    dup node-param swap node-in-d
+    [ param>> ] [ in-d>> ] bi
     [ intersect-value-class ] 2each ;
 
 DEFER: (infer-classes)
 
 : infer-children ( node -- )
-    dup node-children swap child-constraints [
+    [ children>> ] [ child-constraints ] bi [
         [
             value-classes [ clone ] change
             value-literals [ clone ] change
@@ -251,27 +244,27 @@ DEFER: (infer-classes)
     >r dup [ length ] map supremum r> [ pad-left ] 2curry map ;
 
 : (merge-classes) ( nodes -- seq )
-    [ node-input-classes ] map
-    null pad-all flip [ null [ class-or ] reduce ] map ;
+    dup length 1 = [
+        first node-input-classes
+    ] [
+        [ node-input-classes ] map null pad-all flip
+        [ null [ class-or ] reduce ] map
+    ] if ;
 
 : set-classes ( seq node -- )
-    node-out-d [ set-value-class* ] 2reverse-each ;
+    out-d>> [ set-value-class* ] 2reverse-each ;
 
 : merge-classes ( nodes node -- )
     >r (merge-classes) r> set-classes ;
 
-: (merge-intervals) ( nodes quot -- seq )
-    >r
-    [ node-input-intervals ] map
-    f pad-all flip
-    r> map ; inline
-
 : set-intervals ( seq node -- )
-    node-out-d [ set-value-interval* ] 2reverse-each ;
+    out-d>> [ set-value-interval* ] 2reverse-each ;
 
 : merge-intervals ( nodes node -- )
-    >r [ dup first [ interval-union ] reduce ]
-    (merge-intervals) r> set-intervals ;
+    >r
+    [ node-input-intervals ] map f pad-all flip
+    [ dup first [ interval-union ] reduce ] map
+    r> set-intervals ;
 
 : annotate-merge ( nodes #merge/#entry -- )
     [ merge-classes ] [ merge-intervals ] 2bi ;
@@ -280,28 +273,68 @@ DEFER: (infer-classes)
     dup node-successor dup #merge? [
         swap active-children dup empty?
         [ 2drop ] [ swap annotate-merge ] if
-    ] [
-        2drop
-    ] if ;
+    ] [ 2drop ] if ;
+
+: classes= ( inferred current -- ? )
+    2dup min-length [ tail* ] curry bi@ sequence= ;
+
+SYMBOL: fixed-point?
+
+SYMBOL: nested-labels
 
 : annotate-entry ( nodes #label -- )
-    node-child merge-classes ;
+    >r (merge-classes) r> node-child
+    2dup node-output-classes classes=
+    [ 2drop ] [ set-classes fixed-point? off ] if ;
+
+: init-recursive-calls ( #label -- )
+    #! We set recursive calls to output the empty type, then
+    #! repeat inference until a fixed point is reached.
+    #! Hopefully, our type functions are monotonic so this
+    #! will always converge.
+    returns>> [ dup in-d>> [ null ] { } map>assoc >>classes drop ] each ;
 
 M: #label infer-classes-before ( #label -- )
-    #! First, infer types under the hypothesis which hold on
-    #! entry to the recursive label.
-    [ 1array ] keep annotate-entry ;
+    [ init-recursive-calls ]
+    [ [ 1array ] keep annotate-entry ] bi ;
+
+: infer-label-loop ( #label -- )
+    fixed-point? on
+    dup node-child (infer-classes)
+    dup [ calls>> ] [ suffix ] [ annotate-entry ] tri
+    fixed-point? get [ drop ] [ infer-label-loop ] if ;
 
 M: #label infer-classes-around ( #label -- )
     #! Now merge the types at every recursion point with the
     #! entry types.
-    {
-        [ annotate-node ]
-        [ infer-classes-before ]
-        [ infer-children ]
-        [ [ collect-recursion ] [ suffix ] [ annotate-entry ] tri ]
-        [ node-child (infer-classes) ]
-    } cleave ;
+    [
+        {
+            [ nested-labels get push ]
+            [ annotate-node ]
+            [ infer-classes-before ]
+            [ infer-label-loop ]
+            [ drop nested-labels get pop* ]
+        } cleave
+    ] with-scope ;
+
+: find-label ( param -- #label )
+    param>> nested-labels get [ param>> eq? ] with find nip ;
+
+M: #call-label infer-classes-before ( #call-label -- )
+    [ find-label returns>> (merge-classes) ] [ out-d>> ] bi
+    [ set-value-class* ] 2each ;
+
+M: #return infer-classes-around
+    nested-labels get length 0 > [
+        dup param>> nested-labels get peek param>> eq? [
+            [ ] [ node-input-classes ] [ in-d>> [ value-class* ] map ] tri
+            classes= not [
+                fixed-point? off
+                [ in-d>> value-classes get extract-keys ] keep
+                set-node-classes
+            ] [ drop ] if
+        ] [ call-next-method ] if
+    ] [ call-next-method ] if ;
 
 M: object infer-classes-around
     {
@@ -314,11 +347,13 @@ M: object infer-classes-around
 : (infer-classes) ( node -- )
     [
         [ infer-classes-around ]
-        [ node-successor (infer-classes) ] bi
+        [ node-successor ] bi
+        (infer-classes)
     ] when* ;
 
 : infer-classes-with ( node classes literals intervals -- )
     [
+        V{ } clone nested-labels set
         H{ } assoc-like value-intervals set
         H{ } assoc-like value-literals set
         H{ } assoc-like value-classes set
@@ -326,13 +361,11 @@ M: object infer-classes-around
         (infer-classes)
     ] with-scope ;
 
-: infer-classes ( node -- )
-    f f f infer-classes-with ;
+: infer-classes ( node -- node )
+    dup f f f infer-classes-with ;
 
 : infer-classes/node ( node existing -- )
     #! Infer classes, using the existing node's class info as a
     #! starting point.
-    dup node-classes
-    over node-literals
-    rot node-intervals
+    [ classes>> ] [ literals>> ] [ intervals>> ] tri
     infer-classes-with ;
index 3fb047b781123ab33b97a1296a0fd3e9f3a6b7a9..bb66a5386cf0610ab03d79797c5e744a7a0653d9 100755 (executable)
@@ -90,7 +90,7 @@ M: object flatten-curry , ;
 
 : node-child node-children first ;
 
-TUPLE: #label < node word loop? ;
+TUPLE: #label < node word loop? returns calls ;
 
 : #label ( word label -- node )
     \ #label param-node swap >>word ;
@@ -290,6 +290,9 @@ SYMBOL: node-stack
 : node-input-classes ( node -- seq )
     dup in-d>> [ node-class ] with map ;
 
+: node-output-classes ( node -- seq )
+    dup out-d>> [ node-class ] with map ;
+
 : node-input-intervals ( node -- seq )
     dup in-d>> [ node-interval ] with map ;
 
index 453e2460b0362529e5f7ba7746f2931100d7248d..b68c98d25d5cdf2c34cbfce6befeb4cb1675ea3b 100755 (executable)
@@ -54,9 +54,9 @@ IN: inference.known-words
     { swap  T{ effect f 2 { 1 0         } } }
 } [ define-shuffle ] assoc-each
 
-\ >r [ infer->r ] "infer" set-word-prop
+\ >r [ infer->r ] "infer" set-word-prop
 
-\ r> [ infer-r> ] "infer" set-word-prop
+\ r> [ infer-r> ] "infer" set-word-prop
 
 \ declare [
     1 ensure-values
@@ -81,8 +81,8 @@ M: curried infer-call
 
 M: composed infer-call
     infer-uncurry
-    infer->r peek-d infer-call
-    terminated? get [ infer-r> peek-d infer-call ] unless ;
+    infer->r peek-d infer-call
+    terminated? get [ infer-r> peek-d infer-call ] unless ;
 
 M: object infer-call
     \ literal-expected inference-warning ;
@@ -92,6 +92,8 @@ M: object infer-call
     peek-d infer-call
 ] "infer" set-word-prop
 
+\ call t "no-compile" set-word-prop
+
 \ execute [
     1 ensure-values
     pop-literal nip
@@ -471,18 +473,6 @@ set-primitive-effect
 
 \ set-alien-cell { c-ptr c-ptr integer } { } <effect> set-primitive-effect
 
-\ alien>char-string { c-ptr } { string } <effect> set-primitive-effect
-\ alien>char-string make-flushable
-
-\ string>char-alien { string } { byte-array } <effect> set-primitive-effect
-\ string>char-alien make-flushable
-
-\ alien>u16-string { c-ptr } { string } <effect> set-primitive-effect
-\ alien>u16-string make-flushable
-
-\ string>u16-alien { string } { byte-array } <effect> set-primitive-effect
-\ string>u16-alien make-flushable
-
 \ alien-address { alien } { integer } <effect> set-primitive-effect
 \ alien-address make-flushable
 
index bdd9e56d87df19a0bf065c1b6251cab45db1ac90..8a176ce4ec7db6b7a30df6d3b6ce5146e96c2074 100644 (file)
@@ -41,12 +41,13 @@ $low-level-note ;
 
 ARTICLE: "encodings-descriptors" "Encoding descriptors"
 "An encoding descriptor is something which can be used for input or output streams to encode or decode files. It must conform to the " { $link "encodings-protocol" } ". Encodings which you can use are defined in the following vocabularies:"
-{ $vocab-subsection "ASCII" "io.encodings.ascii" }
-{ $vocab-subsection "Binary" "io.encodings.binary" }
+{ $subsection "io.encodings.binary" }
+{ $subsection "io.encodings.utf8" }
+{ $subsection "io.encodings.utf16" }
 { $vocab-subsection "Strict encodings" "io.encodings.strict" }
+"Legacy encodings:"
 { $vocab-subsection "8-bit encodings" "io.encodings.8-bit" }
-{ $vocab-subsection "UTF-8" "io.encodings.utf8" }
-{ $vocab-subsection "UTF-16" "io.encodings.utf16" }
+{ $vocab-subsection "ASCII" "io.encodings.ascii" }
 { $see-also "encodings-introduction" } ;
 
 ARTICLE: "encodings-protocol" "Encoding protocol"
diff --git a/core/io/encodings/utf16/.utf16.factor.swo b/core/io/encodings/utf16/.utf16.factor.swo
new file mode 100644 (file)
index 0000000..01be8fd
Binary files /dev/null and b/core/io/encodings/utf16/.utf16.factor.swo differ
diff --git a/core/io/encodings/utf16/authors.txt b/core/io/encodings/utf16/authors.txt
new file mode 100644 (file)
index 0000000..f990dd0
--- /dev/null
@@ -0,0 +1 @@
+Daniel Ehrenberg
diff --git a/core/io/encodings/utf16/summary.txt b/core/io/encodings/utf16/summary.txt
new file mode 100644 (file)
index 0000000..b249067
--- /dev/null
@@ -0,0 +1 @@
+UTF16 encoding/decoding
diff --git a/core/io/encodings/utf16/tags.txt b/core/io/encodings/utf16/tags.txt
new file mode 100644 (file)
index 0000000..8e27be7
--- /dev/null
@@ -0,0 +1 @@
+text
diff --git a/core/io/encodings/utf16/utf16-docs.factor b/core/io/encodings/utf16/utf16-docs.factor
new file mode 100644 (file)
index 0000000..f37a9d1
--- /dev/null
@@ -0,0 +1,24 @@
+USING: help.markup help.syntax io.encodings strings ;
+IN: io.encodings.utf16
+
+ARTICLE: "io.encodings.utf16" "UTF-16"
+"The UTF-16 encoding is a variable-width encoding. Unicode code points are encoded as 2 or 4 byte sequences. There are three encoding descriptor classes for working with UTF-16, depending on endianness or the presence of a BOM:"
+{ $subsection utf16 }
+{ $subsection utf16le }
+{ $subsection utf16be } ;
+
+ABOUT: "io.encodings.utf16"
+
+HELP: utf16le
+{ $class-description "The encoding descriptor for UTF-16LE, that is, UTF-16 in little endian, without a byte order mark. Streams can be made which read or write wth this encoding." }
+{ $see-also "encodings-introduction" } ;
+
+HELP: utf16be
+{ $class-description "The encoding descriptor for UTF-16BE, that is, UTF-16 in big endian, without a byte order mark. Streams can be made which read or write wth this encoding." }
+{ $see-also "encodings-introduction" } ;
+
+HELP: utf16
+{ $class-description "The encoding descriptor for UTF-16, that is, UTF-16 with a byte order mark. This is the most useful for general input and output in UTF-16. Streams can be made which read or write wth this encoding." }
+{ $see-also "encodings-introduction" } ;
+
+{ utf16 utf16le utf16be } related-words
diff --git a/core/io/encodings/utf16/utf16-tests.factor b/core/io/encodings/utf16/utf16-tests.factor
new file mode 100755 (executable)
index 0000000..0d171ee
--- /dev/null
@@ -0,0 +1,30 @@
+USING: kernel tools.test io.encodings.utf16 arrays sbufs
+io.streams.byte-array sequences io.encodings io unicode
+io.encodings.string alien.c-types alien.strings accessors classes ;
+IN: io.encodings.utf16.tests
+
+[ { CHAR: x } ] [ { 0 CHAR: x } utf16be decode >array ] unit-test
+[ { HEX: 1D11E } ] [ { HEX: D8 HEX: 34 HEX: DD HEX: 1E } utf16be decode >array ] unit-test
+[ { CHAR: replacement-character } ] [ { BIN: 11011111 CHAR: q } utf16be decode >array ] unit-test
+[ { CHAR: replacement-character } ] [ { BIN: 11011011 CHAR: x BIN: 11011011 CHAR: x } utf16be decode >array ] unit-test
+
+[ { 0 120 216 52 221 30 } ] [ { CHAR: x HEX: 1d11e } utf16be encode >array ] unit-test
+
+[ { CHAR: x } ] [ { CHAR: x 0 } utf16le decode >array ] unit-test
+[ { 119070 } ] [ { HEX: 34 HEX: D8 HEX: 1E HEX: DD } utf16le decode >array ] unit-test
+[ { CHAR: replacement-character } ] [ { 0 BIN: 11011111 } utf16le decode >array ] unit-test
+[ { CHAR: replacement-character } ] [ { 0 BIN: 11011011 0 0 } utf16le decode >array ] unit-test
+[ { 119070 } ] [ { HEX: 34 HEX: D8 HEX: 1E HEX: DD } utf16le decode >array ] unit-test
+
+[ { 120 0 52 216 30 221 } ] [ { CHAR: x HEX: 1d11e } utf16le encode >array ] unit-test
+
+[ { CHAR: x } ] [ { HEX: ff HEX: fe CHAR: x 0 } utf16 decode >array ] unit-test
+[ { CHAR: x } ] [ { HEX: fe HEX: ff 0 CHAR: x } utf16 decode >array ] unit-test
+
+[ { HEX: ff HEX: fe 120 0 52 216 30 221 } ] [ { CHAR: x HEX: 1d11e } utf16 encode >array ] unit-test
+
+: correct-endian
+    code>> class little-endian? [ utf16le = ] [ utf16be = ] if ;
+
+[ t ] [ B{ } utf16n <byte-reader> correct-endian ] unit-test
+[ t ] [ utf16n <byte-writer> correct-endian ] unit-test
diff --git a/core/io/encodings/utf16/utf16.factor b/core/io/encodings/utf16/utf16.factor
new file mode 100755 (executable)
index 0000000..9093132
--- /dev/null
@@ -0,0 +1,124 @@
+! Copyright (C) 2006, 2008 Daniel Ehrenberg.
+! See http://factorcode.org/license.txt for BSD license.
+USING: math kernel sequences sbufs vectors namespaces io.binary
+io.encodings combinators splitting io byte-arrays inspector ;
+IN: io.encodings.utf16
+
+TUPLE: utf16be ;
+
+TUPLE: utf16le ;
+
+TUPLE: utf16 ;
+
+<PRIVATE
+
+! UTF-16BE decoding
+
+: append-nums ( byte ch -- ch )
+    over [ 8 shift bitor ] [ 2drop replacement-char ] if ;
+
+: double-be ( stream byte -- stream char )
+    over stream-read1 swap append-nums ;
+
+: quad-be ( stream byte -- stream char )
+    double-be over stream-read1 [
+        dup -2 shift BIN: 110111 number= [
+            >r 2 shift r> BIN: 11 bitand bitor
+            over stream-read1 swap append-nums HEX: 10000 +
+        ] [ 2drop dup stream-read1 drop replacement-char ] if
+    ] when* ;
+
+: ignore ( stream -- stream char )
+    dup stream-read1 drop replacement-char ;
+
+: begin-utf16be ( stream byte -- stream char )
+    dup -3 shift BIN: 11011 number= [
+        dup BIN: 00000100 bitand zero?
+        [ BIN: 11 bitand quad-be ]
+        [ drop ignore ] if
+    ] [ double-be ] if ;
+    
+M: utf16be decode-char
+    drop dup stream-read1 dup [ begin-utf16be ] when nip ;
+
+! UTF-16LE decoding
+
+: quad-le ( stream ch -- stream char )
+    over stream-read1 swap 10 shift bitor
+    over stream-read1 dup -2 shift BIN: 110111 = [
+        BIN: 11 bitand append-nums HEX: 10000 +
+    ] [ 2drop replacement-char ] if ;
+
+: double-le ( stream byte1 byte2 -- stream char )
+    dup -3 shift BIN: 11011 = [
+        dup BIN: 100 bitand 0 number=
+        [ BIN: 11 bitand 8 shift bitor quad-le ]
+        [ 2drop replacement-char ] if
+    ] [ append-nums ] if ;
+
+: begin-utf16le ( stream byte -- stream char )
+    over stream-read1 [ double-le ] [ drop replacement-char ] if* ;
+
+M: utf16le decode-char
+    drop dup stream-read1 dup [ begin-utf16le ] when nip ;
+
+! UTF-16LE/BE encoding
+
+: encode-first ( char -- byte1 byte2 )
+    -10 shift
+    dup -8 shift BIN: 11011000 bitor
+    swap HEX: FF bitand ;
+
+: encode-second ( char -- byte3 byte4 )
+    BIN: 1111111111 bitand
+    dup -8 shift BIN: 11011100 bitor
+    swap BIN: 11111111 bitand ;
+
+: stream-write2 ( stream char1 char2 -- )
+    rot [ stream-write1 ] curry bi@ ;
+
+: char>utf16be ( stream char -- )
+    dup HEX: FFFF > [
+        HEX: 10000 -
+        2dup encode-first stream-write2
+        encode-second stream-write2
+    ] [ h>b/b swap stream-write2 ] if ;
+
+M: utf16be encode-char ( char stream encoding -- )
+    drop swap char>utf16be ;
+
+: char>utf16le ( char stream -- )
+    dup HEX: FFFF > [
+        HEX: 10000 -
+        2dup encode-first swap stream-write2
+        encode-second swap stream-write2
+    ] [ h>b/b stream-write2 ] if ; 
+
+M: utf16le encode-char ( char stream encoding -- )
+    drop swap char>utf16le ;
+
+! UTF-16
+
+: bom-le B{ HEX: ff HEX: fe } ; inline
+
+: bom-be B{ HEX: fe HEX: ff } ; inline
+
+: start-utf16le? ( seq1 -- seq2 ? ) bom-le ?head ;
+
+: start-utf16be? ( seq1 -- seq2 ? ) bom-be ?head ;
+
+TUPLE: missing-bom ;
+M: missing-bom summary drop "The BOM for a UTF-16 stream was missing" ;
+
+: bom>le/be ( bom -- le/be )
+    dup bom-le sequence= [ drop utf16le ] [
+        bom-be sequence= [ utf16be ] [ missing-bom ] if
+    ] if ;
+
+M: utf16 <decoder> ( stream utf16 -- decoder )
+    drop 2 over stream-read bom>le/be <decoder> ;
+
+M: utf16 <encoder> ( stream utf16 -- encoder )
+    drop bom-le over stream-write utf16le <encoder> ;
+
+PRIVATE>
diff --git a/core/io/streams/memory/memory.factor b/core/io/streams/memory/memory.factor
new file mode 100644 (file)
index 0000000..daadbb0
--- /dev/null
@@ -0,0 +1,13 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel accessors alien.accessors math io ;
+IN: io.streams.memory
+
+TUPLE: memory-stream alien index ;
+
+: <memory-stream> ( alien -- stream )
+    0 memory-stream boa ;
+
+M: memory-stream stream-read1
+    [ [ alien>> ] [ index>> ] bi alien-unsigned-1 ]
+    [ [ 1+ ] change-index drop ] bi ;
index eebc45511a098c5ea0e1ffe838cdf86f4e3d193c..fe8e5bddc8c4b049bbe93a19f4a35feb50341fca 100755 (executable)
@@ -184,3 +184,10 @@ unit-test
 [ HEX: 988a259c3433f237 ] [
     B{ HEX: 37 HEX: f2 HEX: 33 HEX: 34 HEX: 9c HEX: 25 HEX: 8a HEX: 98 } byte-array>bignum
 ] unit-test
+
+[ t ] [ 256 power-of-2? ] unit-test
+[ f ] [ 123 power-of-2? ] unit-test
+
+[ f ] [ -128 power-of-2? ] unit-test
+[ f ] [ 0 power-of-2? ] unit-test
+[ t ] [ 1 power-of-2? ] unit-test
index 4ca1a8637c2eb3fe33b60e9b4ad0106f42151819..77d60e67f8cfc07e012c0c2369e92da876d8db63 100755 (executable)
@@ -96,6 +96,8 @@ C: <interval> interval
 
 : interval-bitnot ( i1 -- i2 ) interval-neg interval-1- ;
 
+: interval-sq ( i1 -- i2 ) dup interval* ;
+
 : make-interval ( from to -- int )
     over first over first {
         { [ 2dup > ] [ 2drop 2drop f ] }
index 5533c0009001dd6276ead0576fee81e4719f51ec..c8a763b5f7b91dcb1d6b35ddc4fcb8305de89787 100755 (executable)
@@ -1,5 +1,5 @@
 USING: help.markup help.syntax kernel sequences quotations
-math.private math.functions ;
+math.private ;
 IN: math
 
 ARTICLE: "division-by-zero" "Division by zero"
@@ -26,17 +26,13 @@ $nl
 { $subsection < }
 { $subsection <= }
 { $subsection > }
-{ $subsection >= }
-"Inexact comparison:"
-{ $subsection ~ } ;
+{ $subsection >= } ;
 
 ARTICLE: "modular-arithmetic" "Modular arithmetic"
 { $subsection mod }
 { $subsection rem }
 { $subsection /mod }
 { $subsection /i }
-{ $subsection mod-inv }
-{ $subsection ^mod }
 { $see-also "integer-functions" } ;
 
 ARTICLE: "bitwise-arithmetic" "Bitwise arithmetic"
@@ -363,6 +359,10 @@ HELP: next-power-of-2
 { $values { "m" "a non-negative integer" } { "n" "an integer" } }
 { $description "Outputs the smallest power of 2 greater than " { $snippet "m" } ". The output value is always at least 1." } ;
 
+HELP: power-of-2?
+{ $values { "n" integer } { "?" "a boolean" } }
+{ $description "Tests if " { $snippet "n" } " is a power of 2." } ;
+
 HELP: each-integer
 { $values { "n" integer } { "quot" "a quotation with stack effect " { $snippet "( i -- )" } } }
 { $description "Applies the quotation to each integer from 0 up to " { $snippet "n" } ", excluding " { $snippet "n" } "." }
index 064b488ac30ed9df3d536059e881df0cdbfc0396..14cbe683519fe7566e5043114bb7d114d1bd3723 100755 (executable)
@@ -55,26 +55,26 @@ GENERIC: zero? ( x -- ? ) foldable
 
 M: object zero? drop f ;
 
-: 1+ ( x -- y ) 1 + ; foldable
-: 1- ( x -- y ) 1 - ; foldable
-: 2/ ( x -- y ) -1 shift ; foldable
-: sq ( x -- y ) dup * ; foldable
-: neg ( x -- -x ) 0 swap - ; foldable
-: recip ( x -- y ) 1 swap / ; foldable
+: 1+ ( x -- y ) 1 + ; inline
+: 1- ( x -- y ) 1 - ; inline
+: 2/ ( x -- y ) -1 shift ; inline
+: sq ( x -- y ) dup * ; inline
+: neg ( x -- -x ) 0 swap - ; inline
+: recip ( x -- y ) 1 swap / ; inline
 
 : ?1+ [ 1+ ] [ 0 ] if* ; inline
 
 : /f  ( x y -- z ) >r >float r> >float float/f ; inline
 
-: max ( x y -- z ) [ > ] most ; foldable
-: min ( x y -- z ) [ < ] most ; foldable
+: max ( x y -- z ) [ > ] most ; inline
+: min ( x y -- z ) [ < ] most ; inline
 
 : between? ( x y z -- ? )
     pick >= [ >= ] [ 2drop f ] if ; inline
 
 : rem ( x y -- z ) tuck mod over + swap mod ; foldable
 
-: sgn ( x -- n ) dup 0 < -1 0 ? swap 0 > 1 0 ? bitor ; foldable
+: sgn ( x -- n ) dup 0 < [ drop -1 ] [ 0 > 1 0 ? ] if ; inline
 
 : [-] ( x y -- z ) - 0 max ; inline
 
@@ -121,7 +121,11 @@ M: float fp-nan?
 
 : next-power-of-2 ( m -- n ) 2 swap (next-power-of-2) ; foldable
 
-: align ( m w -- n ) 1- [ + ] keep bitnot bitand ; inline
+: power-of-2? ( n -- ? )
+    dup 0 <= [ drop f ] [ dup 1- bitand zero? ] if ; foldable
+
+: align ( m w -- n )
+    1- [ + ] keep bitnot bitand ; inline
 
 <PRIVATE
 
index 3237f095bf3b3cbf5ae87be6c737a74d40ad741d..9630f9dc7047d22018655dd3677c0163a7e0a676 100755 (executable)
@@ -3,7 +3,7 @@
 USING: arrays generic assocs inference inference.class
 inference.dataflow inference.backend inference.state io kernel
 math namespaces sequences vectors words quotations hashtables
-combinators classes optimizer.def-use ;
+combinators classes optimizer.def-use accessors ;
 IN: optimizer.backend
 
 SYMBOL: class-substitutions
@@ -16,37 +16,32 @@ SYMBOL: optimizer-changed
 
 GENERIC: optimize-node* ( node -- node/t changed? )
 
-: ?union ( assoc/f assoc -- hash )
-    over [ assoc-union ] [ nip ] if ;
+: ?union ( assoc assoc/f -- assoc' )
+    dup assoc-empty? [ drop ] [ swap assoc-union ] if ;
 
-: add-node-literals ( assoc node -- )
-    over assoc-empty? [
-        2drop
-    ] [
-        [ node-literals ?union ] keep set-node-literals
-    ] if ;
+: add-node-literals ( node assoc -- )
+    [ ?union ] curry change-literals drop ;
 
-: add-node-classes ( assoc node -- )
-    over assoc-empty? [
-        2drop
-    ] [
-        [ node-classes ?union ] keep set-node-classes
-    ] if ;
+: add-node-classes ( node assoc -- )
+    [ ?union ] curry change-classes drop ;
 
-: substitute-values ( assoc node -- )
-    over assoc-empty? [
+: substitute-values ( node assoc -- )
+    dup assoc-empty? [
         2drop
     ] [
-        2dup node-in-d swap substitute-here
-        2dup node-in-r swap substitute-here
-        2dup node-out-d swap substitute-here
-        node-out-r swap substitute-here
+        {
+            [ >r  in-d>> r> substitute-here ]
+            [ >r  in-r>> r> substitute-here ]
+            [ >r out-d>> r> substitute-here ]
+            [ >r out-r>> r> substitute-here ]
+        } 2cleave
     ] if ;
 
 : perform-substitutions ( node -- )
-    class-substitutions get over add-node-classes
-    literal-substitutions get over add-node-literals
-    value-substitutions get swap substitute-values ;
+    [   class-substitutions get add-node-classes  ]
+    [ literal-substitutions get add-node-literals ]
+    [   value-substitutions get substitute-values ]
+    tri ;
 
 DEFER: optimize-nodes
 
@@ -90,18 +85,21 @@ M: node optimize-node* drop t f ;
     #! Not very efficient.
     dupd union* update ;
 
-: compute-value-substitutions ( #return/#values #call/#merge -- assoc )
-    node-out-d swap node-in-d 2array unify-lengths flip
+: compute-value-substitutions ( #call/#merge #return/#values -- assoc )
+    [ out-d>> ] [ in-d>> ] bi* 2array unify-lengths flip
     [ = not ] assoc-subset >hashtable ;
 
 : cleanup-inlining ( #return/#values -- newnode changed? )
-    dup node-successor dup [
-        class-substitutions get pick node-classes update
-        literal-substitutions get pick node-literals update
-        tuck compute-value-substitutions value-substitutions get swap update*
-        node-successor t
+    dup node-successor [
+        [ node-successor ] keep
+        {
+            [ nip classes>> class-substitutions get swap update ]
+            [ nip literals>> literal-substitutions get swap update ]
+            [ compute-value-substitutions value-substitutions get swap update* ]
+            [ drop node-successor ]
+        } 2cleave t
     ] [
-        2drop t f
+        drop t f
     ] if ;
 
 ! #return
diff --git a/core/optimizer/collect/collect.factor b/core/optimizer/collect/collect.factor
new file mode 100644 (file)
index 0000000..6b9aee4
--- /dev/null
@@ -0,0 +1,10 @@
+! Copyright (C) 2006, 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: inference.dataflow inference.backend kernel ;
+IN: optimizer
+
+: collect-label-infos ( node -- node )
+    dup [
+        dup #label? [ collect-label-info ] [ drop ] if
+    ] each-node ;
+
index ce77cdd43a77d8094263becf6ff4aa53c7fdb9b9..9c6d041bcace2e5e2e5989383783e5603a8faef5 100755 (executable)
@@ -27,22 +27,22 @@ optimizer ;
     dup [ 1+ loop-test-1 ] [ drop ] if ; inline
                           
 [ t ] [
-    [ loop-test-1 ] dataflow dup detect-loops
+    [ loop-test-1 ] dataflow detect-loops
     \ loop-test-1 label-is-loop?
 ] unit-test
 
 [ t ] [
-    [ loop-test-1 1 2 3 ] dataflow dup detect-loops
+    [ loop-test-1 1 2 3 ] dataflow detect-loops
     \ loop-test-1 label-is-loop?
 ] unit-test
 
 [ t ] [
-    [ [ loop-test-1 ] each ] dataflow dup detect-loops
+    [ [ loop-test-1 ] each ] dataflow detect-loops
     \ loop-test-1 label-is-loop?
 ] unit-test
 
 [ t ] [
-    [ [ loop-test-1 ] each ] dataflow dup detect-loops
+    [ [ loop-test-1 ] each ] dataflow detect-loops
     \ (each-integer) label-is-loop?
 ] unit-test
 
@@ -50,7 +50,7 @@ optimizer ;
     dup [ 1+ loop-test-2 1- ] [ drop ] if ; inline
 
 [ t ] [
-    [ loop-test-2 ] dataflow dup detect-loops
+    [ loop-test-2 ] dataflow detect-loops
     \ loop-test-2 label-is-not-loop?
 ] unit-test
 
@@ -58,7 +58,7 @@ optimizer ;
     dup [ [ loop-test-3 ] each ] [ drop ] if ; inline
 
 [ t ] [
-    [ loop-test-3 ] dataflow dup detect-loops
+    [ loop-test-3 ] dataflow detect-loops
     \ loop-test-3 label-is-not-loop?
 ] unit-test
 
@@ -73,7 +73,7 @@ optimizer ;
     dup #label? [ node-successor find-label ] unless ;
 
 : test-loop-exits
-    dataflow dup detect-loops find-label
+    dataflow detect-loops find-label
     dup node-param swap
     [ node-child find-tail find-loop-exits [ class ] map ] keep
     #label-loop? ;
@@ -113,7 +113,7 @@ optimizer ;
 ] unit-test
 
 [ f ] [
-    [ [ [ ] map ] map ] dataflow dup detect-loops
+    [ [ [ ] map ] map ] dataflow detect-loops
     [ dup #label? swap #loop? not and ] node-exists?
 ] unit-test
 
@@ -128,22 +128,22 @@ DEFER: a
     blah [ b ] [ a ] if ; inline
 
 [ t ] [
-    [ a ] dataflow dup detect-loops
+    [ a ] dataflow detect-loops
     \ a label-is-loop?
 ] unit-test
 
 [ t ] [
-    [ a ] dataflow dup detect-loops
+    [ a ] dataflow detect-loops
     \ b label-is-loop?
 ] unit-test
 
 [ t ] [
-    [ b ] dataflow dup detect-loops
+    [ b ] dataflow detect-loops
     \ a label-is-loop?
 ] unit-test
 
 [ t ] [
-    [ a ] dataflow dup detect-loops
+    [ a ] dataflow detect-loops
     \ b label-is-loop?
 ] unit-test
 
@@ -156,12 +156,12 @@ DEFER: a'
     blah [ b' ] [ a' ] if ; inline
 
 [ f ] [
-    [ a' ] dataflow dup detect-loops
+    [ a' ] dataflow detect-loops
     \ a' label-is-loop?
 ] unit-test
 
 [ f ] [
-    [ b' ] dataflow dup detect-loops
+    [ b' ] dataflow detect-loops
     \ b' label-is-loop?
 ] unit-test
 
@@ -171,11 +171,11 @@ DEFER: a'
 ! a standard iterative dataflow problem after all -- so I'm
 ! tempted to believe the computer here
 [ t ] [
-    [ b' ] dataflow dup detect-loops
+    [ b' ] dataflow detect-loops
     \ a' label-is-loop?
 ] unit-test
 
 [ f ] [
-    [ a' ] dataflow dup detect-loops
+    [ a' ] dataflow detect-loops
     \ b' label-is-loop?
 ] unit-test
index f9f8901c41f6673b2d953939ed2efbb2dd9c6e9f..976156db7713cfec3255824b7df2f53f7c7b33fa 100755 (executable)
@@ -109,8 +109,9 @@ SYMBOL: potential-loops
         ] [ 2drop ] if
     ] assoc-each [ remove-non-loop-calls ] when ;
 
-: detect-loops ( nodes -- )
+: detect-loops ( node -- node )
     [
+        dup
         collect-label-info
         remove-non-tail-calls
         remove-non-loop-calls
index f22cce9fa87dcf46dbbbc3c96434dad6e72103ae..914018437ab406cda0773e1557470435d6d1f1c9 100755 (executable)
@@ -3,12 +3,12 @@ USING: inference inference.dataflow optimizer optimizer.def-use
 namespaces assocs kernel sequences math tools.test words ;
 
 [ 3 { 1 1 1 } ] [
-    [ 1 2 3 ] dataflow compute-def-use
+    [ 1 2 3 ] dataflow compute-def-use drop
     def-use get values dup length swap [ length ] map
 ] unit-test
 
 : kill-set ( quot -- seq )
-    dataflow compute-def-use compute-dead-literals keys
+    dataflow compute-def-use drop compute-dead-literals keys
     [ value-literal ] map ;
 
 : subset? [ member? ] curry all? ;
index 54fca38ee22bbbb8b25a008fe589ab8ffd8bb8f0..66bffd9767885f152a717870b9f2dc677c159492 100755 (executable)
@@ -1,8 +1,9 @@
-! Copyright (C) 2004, 2007 Slava Pestov.
+! Copyright (C) 2004, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-IN: optimizer.def-use
 USING: namespaces assocs sequences inference.dataflow
-inference.backend kernel generic assocs classes vectors ;
+inference.backend kernel generic assocs classes vectors
+accessors combinators ;
+IN: optimizer.def-use
 
 SYMBOL: def-use
 
@@ -21,17 +22,20 @@ SYMBOL: def-use
 
 GENERIC: node-def-use ( node -- )
 
-: compute-def-use ( node -- )
-    H{ } clone def-use set [ node-def-use ] each-node ;
+: compute-def-use ( node -- node )
+    H{ } clone def-use set
+    dup [ node-def-use ] each-node ;
 
 : nest-def-use ( node -- def-use )
-    [ compute-def-use def-use get ] with-scope ;
+    [ compute-def-use drop def-use get ] with-scope ;
 
 : (node-def-use) ( node -- )
-    dup dup node-in-d uses-values
-    dup dup node-in-r uses-values
-    dup node-out-d defs-values
-    node-out-r defs-values ;
+    {
+        [ dup in-d>> uses-values ] 
+        [ dup in-r>> uses-values ] 
+        [ out-d>>    defs-values ] 
+        [ out-r>>    defs-values ]
+    } cleave ;
 
 M: object node-def-use (node-def-use) ;
 
@@ -43,7 +47,7 @@ M: #passthru node-def-use drop ;
 
 M: #return node-def-use
     #! Values returned by local labels can be killed.
-    dup node-param [ drop ] [ (node-def-use) ] if ;
+    dup param>> [ drop ] [ (node-def-use) ] if ;
 
 ! nodes that don't use their values directly
 UNION: #killable
@@ -56,13 +60,13 @@ UNION: #killable
 
 M: #label node-def-use
     [
-        dup node-in-d ,
-        dup node-child node-out-d ,
-        dup collect-recursion [ node-in-d , ] each
+        dup in-d>> ,
+        dup node-child out-d>> ,
+        dup calls>> [ in-d>> , ] each
     ] { } make purge-invariants uses-values ;
 
 : branch-def-use ( #branch -- )
-    active-children [ node-in-d ] map
+    active-children [ in-d>> ] map
     purge-invariants t swap uses-values ;
 
 M: #branch node-def-use
@@ -85,16 +89,16 @@ M: node kill-node* drop t ;
     inline
 
 M: #shuffle kill-node* 
-    [
-        dup node-in-d empty? swap node-out-d empty? and
-    ] prune-if ;
+    [ [ in-d>> empty? ] [ out-d>> empty? ] bi and ] prune-if ;
 
 M: #push kill-node* 
-    [ node-out-d empty? ] prune-if ;
+    [ out-d>> empty? ] prune-if ;
 
-M: #>r kill-node* [ node-in-d empty? ] prune-if ;
+M: #>r kill-node*
+    [ in-d>> empty? ] prune-if ;
 
-M: #r> kill-node* [ node-in-r empty? ] prune-if ;
+M: #r> kill-node*
+    [ in-r>> empty? ] prune-if ;
 
 : kill-node ( node -- node )
     dup [
@@ -116,7 +120,7 @@ M: #r> kill-node* [ node-in-r empty? ] prune-if ;
     ] if ;
 
 : sole-consumer ( #call -- node/f )
-    node-out-d first used-by
+    out-d>> first used-by
     dup length 1 = [ first ] [ drop f ] if ;
 
 : splice-def-use ( node -- )
@@ -128,5 +132,5 @@ M: #r> kill-node* [ node-in-r empty? ] prune-if ;
     #! degree of accuracy; the new values should be marked as
     #! having _some_ usage, so that flushing doesn't erronously
     #! flush them away.
-    [ compute-def-use def-use get keys ] with-scope
+    nest-def-use keys
     def-use get [ [ t swap ?push ] change-at ] curry each ;
diff --git a/core/optimizer/inlining/inlining-tests.factor b/core/optimizer/inlining/inlining-tests.factor
new file mode 100644 (file)
index 0000000..608054b
--- /dev/null
@@ -0,0 +1,10 @@
+IN: optimizer.inlining.tests
+USING: tools.test optimizer.inlining ;
+
+\ word-flat-length must-infer
+
+\ inlining-math-method must-infer
+
+\ optimistic-inline? must-infer
+
+\ find-identity must-infer
index 8447d1be5fe0bc1126ddbbaf8f30d870ba8847e5..33c8244b4c0d68bb36eb9bd27e368e3a81e3626d 100755 (executable)
@@ -3,10 +3,11 @@
 USING: arrays generic assocs inference inference.class
 inference.dataflow inference.backend inference.state io kernel
 math namespaces sequences vectors words quotations hashtables
-combinators classes classes.algebra generic.math continuations
-optimizer.def-use optimizer.backend generic.standard
-optimizer.specializers optimizer.def-use optimizer.pattern-match
-generic.standard optimizer.control kernel.private ;
+combinators classes classes.algebra generic.math
+optimizer.math.partial continuations optimizer.def-use
+optimizer.backend generic.standard optimizer.specializers
+optimizer.def-use optimizer.pattern-match generic.standard
+optimizer.control kernel.private ;
 IN: optimizer.inlining
 
 : remember-inlining ( node history -- )
@@ -53,8 +54,6 @@ DEFER: (flat-length)
     [ word-def (flat-length) ] with-scope ;
 
 ! Single dispatch method inlining optimization
-: specific-method ( class word -- class ) order min-class ;
-
 : node-class# ( node n -- class )
     over node-in-d <reversed> ?nth node-class ;
 
@@ -72,6 +71,7 @@ DEFER: (flat-length)
 ! Partial dispatch of math-generic words
 : normalize-math-class ( class -- class' )
     {
+        null
         fixnum bignum integer
         ratio rational
         float real
@@ -79,21 +79,31 @@ DEFER: (flat-length)
         object
     } [ class< ] with find nip ;
 
-: math-both-known? ( word left right -- ? )
-    math-class-max swap specific-method ;
-
-: inline-math-method ( #call word -- node )
-    over node-input-classes
+: inlining-math-method ( #call word -- quot/f )
+    swap node-input-classes
     [ first normalize-math-class ]
     [ second normalize-math-class ] bi
-    3dup math-both-known?
-    [ math-method f splice-quot ]
-    [ 2drop 2drop t ] if ;
+    3dup math-both-known? [ math-method* ] [ 3drop f ] if ;
+
+: inline-math-method ( #call word -- node/t )
+    [ drop ] [ inlining-math-method ] 2bi
+    dup [ f splice-quot ] [ 2drop t ] if ;
+
+: inline-math-partial ( #call word -- node/t )
+    [ drop ]
+    [
+        "derived-from" word-prop first
+        inlining-math-method dup
+    ]
+    [ nip 1quotation ] 2tri
+    [ = not ] [ drop ] 2bi and
+    [ f splice-quot ] [ 2drop t ] if ;
 
 : inline-method ( #call -- node )
     dup node-param {
         { [ dup standard-generic? ] [ inline-standard-method ] }
         { [ dup math-generic? ] [ inline-math-method ] }
+        { [ dup math-partial? ] [ inline-math-partial ] }
         [ 2drop t ]
     } cond ;
 
@@ -183,7 +193,7 @@ DEFER: (flat-length)
     nip dup [ second ] when ;
 
 : apply-identities ( node -- node/f )
-    dup find-identity dup [ f splice-quot ] [ 2drop f ] if ;
+    dup find-identity f splice-quot ;
 
 : optimistic-inline? ( #call -- ? )
     dup node-param "specializer" word-prop dup [
index cf71af216ef2633728c979d1b739a3919bc4657d..6e1aacff4495b6d6157a87edc80200d5570e491f 100755 (executable)
@@ -60,7 +60,8 @@ sequences.private combinators ;
     [ value-literal sequence? ] [ drop f ] if ;
 
 : member-quot ( seq -- newquot )
-    [ [ t ] ] { } map>assoc [ drop f ] suffix [ nip case ] curry ;
+    [ literalize [ t ] ] { } map>assoc
+    [ drop f ] suffix [ nip case ] curry ;
 
 : expand-member ( #call -- )
     dup node-in-d peek value-literal member-quot f splice-quot ;
@@ -83,21 +84,11 @@ sequences.private combinators ;
 ] "constraints" set-word-prop
 
 ! eq? on the same object is always t
-{ eq? bignum= float= number= = } {
+{ eq? = } {
     { { @ @ } [ 2drop t ] }
 } define-identities
 
 ! Specializers
-{ 1+ 1- sq neg recip sgn } [
-    { number } "specializer" set-word-prop
-] each
-
-\ 2/ { fixnum } "specializer" set-word-prop
-
-{ min max } [
-    { number number } "specializer" set-word-prop
-] each
-
 { first first2 first3 first4 }
 [ { array } "specializer" set-word-prop ] each
 
index 4ec4bfeb360f56947e3f806e3e149a5a5e83dfa5..ab8a1f3edade40a745034710709b85240ba36925 100755 (executable)
@@ -8,103 +8,104 @@ namespaces assocs quotations math.intervals sequences.private
 combinators splitting layouts math.parser classes
 classes.algebra generic.math optimizer.pattern-match
 optimizer.backend optimizer.def-use optimizer.inlining
-generic.standard system ;
+optimizer.math.partial generic.standard system accessors ;
 
-{ + bignum+ float+ fixnum+fast } {
-    { { number 0 } [ drop ] }
-    { { 0 number } [ nip ] }
-} define-identities
+: define-math-identities ( word identities -- )
+    >r all-derived-ops r> define-identities ;
+
+\ number= {
+    { { @ @ } [ 2drop t ] }
+} define-math-identities
 
-{ fixnum+ } {
+\ + {
     { { number 0 } [ drop ] }
     { { 0 number } [ nip ] }
-} define-identities
+} define-math-identities
 
-{ - fixnum- bignum- float- fixnum-fast } {
+\ - {
     { { number 0 } [ drop ] }
     { { @ @ } [ 2drop 0 ] }
-} define-identities
+} define-math-identities
 
-{ < fixnum< bignum< float< } {
+\ < {
     { { @ @ } [ 2drop f ] }
-} define-identities
+} define-math-identities
 
-{ <= fixnum<= bignum<= float<= } {
+\ <= {
     { { @ @ } [ 2drop t ] }
-} define-identities
+} define-math-identities
 
-{ > fixnum> bignum> float>= } {
+\ > {
     { { @ @ } [ 2drop f ] }
-} define-identities
+} define-math-identities
 
-{ >= fixnum>= bignum>= float>= } {
+\ >= {
     { { @ @ } [ 2drop t ] }
-} define-identities
+} define-math-identities
 
-{ * fixnum* bignum* float* } {
+\ * {
     { { number 1 } [ drop ] }
     { { 1 number } [ nip ] }
     { { number 0 } [ nip ] }
     { { 0 number } [ drop ] }
     { { number -1 } [ drop 0 swap - ] }
     { { -1 number } [ nip 0 swap - ] }
-} define-identities
+} define-math-identities
 
-{ / fixnum/i bignum/i float/f } {
+\ / {
     { { number 1 } [ drop ] }
     { { number -1 } [ drop 0 swap - ] }
-} define-identities
+} define-math-identities
 
-{ fixnum-mod bignum-mod } {
-    { { number 1 } [ 2drop 0 ] }
-} define-identities
+\ mod {
+    { { integer 1 } [ 2drop 0 ] }
+} define-math-identities
 
-{ bitand fixnum-bitand bignum-bitand } {
+\ rem {
+    { { integer 1 } [ 2drop 0 ] }
+} define-math-identities
+
+\ bitand {
     { { number -1 } [ drop ] }
     { { -1 number } [ nip ] }
     { { @ @ } [ drop ] }
     { { number 0 } [ nip ] }
     { { 0 number } [ drop ] }
-} define-identities
+} define-math-identities
 
-{ bitor fixnum-bitor bignum-bitor } {
+\ bitor {
     { { number 0 } [ drop ] }
     { { 0 number } [ nip ] }
     { { @ @ } [ drop ] }
     { { number -1 } [ nip ] }
     { { -1 number } [ drop ] }
-} define-identities
+} define-math-identities
 
-{ bitxor fixnum-bitxor bignum-bitxor } {
+\ bitxor {
     { { number 0 } [ drop ] }
     { { 0 number } [ nip ] }
     { { number -1 } [ drop bitnot ] }
     { { -1 number } [ nip bitnot ] }
     { { @ @ } [ 2drop 0 ] }
-} define-identities
+} define-math-identities
 
-{ shift fixnum-shift fixnum-shift-fast bignum-shift } {
+\ shift {
     { { 0 number } [ drop ] }
     { { number 0 } [ drop ] }
-} define-identities
+} define-math-identities
 
 : math-closure ( class -- newclass )
-    { fixnum integer rational real }
+    { null fixnum bignum integer rational float real number }
     [ class< ] with find nip number or ;
 
 : fits? ( interval class -- ? )
     "interval" word-prop dup
     [ interval-subset? ] [ 2drop t ] if ;
 
-: math-output-class ( node min -- newclass )
-    #! if min is f, it means we just want to use the declared
-    #! output class from the "infer-effect".
-    dup [
-        swap node-in-d
-        [ value-class* math-closure math-class-max ] each
-    ] [
-        2drop f
-    ] if ;
+: math-output-class ( node upgrades -- newclass )
+    >r
+    in-d>> null [ value-class* math-closure math-class-max ] reduce
+    dup r> at swap or ;
 
 : won't-overflow? ( interval node -- ? )
     node-in-d [ value-class* fixnum class< ] all?
@@ -123,28 +124,18 @@ generic.standard system ;
         2drop f
     ] if ; inline
 
-: math-output-class/interval-1 ( node min word -- classes intervals )
-    pick >r
-    >r over r>
-    math-output-interval-1
-    >r math-output-class r>
-    r> post-process ; inline
+: math-output-class/interval-1 ( node word -- classes intervals )
+    [ drop { } math-output-class 1array ]
+    [ math-output-interval-1 1array ] 2bi ;
 
 {
-    { 1+ integer interval-1+ }
-    { 1- integer interval-1- }
-    { neg integer interval-neg }
-    { shift integer interval-recip }
-    { bitnot fixnum interval-bitnot }
-    { fixnum-bitnot f interval-bitnot }
-    { bignum-bitnot f interval-bitnot }
-    { 2/ fixnum interval-2/ }
-    { sq integer f }
+    { bitnot interval-bitnot }
+    { fixnum-bitnot interval-bitnot }
+    { bignum-bitnot interval-bitnot }
 } [
-    first3 [
-        math-output-class/interval-1
-    ] 2curry "output-classes" set-word-prop
-] each
+    [ math-output-class/interval-1 ] curry
+    "output-classes" set-word-prop
+] assoc-each
 
 : intervals ( node -- i1 i2 )
     node-in-d first2 [ value-interval* ] bi@ ;
@@ -156,7 +147,7 @@ generic.standard system ;
         2drop f
     ] if ; inline
 
-: math-output-class/interval-2 ( node min word -- classes intervals )
+: math-output-class/interval-2 ( node upgrades word -- classes intervals )
     pick >r
     >r over r>
     math-output-interval-2
@@ -164,47 +155,18 @@ generic.standard system ;
     r> post-process ; inline
 
 {
-    { + integer interval+ }
-    { - integer interval- }
-    { * integer interval* }
-    { / rational interval/ }
-    { /i integer interval/i }
-
-    { fixnum+ f interval+ }
-    { fixnum+fast f interval+ }
-    { fixnum- f interval- }
-    { fixnum-fast f interval- }
-    { fixnum* f interval* }
-    { fixnum*fast f interval* }
-    { fixnum/i f interval/i }
-
-    { bignum+ f interval+ }
-    { bignum- f interval- }
-    { bignum* f interval* }
-    { bignum/i f interval/i }
-    { bignum-shift f interval-shift-safe }
-
-    { float+ f interval+ }
-    { float- f interval- }
-    { float* f interval* }
-    { float/f f interval/ }
-
-    { min fixnum interval-min }
-    { max fixnum interval-max }
+    { + { { fixnum integer } } interval+ }
+    { - { { fixnum integer } } interval- }
+    { * { { fixnum integer } } interval* }
+    { / { { fixnum rational } { integer rational } } interval/ }
+    { /i { { fixnum integer } } interval/i }
+    { shift { { fixnum integer } } interval-shift-safe }
 } [
     first3 [
-        math-output-class/interval-2
-    ] 2curry "output-classes" set-word-prop
-] each
-
-{ fixnum-shift fixnum-shift-fast shift } [
-    [
-        dup
-        node-in-d second value-interval*
-        -1./0. 0 [a,b] interval-subset? fixnum integer ?
-        \ interval-shift-safe
-        math-output-class/interval-2
-    ] "output-classes" set-word-prop
+        [
+            math-output-class/interval-2
+        ] 2curry "output-classes" set-word-prop
+    ] 2curry each-derived-op
 ] each
 
 : real-value? ( value -- n ? )
@@ -235,22 +197,18 @@ generic.standard system ;
     r> post-process ; inline
 
 {
-    { mod fixnum mod-range }
-    { fixnum-mod f mod-range }
-    { bignum-mod f mod-range }
-    { float-mod f mod-range }
-
-    { rem integer rem-range }
+    { mod { } mod-range }
+    { rem { { fixnum integer } } rem-range }
 
-    { bitand fixnum bitand-range }
-    { fixnum-bitand f bitand-range }
-
-    { bitor fixnum f }
-    { bitxor fixnum f }
+    { bitand { } bitand-range }
+    { bitor { } f }
+    { bitxor { } f }
 } [
     first3 [
-        math-output-class/interval-special
-    ] 2curry "output-classes" set-word-prop
+        [
+            math-output-class/interval-special
+        ] 2curry "output-classes" set-word-prop
+    ] 2curry each-derived-op
 ] each
 
 : twiddle-interval ( i1 -- i2 )
@@ -280,26 +238,12 @@ generic.standard system ;
     { <= assume<= assume> }
     { > assume> assume<= }
     { >= assume>= assume< }
-
-    { fixnum< assume< assume>= }
-    { fixnum<= assume<= assume> }
-    { fixnum> assume> assume<= }
-    { fixnum>= assume>= assume< }
-
-    { bignum< assume< assume>= }
-    { bignum<= assume<= assume> }
-    { bignum> assume> assume<= }
-    { bignum>= assume>= assume< }
-
-    { float< assume< assume>= }
-    { float<= assume<= assume> }
-    { float> assume> assume<= }
-    { float>= assume>= assume< }
 } [
-    first3
-    [
-        [ comparison-constraints ] with-scope
-    ] 2curry "constraints" set-word-prop
+    first3 [
+        [
+            [ comparison-constraints ] with-scope
+        ] 2curry "constraints" set-word-prop
+    ] 2curry each-derived-op
 ] each
 
 {
@@ -348,22 +292,20 @@ most-negative-fixnum most-positive-fixnum [a,b]
 
 ! Removing overflow checks
 : remove-overflow-check? ( #call -- ? )
-    dup node-out-d first node-class fixnum class< ;
+    dup out-d>> first node-class
+    [ fixnum class< ] [ null eq? not ] bi and ;
 
 {
     { + [ fixnum+fast ] }
+    { +-integer-fixnum [ fixnum+fast ] }
     { - [ fixnum-fast ] }
     { * [ fixnum*fast ] }
+    { *-integer-fixnum [ fixnum*fast ] }
+    { shift [ fixnum-shift-fast ] }
     { fixnum+ [ fixnum+fast ] }
     { fixnum- [ fixnum-fast ] }
     { fixnum* [ fixnum*fast ] }
-    ! these are here as an optimization. if they weren't given
-    ! explicitly, the same would be inferred after an extra
-    ! optimization step (see optimistic-inline?)
-    { 1+ [ 1 fixnum+fast ] }
-    { 1- [ 1 fixnum-fast ] }
-    { 2/ [ -1 fixnum-shift ] }
-    { neg [ 0 swap fixnum-fast ] }
+    { fixnum-shift [ fixnum-shift-fast ] }
 } [
     [
         [ dup remove-overflow-check? ] ,
@@ -397,26 +339,13 @@ most-negative-fixnum most-positive-fixnum [a,b]
     { <= interval<= }
     { > interval> }
     { >= interval>= }
-
-    { fixnum< interval< }
-    { fixnum<= interval<= }
-    { fixnum> interval> }
-    { fixnum>= interval>= }
-
-    { bignum< interval< }
-    { bignum<= interval<= }
-    { bignum> interval> }
-    { bignum>= interval>= }
-
-    { float< interval< }
-    { float<= interval<= }
-    { float> interval> }
-    { float>= interval>= }
 } [
     [
-        dup [ dupd foldable-comparison? ] curry ,
-        [ fold-comparison ] curry ,
-    ] { } make 1array define-optimizers
+        [
+            dup [ dupd foldable-comparison? ] curry ,
+            [ fold-comparison ] curry ,
+        ] { } make 1array define-optimizers
+    ] curry each-derived-op
 ] assoc-each
 
 ! The following words are handled in a similar way except if
@@ -426,44 +355,68 @@ most-negative-fixnum most-positive-fixnum [a,b]
     swap sole-consumer
     dup #call? [ node-param eq? ] [ 2drop f ] if ;
 
-: coereced-to-fixnum? ( #call -- ? )
-    \ >fixnum consumed-by? ;
+: coerced-to-fixnum? ( #call -- ? )
+    dup dup node-in-d [ node-class integer class< ] with all?
+    [ \ >fixnum consumed-by? ] [ drop f ] if ;
 
 {
-    { fixnum+ [ fixnum+fast ] }
-    { fixnum- [ fixnum-fast ] }
-    { fixnum* [ fixnum*fast ] }
+    { + [ [ >fixnum ] bi@ fixnum+fast ] }
+    { - [ [ >fixnum ] bi@ fixnum-fast ] }
+    { * [ [ >fixnum ] bi@ fixnum*fast ] }
 } [
-    [
+    >r derived-ops r> [
         [
-            dup remove-overflow-check?
-            over coereced-to-fixnum? or
-        ] ,
-        [ f splice-quot ] curry ,
-    ] { } make 1array define-optimizers
+            [
+                dup remove-overflow-check?
+                over coerced-to-fixnum? or
+            ] ,
+            [ f splice-quot ] curry ,
+        ] { } make 1array define-optimizers
+    ] curry each
 ] assoc-each
 
-: fixnum-shift-fast-pos? ( node -- ? )
-    #! Shifting 1 to the left won't overflow if the shift
-    #! count is small enough
-    dup dup node-in-d first node-literal 1 = [
-        dup node-in-d second node-interval
-        0 cell-bits tag-bits get - 2 - [a,b] interval-subset?
-    ] [ drop f ] if ;
-
-: fixnum-shift-fast-neg? ( node -- ? )
-    #! Shifting any number to the right won't overflow if the
-    #! shift count is small enough
-    dup node-in-d second node-interval
-    cell-bits 1- neg 0 [a,b] interval-subset? ;
-
-: fixnum-shift-fast? ( node -- ? )
-    dup fixnum-shift-fast-pos?
-    [ drop t ] [ fixnum-shift-fast-neg? ] if ;
-
-\ fixnum-shift {
+: convert-rem-to-and? ( #call -- ? )
+    dup node-in-d {
+        { [ 2dup first node-class integer class< not ] [ f ] }
+        { [ 2dup second node-literal integer? not ] [ f ] }
+        { [ 2dup second node-literal power-of-2? not ] [ f ] }
+        [ t ]
+    } cond 2nip ;
+
+: convert-mod-to-and? ( #call -- ? )
+    dup dup node-in-d first node-interval 0 [a,inf] interval-subset?
+    [ convert-rem-to-and? ] [ drop f ] if ;
+
+: convert-mod-to-and ( #call -- node )
+    dup
+    dup node-in-d second node-literal 1-
+    [ nip bitand ] curry f splice-quot ;
+
+\ mod [
+    {
+        {
+            [ dup convert-mod-to-and? ]
+            [ convert-mod-to-and ]
+        }
+    } define-optimizers
+] each-derived-op
+
+\ rem {
+    {
+        [ dup convert-rem-to-and? ]
+        [ convert-mod-to-and ]
+    }
+} define-optimizers
+
+: fixnumify-bitand? ( #call -- ? )
+    dup node-in-d second node-interval fixnum fits? ;
+
+: fixnumify-bitand ( #call -- node )
+    [ [ >fixnum ] bi@ fixnum-bitand ] f splice-quot ;
+
+\ bitand {
     {
-        [ dup fixnum-shift-fast? ]
-        [ [ fixnum-shift-fast ] f splice-quot ]
+        [ dup fixnumify-bitand? ]
+        [ fixnumify-bitand ]
     }
 } define-optimizers
diff --git a/core/optimizer/math/partial/partial-tests.factor b/core/optimizer/math/partial/partial-tests.factor
new file mode 100644 (file)
index 0000000..671933b
--- /dev/null
@@ -0,0 +1,13 @@
+IN: optimizer.math.partial.tests
+USING: optimizer.math.partial tools.test math kernel
+sequences ;
+
+[ t ] [ \ + integer fixnum math-both-known? ] unit-test
+[ t ] [ \ + bignum fixnum math-both-known? ] unit-test
+[ t ] [ \ + integer bignum math-both-known? ] unit-test
+[ t ] [ \ + float fixnum math-both-known? ] unit-test
+[ f ] [ \ + real fixnum math-both-known? ] unit-test
+[ f ] [ \ + object number math-both-known? ] unit-test
+[ f ] [ \ number= fixnum object math-both-known? ] unit-test
+[ t ] [ \ number= integer fixnum math-both-known? ] unit-test
+[ f ] [ \ >fixnum \ shift derived-ops memq? ] unit-test
diff --git a/core/optimizer/math/partial/partial.factor b/core/optimizer/math/partial/partial.factor
new file mode 100644 (file)
index 0000000..bbe1d0a
--- /dev/null
@@ -0,0 +1,172 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel kernel.private math math.private words
+sequences parser namespaces assocs quotations arrays
+generic generic.math hashtables effects ;
+IN: optimizer.math.partial
+
+! Partial dispatch.
+
+! This code will be overhauled and generalized when
+! multi-methods go into the core.
+PREDICATE: math-partial < word
+    "derived-from" word-prop >boolean ;
+
+: fixnum-integer-op ( a b fix-word big-word -- c )
+    pick tag 0 eq? [
+        drop execute
+    ] [
+        >r drop >r fixnum>bignum r> r> execute
+    ] if ; inline
+
+: integer-fixnum-op ( a b fix-word big-word -- c )
+    >r pick tag 0 eq? [
+        r> drop execute
+    ] [
+        drop fixnum>bignum r> execute
+    ] if ; inline
+
+: integer-integer-op ( a b fix-word big-word -- c )
+    pick tag 0 eq? [
+        integer-fixnum-op
+    ] [
+        >r drop over tag 0 eq? [
+            >r fixnum>bignum r> r> execute
+        ] [
+            r> execute
+        ] if
+    ] if ; inline
+
+<<
+: integer-op-combinator ( triple -- word )
+    [
+        [ second word-name % "-" % ]
+        [ third word-name % "-op" % ]
+        bi
+    ] "" make in get lookup ;
+
+: integer-op-word ( triple fix-word big-word -- word )
+    [
+        drop
+        word-name "fast" tail? >r
+        [ "-" % ] [ word-name % ] interleave
+        r> [ "-fast" % ] when
+    ] "" make in get create ;
+
+: integer-op-quot ( word fix-word big-word -- quot )
+    rot integer-op-combinator 1quotation 2curry ;
+
+: define-integer-op-word ( word fix-word big-word -- )
+    [
+        [ integer-op-word ] [ integer-op-quot ] 3bi
+        2 1 <effect> define-declared
+    ]
+    [
+        [ integer-op-word ] [ 2drop ] 3bi
+        "derived-from" set-word-prop
+    ] 3bi ;
+
+: define-integer-op-words ( words fix-word big-word -- )
+    [ define-integer-op-word ] 2curry each ;
+
+: integer-op-triples ( word -- triples )
+    {
+        { fixnum integer }
+        { integer fixnum }
+        { integer integer }
+    } swap [ prefix ] curry map ;
+
+: define-integer-ops ( word fix-word big-word -- )
+    >r >r integer-op-triples r> r>
+    [ define-integer-op-words ]
+    [ [ 2drop ] [ [ integer-op-word ] 2curry map ] 3bi zip % ]
+    3bi ;
+
+: define-math-ops ( op -- )
+    { fixnum bignum float }
+    [ [ dup 3array ] [ swap method ] 2bi ] with { } map>assoc
+    [ nip ] assoc-subset
+    [ word-def peek ] assoc-map % ;
+
+SYMBOL: math-ops
+
+[
+    \ +       define-math-ops
+    \ -       define-math-ops
+    \ *       define-math-ops
+    \ shift   define-math-ops
+    \ mod     define-math-ops
+    \ /i      define-math-ops
+
+    \ bitand  define-math-ops
+    \ bitor   define-math-ops
+    \ bitxor  define-math-ops
+
+    \ <       define-math-ops
+    \ <=      define-math-ops
+    \ >       define-math-ops
+    \ >=      define-math-ops
+    \ number= define-math-ops
+
+    \ + \ fixnum+ \ bignum+ define-integer-ops
+    \ - \ fixnum- \ bignum- define-integer-ops
+    \ * \ fixnum* \ bignum* define-integer-ops
+    \ shift \ fixnum-shift \ bignum-shift define-integer-ops
+    \ mod \ fixnum-mod \ bignum-mod define-integer-ops
+    \ /i \ fixnum/i \ bignum/i define-integer-ops
+    
+    \ bitand \ fixnum-bitand \ bignum-bitand define-integer-ops
+    \ bitor \ fixnum-bitor \ bignum-bitor define-integer-ops
+    \ bitxor \ fixnum-bitxor \ bignum-bitxor define-integer-ops
+    
+    \ < \ fixnum< \ bignum< define-integer-ops
+    \ <= \ fixnum<= \ bignum<= define-integer-ops
+    \ > \ fixnum> \ bignum> define-integer-ops
+    \ >= \ fixnum>= \ bignum>= define-integer-ops
+    \ number= \ eq? \ bignum= define-integer-ops
+] { } make >hashtable math-ops set-global
+
+SYMBOL: fast-math-ops
+
+[
+    { { + fixnum fixnum } fixnum+fast } ,
+    { { - fixnum fixnum } fixnum-fast } ,
+    { { * fixnum fixnum } fixnum*fast } ,
+    { { shift fixnum fixnum } fixnum-shift-fast } ,
+
+    \ + \ fixnum+fast \ bignum+ define-integer-ops
+    \ - \ fixnum-fast \ bignum- define-integer-ops
+    \ * \ fixnum*fast \ bignum* define-integer-ops
+    \ shift \ fixnum-shift-fast \ bignum-shift define-integer-ops
+] { } make >hashtable fast-math-ops set-global
+
+>>
+
+: math-op ( word left right -- word' ? )
+    3array math-ops get at* ;
+
+: math-method* ( word left right -- quot )
+    3dup math-op
+    [ >r 3drop r> 1quotation ] [ drop math-method ] if ;
+
+: math-both-known? ( word left right -- ? )
+    3dup math-op
+    [ 2drop 2drop t ]
+    [ drop math-class-max swap specific-method >boolean ] if ;
+
+: (derived-ops) ( word assoc -- words )
+    swap [ rot first eq? nip ] curry assoc-subset values ;
+
+: derived-ops ( word -- words )
+    [ 1array ]
+    [ math-ops get (derived-ops) ]
+    bi append ;
+
+: fast-derived-ops ( word -- words )
+    fast-math-ops get (derived-ops) ;
+
+: all-derived-ops ( word -- words )
+    [ derived-ops ] [ fast-derived-ops ] bi append ;
+
+: each-derived-op ( word quot -- )
+    >r derived-ops r> each ; inline
index 1a48e353a2aa4fc5e1ced8601758eae2c8507a7c..6f4ae2c1d5bccb4cb0983b03ab50f91295aef5b7 100755 (executable)
@@ -1,9 +1,9 @@
 USING: arrays compiler.units generic hashtables inference kernel
-kernel.private math optimizer prettyprint sequences sbufs
-strings tools.test vectors words sequences.private quotations
-optimizer.backend classes classes.algebra inference.dataflow
-classes.tuple.private continuations growable optimizer.inlining
-namespaces hints ;
+kernel.private math optimizer generator prettyprint sequences
+sbufs strings tools.test vectors words sequences.private
+quotations optimizer.backend classes classes.algebra
+inference.dataflow classes.tuple.private continuations growable
+optimizer.inlining namespaces hints ;
 IN: optimizer.tests
 
 [ H{ { 1 5 } { 3 4 } { 2 5 } } ] [
@@ -14,40 +14,6 @@ IN: optimizer.tests
     H{ { 1 2 } { 3 4 } } H{ { 2 3 } } union*
 ] unit-test
 
-! Test method inlining
-[ f ] [ fixnum { } min-class ] unit-test
-
-[ string ] [
-    \ string
-    [ integer string array reversed sbuf
-    slice vector quotation ]
-    sort-classes min-class
-] unit-test
-
-[ fixnum ] [
-    \ fixnum
-    [ fixnum integer object ]
-    sort-classes min-class
-] unit-test
-
-[ integer ] [
-    \ fixnum
-    [ integer float object ]
-    sort-classes min-class
-] unit-test
-
-[ object ] [
-    \ word
-    [ integer float object ]
-    sort-classes min-class
-] unit-test
-
-[ reversed ] [
-    \ reversed
-    [ integer reversed slice ]
-    sort-classes min-class
-] unit-test
-
 GENERIC: xyz ( obj -- obj )
 M: array xyz xyz ;
 
@@ -325,7 +291,6 @@ TUPLE: silly-tuple a b ;
 
 [ 1 2 3 ] [ lift-loop-tail-test-2 ] unit-test
 
-! Make sure we don't lose
 GENERIC: generic-inline-test ( x -- y )
 M: integer generic-inline-test ;
 
@@ -342,6 +307,7 @@ M: integer generic-inline-test ;
     generic-inline-test
     generic-inline-test ;
 
+! Inlining all of the above should only take two passes
 [ { t f } ] [
     \ generic-inline-test-1 word-def dataflow
     [ optimize-1 , optimize-1 , drop ] { } make
@@ -374,3 +340,19 @@ HINTS: recursive-inline-hang-3 array ;
 USE: sequences.private
 
 [ ] [ { (3append) } compile ] unit-test
+
+! Wow
+: counter-example ( a b c d -- a' b' c' d' )
+    dup 0 > [ 1 - >r rot 2 * r> counter-example ] when ; inline
+
+: counter-example' ( -- a' b' c' d' )
+    1 2 3.0 3 counter-example ;
+
+[ 2 4 6.0 0 ] [ counter-example' ] unit-test
+
+: member-test { + - * / /i } member? ;
+
+\ member-test must-infer
+[ ] [ \ member-test word-dataflow optimize 2drop ] unit-test
+[ t ] [ \ + member-test ] unit-test
+[ f ] [ \ append member-test ] unit-test
index 9e898450cc0a578161ad1942e652f8e45d7737ff..23cba3ea4c836138abc072f50c291c5caa3c2d55 100755 (executable)
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel namespaces optimizer.backend optimizer.def-use
 optimizer.known-words optimizer.math optimizer.control
-optimizer.inlining inference.class ;
+optimizer.collect optimizer.inlining inference.class ;
 IN: optimizer
 
 : optimize-1 ( node -- newnode ? )
@@ -10,10 +10,13 @@ IN: optimizer
         H{ } clone class-substitutions set
         H{ } clone literal-substitutions set
         H{ } clone value-substitutions set
-        dup compute-def-use
+
+        collect-label-infos
+        compute-def-use
         kill-values
-        dup detect-loops
-        dup infer-classes
+        detect-loops
+        infer-classes
+
         optimizer-changed off
         optimize-nodes
         optimizer-changed get
index c9019b029d70dd486cb077f79f38cb4b7fa38c00..c9933d5be2cf8b18d240d995d0623dac2c2a0fc7 100755 (executable)
@@ -1,11 +1,10 @@
 ! Copyright (C) 2003, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: arrays byte-arrays byte-vectors bit-arrays bit-vectors
-generic hashtables io assocs kernel math namespaces sequences
-strings sbufs io.styles vectors words prettyprint.config
-prettyprint.sections quotations io io.files math.parser effects
-classes.tuple classes.tuple.private classes float-arrays
-float-vectors ;
+USING: arrays byte-arrays bit-arrays generic hashtables io
+assocs kernel math namespaces sequences strings sbufs io.styles
+vectors words prettyprint.config prettyprint.sections quotations
+io io.files math.parser effects classes.tuple
+classes.tuple.private classes float-arrays ;
 IN: prettyprint.backend
 
 GENERIC: pprint* ( obj -- )
@@ -140,11 +139,8 @@ M: curry pprint-delims drop \ [ \ ] ;
 M: compose pprint-delims drop \ [ \ ] ;
 M: array pprint-delims drop \ { \ } ;
 M: byte-array pprint-delims drop \ B{ \ } ;
-M: byte-vector pprint-delims drop \ BV{ \ } ;
 M: bit-array pprint-delims drop \ ?{ \ } ;
-M: bit-vector pprint-delims drop \ ?V{ \ } ;
 M: float-array pprint-delims drop \ F{ \ } ;
-M: float-vector pprint-delims drop \ FV{ \ } ;
 M: vector pprint-delims drop \ V{ \ } ;
 M: hashtable pprint-delims drop \ H{ \ } ;
 M: tuple pprint-delims drop \ T{ \ } ;
@@ -156,9 +152,6 @@ GENERIC: >pprint-sequence ( obj -- seq )
 M: object >pprint-sequence ;
 
 M: vector >pprint-sequence ;
-M: bit-vector >pprint-sequence ;
-M: byte-vector >pprint-sequence ;
-M: float-vector >pprint-sequence ;
 M: curry >pprint-sequence ;
 M: compose >pprint-sequence ;
 M: hashtable >pprint-sequence >alist ;
index 1474f51c5316956a462b2d8bce517909e1ce2152..6a649bc5a688b1b9430bfb755a67c4ce5669cf2a 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2003, 2007 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 IN: prettyprint.config
-USING: alien arrays generic assocs io kernel math
+USING: arrays generic assocs io kernel math
 namespaces sequences strings io.styles vectors words
 continuations ;
 
index 525749cfae148e09b3beb7b026d0ccfe934fd3fa..981c8dcfd04447dda4917e7b9c93e09b3e8b3d6a 100755 (executable)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2003, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 IN: prettyprint
-USING: alien arrays generic generic.standard assocs io kernel
+USING: arrays generic generic.standard assocs io kernel
 math namespaces sequences strings io.styles io.streams.string
 vectors words prettyprint.backend prettyprint.sections
 prettyprint.config sorting splitting math.parser vocabs
index 319e5eab658e93675a231a8bd97e6028b3110b3f..803f6e24599451ae75095f8e3ede4eee5ff43670 100644 (file)
@@ -1,6 +1,6 @@
 ! Copyright (C) 2003, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien arrays generic hashtables io kernel math assocs
+USING: arrays generic hashtables io kernel math assocs
 namespaces sequences strings io.styles vectors words
 prettyprint.config splitting classes continuations
 io.streams.nested accessors ;
index bb3dc9337e84317e351273e7e6668c84e0d39d66..0dea0f43d96d7c632590888de34341c7f1ae06ca 100755 (executable)
@@ -76,10 +76,7 @@ ARTICLE: "sequences-reshape" "Reshaping sequences"
 { $subsection reversed }
 { $subsection <reversed> }
 "Transposing a matrix:"
-{ $subsection flip }
-"A " { $emphasis "column" } " presents a column of a matrix represented as a sequence of rows:"
-{ $subsection column }
-{ $subsection <column> } ;
+{ $subsection flip } ;
 
 ARTICLE: "sequences-appending" "Appending sequences"
 { $subsection append }
@@ -785,23 +782,6 @@ HELP: <slice>
 
 { <slice> subseq } related-words
 
-HELP: column
-{ $class-description "A virtual sequence which presents a fixed column of a matrix represented as a sequence of rows. New instances can be created by calling " { $link <column> } "." } ;
-
-HELP: <column> ( seq n -- column )
-{ $values { "seq" sequence } { "n" "a non-negative integer" } { "column" column } }
-{ $description "Outputs a new virtual sequence which presents a fixed column of a matrix represented as a sequence of rows." "The " { $snippet "i" } "th element of a column is the " { $snippet "n" } "th element of the " { $snippet "i" } "th element of" { $snippet "seq" } ". Every element of " { $snippet "seq" } " must be a sequence, and all sequences must have equal length." }
-{ $examples
-    { $example
-        "USING: arrays prettyprint sequences ;"
-        "{ { 1 2 3 } { 4 5 6 } { 7 8 9 } } 0 <column> >array ."
-        "{ 1 4 7 }"
-    }
-}
-{ $notes
-    "In the same sense that " { $link <reversed> } " is a virtual variant of " { $link reverse } ", " { $link <column> } " is a virtual variant of " { $snippet "swap [ nth ] curry map" } "."
-} ;
-
 HELP: repetition
 { $class-description "A virtual sequence consisting of " { $link repetition-elt } " repeated " { $link repetition-len } " times. Repetitions are created by calling " { $link <repetition> } "." } ;
 
index e8db18b3d03872beb3ba6e5ff6cf18683e0cff68..100184798ce6ad89994bfd1f12b8351b35e18dee 100755 (executable)
@@ -224,13 +224,6 @@ unit-test
 [ V{ 1 2 3 } ]
 [ 3 V{ 1 3 2 } clone [ push-new ] keep ] unit-test
 
-! Columns
-{ { 1 2 3 } { 4 5 6 } { 7 8 9 } } [ clone ] map "seq" set
-
-[ { 1 4 7 } ] [ "seq" get 0 <column> >array ] unit-test
-[ ] [ "seq" get 1 <column> [ sq ] change-each ] unit-test
-[ { 4 25 64 } ] [ "seq" get 1 <column> >array ] unit-test
-
 ! erg's random tester found this one
 [ SBUF" 12341234" ] [
     9 <sbuf> dup "1234" swap push-all dup dup swap push-all
index 252df543912ff901986da371bc02d48ea0b965d4..924d9a05cb84df55e8606db17c06c6ebc284e103 100755 (executable)
@@ -215,18 +215,6 @@ M: slice length dup slice-to swap slice-from - ;
 
 INSTANCE: slice virtual-sequence
 
-! A column of a matrix
-TUPLE: column seq col ;
-
-C: <column> column
-
-M: column virtual-seq column-seq ;
-M: column virtual@
-    dup column-col -rot column-seq nth bounds-check ;
-M: column length column-seq length ;
-
-INSTANCE: column virtual-sequence
-
 ! One element repeated many times
 TUPLE: repetition len elt ;
 
@@ -703,5 +691,5 @@ PRIVATE>
 : flip ( matrix -- newmatrix )
     dup empty? [
         dup [ length ] map infimum
-        [ <column> dup like ] with map
+        swap [ [ nth-unsafe ] with { } map-as ] curry { } map-as
     ] unless ;
index c2eb411f0a727657098acff3f4861cb8d3ad61c9..a2d15d298177c12b7fe47b925ef6e499f293b677 100755 (executable)
@@ -150,18 +150,6 @@ ARTICLE: "syntax-byte-arrays" "Byte array syntax"
 { $subsection POSTPONE: B{ }
 "Byte arrays are documented in " { $link "byte-arrays" } "." ;
 
-ARTICLE: "syntax-bit-vectors" "Bit vector syntax"
-{ $subsection POSTPONE: ?V{ }
-"Bit vectors are documented in " { $link "bit-vectors" } "." ;
-
-ARTICLE: "syntax-float-vectors" "Float vector syntax"
-{ $subsection POSTPONE: FV{ }
-"Float vectors are documented in " { $link "float-vectors" } "." ;
-
-ARTICLE: "syntax-byte-vectors" "Byte vector syntax"
-{ $subsection POSTPONE: BV{ }
-"Byte vectors are documented in " { $link "byte-vectors" } "." ;
-
 ARTICLE: "syntax-pathnames" "Pathname syntax"
 { $subsection POSTPONE: P" }
 "Pathnames are documented in " { $link "pathnames" } "." ;
@@ -182,9 +170,6 @@ $nl
 { $subsection "syntax-float-arrays" }
 { $subsection "syntax-vectors" }
 { $subsection "syntax-sbufs" }
-{ $subsection "syntax-bit-vectors" }
-{ $subsection "syntax-byte-vectors" }
-{ $subsection "syntax-float-vectors" }
 { $subsection "syntax-hashtables" }
 { $subsection "syntax-tuples" }
 { $subsection "syntax-pathnames" } ;
@@ -291,30 +276,12 @@ HELP: B{
 { $description "Marks the beginning of a literal byte array. Literal byte arrays are terminated by " { $link POSTPONE: } } "." } 
 { $examples { $code "B{ 1 2 3 }" } } ;
 
-HELP: BV{
-{ $syntax "BV{ elements... }" }
-{ $values { "elements" "a list of bytes" } }
-{ $description "Marks the beginning of a literal byte vector. Literal byte vectors are terminated by " { $link POSTPONE: } } "." } 
-{ $examples { $code "BV{ 1 2 3 12 }" } } ;
-
 HELP: ?{
 { $syntax "?{ elements... }" }
 { $values { "elements" "a list of booleans" } }
 { $description "Marks the beginning of a literal bit array. Literal bit arrays are terminated by " { $link POSTPONE: } } "." } 
 { $examples { $code "?{ t f t }" } } ;
 
-HELP: ?V{
-{ $syntax "?V{ elements... }" }
-{ $values { "elements" "a list of booleans" } }
-{ $description "Marks the beginning of a literal bit vector. Literal bit vectors are terminated by " { $link POSTPONE: } } "." } 
-{ $examples { $code "?V{ t f t }" } } ;
-
-HELP: FV{
-{ $syntax "FV{ elements... }" }
-{ $values { "elements" "a list of real numbers" } }
-{ $description "Marks the beginning of a literal float vector. Literal float vectors are terminated by " { $link POSTPONE: } } "." } 
-{ $examples { $code "FV{ 1.0 2.0 3.0 }" } } ;
-
 HELP: F{
 { $syntax "F{ elements... }" }
 { $values { "elements" "a list of real numbers" } }
index eaf5ffea051bd2fe3953cc91b4a0ae0ddb8a6d1f..566f5471f4af1f00829621cfb3ff5d0c2103b154 100755 (executable)
@@ -1,10 +1,10 @@
 ! Copyright (C) 2004, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien arrays bit-arrays bit-vectors byte-arrays
-byte-vectors definitions generic hashtables kernel math
+USING: alien arrays bit-arrays byte-arrays
+definitions generic hashtables kernel math
 namespaces parser sequences strings sbufs vectors words
 quotations io assocs splitting classes.tuple generic.standard
-generic.math classes io.files vocabs float-arrays float-vectors
+generic.math classes io.files vocabs float-arrays
 classes.union classes.mixin classes.predicate classes.singleton
 compiler.units combinators debugger ;
 IN: bootstrap.syntax
@@ -79,11 +79,8 @@ IN: bootstrap.syntax
     "{" [ \ } [ >array ] parse-literal ] define-syntax
     "V{" [ \ } [ >vector ] parse-literal ] define-syntax
     "B{" [ \ } [ >byte-array ] parse-literal ] define-syntax
-    "BV{" [ \ } [ >byte-vector ] parse-literal ] define-syntax
     "?{" [ \ } [ >bit-array ] parse-literal ] define-syntax
-    "?V{" [ \ } [ >bit-vector ] parse-literal ] define-syntax
     "F{" [ \ } [ >float-array ] parse-literal ] define-syntax
-    "FV{" [ \ } [ >float-vector ] parse-literal ] define-syntax
     "H{" [ \ } [ >hashtable ] parse-literal ] define-syntax
     "T{" [ \ } [ >tuple ] parse-literal ] define-syntax
     "W{" [ \ } [ first <wrapper> ] parse-literal ] define-syntax
index a2c50346df6478511413ae9cf69abb288673483c..3f9ff54ac858553543d8fef5bc60cf629a5b28a3 100755 (executable)
@@ -26,7 +26,7 @@ ARTICLE: "threads-yield" "Yielding and suspending threads"
 { $subsection resume }
 { $subsection resume-with } ;
 
-ARTICLE: "thread-state" "Thread-local state"
+ARTICLE: "thread-state" "Thread-local state and variables"
 "Threads form a class of objects:"
 { $subsection thread }
 "The current thread:"
@@ -36,6 +36,8 @@ ARTICLE: "thread-state" "Thread-local state"
 { $subsection tget }
 { $subsection tset }
 { $subsection tchange }
+"Each thread has its own independent set of thread-local variables and newly-spawned threads begin with an empty set."
+$nl
 "Global hashtable of all threads, keyed by " { $link thread-id } ":"
 { $subsection threads }
 "Threads have an identity independent of continuations. If a continuation is refied in one thread and then resumed in another thread, the code running in that continuation will observe a change in the value output by " { $link self } "." ;
index d746404cba4b751de0e4b1d5eac5622b655b6c3f..0ac607f0ede98baf658806fe7f19a73838079a3c 100755 (executable)
@@ -1,4 +1,5 @@
-USING: namespaces io tools.test threads kernel ;
+USING: namespaces io tools.test threads kernel
+concurrency.combinators math ;
 IN: threads.tests
 
 3 "x" set
@@ -16,3 +17,13 @@ yield
 ] unit-test
 
 [ f ] [ f get-global ] unit-test
+
+{ { 0 3 6 9 12 15 18 21 24 27 } } [
+    10 [
+        0 "i" tset
+        [
+            "i" [ yield 3 + ] tchange
+        ] times yield
+        "i" tget
+    ] parallel-map
+] unit-test
index f99191b91ffac7b08ceb66150f218ed4cab94b39..2f9c3a73de3c8efe2597c047108d825c51a9d5a9 100755 (executable)
@@ -27,7 +27,7 @@ mailbox variables sleep-entry ;
     tnamespace set-at ;
 
 : tchange ( key quot -- )
-    tnamespace change-at ; inline
+    tnamespace swap change-at ; inline
 
 : threads 41 getenv ;
 
diff --git a/extra/benchmark/binary-trees/binary-trees.factor b/extra/benchmark/binary-trees/binary-trees.factor
new file mode 100644 (file)
index 0000000..be4620b
--- /dev/null
@@ -0,0 +1,55 @@
+USING: kernel math accessors prettyprint io locals sequences
+math.ranges ;
+IN: benchmark.binary-trees
+
+TUPLE: tree-node item left right ;
+
+C: <tree-node> tree-node
+
+: bottom-up-tree ( item depth -- tree )
+    dup 0 > [
+        1 -
+        [ drop ]
+        [ >r 2 * 1 - r> bottom-up-tree ]
+        [ >r 2 *     r> bottom-up-tree ] 2tri
+    ] [
+        drop f f
+    ] if <tree-node> ;
+
+GENERIC: item-check ( node -- n )
+
+M: tree-node item-check
+    [ item>> ] [ left>> ] [ right>> ] tri [ item-check ] bi@ - + ;
+
+M: f item-check drop 0 ;
+
+: min-depth 4 ; inline
+
+: stretch-tree ( max-depth -- )
+    1 + 0 over bottom-up-tree item-check
+    [ "stretch tree of depth " write pprint ]
+    [ "\t check: " write . ] bi* ;
+
+:: long-lived-tree ( max-depth -- )
+    0 max-depth bottom-up-tree
+
+    min-depth max-depth 2 <range> [| depth |
+        max-depth depth - min-depth + 2^ [
+            [1,b] 0 [
+                dup neg
+                [ depth bottom-up-tree item-check + ] bi@
+            ] reduce
+        ]
+        [ 2 * ] bi
+        pprint "\t trees of depth " write depth pprint
+        "\t check: " write .
+    ] each
+
+    "long lived tree of depth " write max-depth pprint
+    "\t check: " write item-check . ;
+
+: binary-trees ( n -- )
+    min-depth 2 + max [ stretch-tree ] [ long-lived-tree ] bi ;
+
+: binary-trees-main ( -- )
+    16 binary-trees ;
index d51a723cbdf0c8e48114e74c4ab920e345c8201b..53e9c9a14c6e1e3f5e7ebb2d500d6ebf3e8833e8 100644 (file)
@@ -1,4 +1,4 @@
-USING: namespaces math sequences splitting kernel ;
+USING: namespaces math sequences splitting kernel columns ;
 IN: benchmark.dispatch2
 
 : sequences
index bb4c5ba904227f890fa5d304c8f543272b1f9cf1..409d6d4a0f1866b5dbb6bb8e763686fdb52c232d 100644 (file)
@@ -1,5 +1,5 @@
 USING: sequences math mirrors splitting kernel namespaces
-assocs alien.syntax ;
+assocs alien.syntax columns ;
 IN: benchmark.dispatch3
 
 GENERIC: g ( obj -- str )
index ee66e303ec0a65ada329fbc614653d60179060c3..f69547df6069cc9852a7a2b2c536d3be60297e8e 100755 (executable)
@@ -1,38 +1,37 @@
+USING: math kernel hints prettyprint io combinators ;
 IN: benchmark.recursive
-USING: math kernel hints prettyprint io ;
 
 : fib ( m -- n )
-    dup 2 < [ drop 1 ] [ dup 1 - fib swap 2 - fib + ] if ;
+    dup 2 < [ drop 1 ] [ [ 1 - fib ] [ 2 - fib ] bi + ] if ;
+    inline
 
 : ack ( m n -- x )
-    over zero? [
-        nip 1+
-    ] [
-        dup zero? [
-            drop 1- 1 ack
-        ] [
-            dupd 1- ack >r 1- r> ack
-        ] if
-    ] if ;
+    {
+        { [ over zero? ] [ nip 1+ ] }
+        { [ dup zero? ] [ drop 1- 1 ack ] }
+        [ [ drop 1- ] [ 1- ack ] 2bi ack ]
+    } cond ; inline
 
 : tak ( x y z -- t )
-    2over swap < [
-        [ rot 1- -rot tak ] 3keep
-        [ -rot 1- -rot tak ] 3keep
-        1- -rot tak
-        tak
-    ] [
+    2over <= [
         2nip
-    ] if ;
+    ] [
+        [  rot 1- -rot tak ]
+        [ -rot 1- -rot tak ]
+        [      1- -rot tak ]
+        3tri
+        tak
+    ] if ; inline
 
 : recursive ( n -- )
-    3 over ack . flush
-    dup 27.0 + fib . flush
-    1-
-    dup 3 * over 2 * rot tak . flush
+    [ 3 swap ack . flush ]
+    [ 27.0 + fib . flush ]
+    [ 1- [ 3 * ] [ 2 * ] [ ] tri tak . flush ] tri
     3 fib . flush
     3.0 2.0 1.0 tak . flush ;
 
+HINTS: recursive fixnum ;
+
 : recursive-main 11 recursive ;
 
 MAIN: recursive-main
index 7eddeefc1b0a97717590a25085466dfebb8d399f..5d36aa25bd8154ce8f8ce3c75928e32e2e2ab4fc 100644 (file)
@@ -1,48 +1,44 @@
 ! Factor port of
 ! http://shootout.alioth.debian.org/gp4/benchmark.php?test=spectralnorm&lang=all
 USING: float-arrays kernel math math.functions math.vectors
-sequences sequences.private prettyprint words tools.time hints ;
+sequences sequences.private prettyprint words
+hints locals ;
 IN: benchmark.spectral-norm
 
-: fast-truncate >fixnum >float ; inline
+:: inner-loop ( u n quot -- seq )
+    n [| i |
+        n 0.0 [| j |
+            u i j quot call +
+        ] reduce
+    ] F{ } map-as ; inline
 
 : eval-A ( i j -- n )
     [ >float ] bi@
-    dupd + dup 1+ * 2 /f fast-truncate + 1+
-    recip ; inline
+    [ drop ] [ + [ ] [ 1 + ] bi * 0.5 * ] 2bi
+    + 1 + recip ; inline
 
 : (eval-A-times-u) ( u i j -- x )
-    tuck eval-A >r swap nth-unsafe r> * ; inline
+    tuck [ swap nth-unsafe ] [ eval-A ] 2bi* * ; inline
 
 : eval-A-times-u ( n u -- seq )
-    over [
-        pick 0.0 [
-            swap >r >r 2dup r> (eval-A-times-u) r> +
-        ] reduce nip
-    ] F{ } map-as 2nip ; inline
+    [ (eval-A-times-u) ] inner-loop ; inline
 
 : (eval-At-times-u) ( u i j -- x )
-    tuck swap eval-A >r swap nth-unsafe r> * ; inline
+    tuck [ swap nth-unsafe ] [ swap eval-A ] 2bi* * ; inline
 
-: eval-At-times-u ( n u -- seq )
-    over [
-        pick 0.0 [
-            swap >r >r 2dup r> (eval-At-times-u) r> +
-        ] reduce nip
-    ] F{ } map-as 2nip ; inline
+: eval-At-times-u ( u n -- seq )
+    [ (eval-At-times-u) ] inner-loop ; inline
 
-: eval-AtA-times-u ( n u -- seq )
-    dupd eval-A-times-u eval-At-times-u ; inline
+: eval-AtA-times-u ( u n -- seq )
+    [ eval-A-times-u ] [ eval-At-times-u ] bi ; inline
 
-: u/v ( n -- u v )
-    dup 1.0 <float-array> dup
+:: u/v ( n -- u v )
+    n 1.0 <float-array> dup
     10 [
         drop
-        dupd eval-AtA-times-u
-        2dup eval-AtA-times-u
-        swap
-    ] times
-    rot drop ; inline
+        n eval-AtA-times-u
+        [ n eval-AtA-times-u ] keep
+    ] times ; inline
 
 : spectral-norm ( n -- norm )
     u/v [ v. ] keep norm-sq /f sqrt ;
@@ -50,6 +46,6 @@ IN: benchmark.spectral-norm
 HINTS: spectral-norm fixnum ;
 
 : spectral-norm-main ( -- )
-    2000 spectral-norm . ;
+    5500 spectral-norm . ;
 
 MAIN: spectral-norm-main
diff --git a/extra/bit-vectors/bit-vectors-docs.factor b/extra/bit-vectors/bit-vectors-docs.factor
new file mode 100755 (executable)
index 0000000..41f32b4
--- /dev/null
@@ -0,0 +1,42 @@
+USING: arrays bit-arrays help.markup help.syntax kernel\r
+bit-vectors.private combinators ;\r
+IN: bit-vectors\r
+\r
+ARTICLE: "bit-vectors" "Bit vectors"\r
+"A bit vector is a resizable mutable sequence of bits. Bit vector words are found in the " { $vocab-link "bit-vectors" } " vocabulary."\r
+$nl\r
+"Bit vectors form a class:"\r
+{ $subsection bit-vector }\r
+{ $subsection bit-vector? }\r
+"Creating bit vectors:"\r
+{ $subsection >bit-vector }\r
+{ $subsection <bit-vector> }\r
+"Literal syntax:"\r
+{ $subsection POSTPONE: ?V{ }\r
+"If you don't care about initial capacity, a more elegant way to create a new bit vector is to write:"\r
+{ $code "?V{ } clone" } ;\r
+\r
+ABOUT: "bit-vectors"\r
+\r
+HELP: bit-vector\r
+{ $description "The class of resizable bit vectors. See " { $link "bit-vectors" } " for information." } ;\r
+\r
+HELP: <bit-vector>\r
+{ $values { "n" "a positive integer specifying initial capacity" } { "bit-vector" bit-vector } }\r
+{ $description "Creates a new bit vector that can hold " { $snippet "n" } " bits before resizing." } ;\r
+\r
+HELP: >bit-vector\r
+{ $values { "seq" "a sequence" } { "bit-vector" bit-vector } }\r
+{ $description "Outputs a freshly-allocated bit vector with the same elements as a given sequence." } ;\r
+\r
+HELP: bit-array>vector\r
+{ $values { "bit-array" "an array" } { "length" "a non-negative integer" } { "bit-vector" bit-vector } }\r
+{ $description "Creates a new bit vector using the array for underlying storage with the specified initial length." }\r
+{ $warning "This word is in the " { $vocab-link "bit-vectors.private" } " vocabulary because it does not perform type or bounds checks. User code should call " { $link >bit-vector } " instead." } ;\r
+\r
+HELP: ?V{\r
+{ $syntax "?V{ elements... }" }\r
+{ $values { "elements" "a list of booleans" } }\r
+{ $description "Marks the beginning of a literal bit vector. Literal bit vectors are terminated by " { $link POSTPONE: } } "." } \r
+{ $examples { $code "?V{ t f t }" } } ;\r
+\r
diff --git a/extra/bit-vectors/bit-vectors-tests.factor b/extra/bit-vectors/bit-vectors-tests.factor
new file mode 100755 (executable)
index 0000000..dff9a8d
--- /dev/null
@@ -0,0 +1,14 @@
+IN: bit-vectors.tests\r
+USING: tools.test bit-vectors vectors sequences kernel math ;\r
+\r
+[ 0 ] [ 123 <bit-vector> length ] unit-test\r
+\r
+: do-it\r
+    1234 swap [ >r even? r> push ] curry each ;\r
+\r
+[ t ] [\r
+    3 <bit-vector> dup do-it\r
+    3 <vector> dup do-it sequence=\r
+] unit-test\r
+\r
+[ t ] [ ?V{ } bit-vector? ] unit-test\r
diff --git a/extra/bit-vectors/bit-vectors.factor b/extra/bit-vectors/bit-vectors.factor
new file mode 100755 (executable)
index 0000000..c14b0a5
--- /dev/null
@@ -0,0 +1,51 @@
+! Copyright (C) 2008 Slava Pestov.\r
+! See http://factorcode.org/license.txt for BSD license.\r
+USING: arrays kernel kernel.private math sequences\r
+sequences.private growable bit-arrays prettyprint.backend\r
+parser accessors ;\r
+IN: bit-vectors\r
+\r
+TUPLE: bit-vector underlying fill ;\r
+\r
+M: bit-vector underlying underlying>> { bit-array } declare ;\r
+\r
+M: bit-vector set-underlying (>>underlying) ;\r
+\r
+M: bit-vector length fill>> { array-capacity } declare ;\r
+\r
+M: bit-vector set-fill (>>fill) ;\r
+\r
+<PRIVATE\r
+\r
+: bit-array>vector ( bit-array length -- bit-vector )\r
+    bit-vector boa ; inline\r
+\r
+PRIVATE>\r
+\r
+: <bit-vector> ( n -- bit-vector )\r
+    <bit-array> 0 bit-array>vector ; inline\r
+\r
+: >bit-vector ( seq -- bit-vector )\r
+    T{ bit-vector f ?{ } 0 } clone-like ;\r
+\r
+M: bit-vector like\r
+    drop dup bit-vector? [\r
+        dup bit-array?\r
+        [ dup length bit-array>vector ] [ >bit-vector ] if\r
+    ] unless ;\r
+\r
+M: bit-vector new-sequence\r
+    drop [ <bit-array> ] keep >fixnum bit-array>vector ;\r
+\r
+M: bit-vector equal?\r
+    over bit-vector? [ sequence= ] [ 2drop f ] if ;\r
+\r
+M: bit-array new-resizable drop <bit-vector> ;\r
+\r
+INSTANCE: bit-vector growable\r
+\r
+: ?V{ \ } [ >bit-vector ] parse-literal ; parsing\r
+\r
+M: bit-vector >pprint-sequence ;\r
+\r
+M: bit-vector pprint-delims drop \ ?V{ \ } ;\r
diff --git a/extra/bit-vectors/summary.txt b/extra/bit-vectors/summary.txt
new file mode 100644 (file)
index 0000000..76a7d0f
--- /dev/null
@@ -0,0 +1 @@
+Growable bit arrays
diff --git a/extra/bit-vectors/tags.txt b/extra/bit-vectors/tags.txt
new file mode 100644 (file)
index 0000000..42d711b
--- /dev/null
@@ -0,0 +1 @@
+collections
index 327b90e01f08a5561927e25589ea96cc4942f0a9..e601506fb457d92bf46884754e67e8bc2a7c4a8a 100644 (file)
@@ -8,6 +8,8 @@ IN: builder.cleanup
 
 SYMBOL: builder-debug
 
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
 : compress-image ( -- ) { "bzip2" my-boot-image-name } to-strings try-process ;
 
 : delete-child-factor ( -- )
index e3c207eaaaf1dfa81014fddcffac3f6c56270e32..474606e451a5fb08cea0d6641e2a59cd1c539947 100644 (file)
@@ -7,6 +7,10 @@ IN: builder.common
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
+SYMBOL: upload-to-factorcode
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
 SYMBOL: builds-dir
 
 : builds ( -- path )
@@ -21,15 +25,6 @@ VAR: stamp
 : builds/factor ( -- path ) builds "factor" append-path ;
 : build-dir     ( -- path ) builds stamp>   append-path ;
 
-: create-build-dir ( -- )
-  datestamp >stamp
-  build-dir make-directory ;
-  
-: enter-build-dir  ( -- ) build-dir set-current-directory ;
-
-: clone-builds-factor ( -- )
-  { "git" "clone" builds/factor } to-strings try-process ;
-
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
 : prepare-build-machine ( -- )
@@ -57,8 +52,3 @@ SYMBOL: status
   { status-vm status-boot status-test status-build status-release status }
     [ off ]
   each ;
-
-! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-SYMBOL: upload-to-factorcode
-
index eed48cb177b5e465a2bb6ae04ad2733c872656be..ecde47f8f7f90d51cfa718c08d3863cdd85de507 100644 (file)
@@ -8,6 +8,8 @@ IN: builder.email
 SYMBOL: builder-from
 SYMBOL: builder-recipients
 
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
 : subject-status ( -- str ) status get [ "report" ] [ "error" ] if ;
 
 : subject ( -- str ) { "builder@" host-name* ": " subject-status } to-string ;
diff --git a/extra/byte-vectors/byte-vectors-docs.factor b/extra/byte-vectors/byte-vectors-docs.factor
new file mode 100755 (executable)
index 0000000..139cbab
--- /dev/null
@@ -0,0 +1,42 @@
+USING: arrays byte-arrays help.markup help.syntax kernel\r
+byte-vectors.private combinators ;\r
+IN: byte-vectors\r
+\r
+ARTICLE: "byte-vectors" "Byte vectors"\r
+"A byte vector is a resizable mutable sequence of unsigned bytes. Byte vector words are found in the " { $vocab-link "byte-vectors" } " vocabulary."\r
+$nl\r
+"Byte vectors form a class:"\r
+{ $subsection byte-vector }\r
+{ $subsection byte-vector? }\r
+"Creating byte vectors:"\r
+{ $subsection >byte-vector }\r
+{ $subsection <byte-vector> }\r
+"Literal syntax:"\r
+{ $subsection POSTPONE: BV{ }\r
+"If you don't care about initial capacity, a more elegant way to create a new byte vector is to write:"\r
+{ $code "BV{ } clone" } ;\r
+\r
+ABOUT: "byte-vectors"\r
+\r
+HELP: byte-vector\r
+{ $description "The class of resizable byte vectors. See " { $link "byte-vectors" } " for information." } ;\r
+\r
+HELP: <byte-vector>\r
+{ $values { "n" "a positive integer specifying initial capacity" } { "byte-vector" byte-vector } }\r
+{ $description "Creates a new byte vector that can hold " { $snippet "n" } " bytes before resizing." } ;\r
+\r
+HELP: >byte-vector\r
+{ $values { "seq" "a sequence" } { "byte-vector" byte-vector } }\r
+{ $description "Outputs a freshly-allocated byte vector with the same elements as a given sequence." }\r
+{ $errors "Throws an error if the sequence contains elements other than integers." } ;\r
+\r
+HELP: byte-array>vector\r
+{ $values { "byte-array" "an array" } { "length" "a non-negative integer" } { "byte-vector" byte-vector } }\r
+{ $description "Creates a new byte vector using the array for underlying storage with the specified initial length." }\r
+{ $warning "This word is in the " { $vocab-link "byte-vectors.private" } " vocabulary because it does not perform type or bounds checks. User code should call " { $link >byte-vector } " instead." } ;\r
+\r
+HELP: BV{\r
+{ $syntax "BV{ elements... }" }\r
+{ $values { "elements" "a list of bytes" } }\r
+{ $description "Marks the beginning of a literal byte vector. Literal byte vectors are terminated by " { $link POSTPONE: } } "." } \r
+{ $examples { $code "BV{ 1 2 3 12 }" } } ;\r
diff --git a/extra/byte-vectors/byte-vectors-tests.factor b/extra/byte-vectors/byte-vectors-tests.factor
new file mode 100755 (executable)
index 0000000..d457d68
--- /dev/null
@@ -0,0 +1,14 @@
+IN: byte-vectors.tests\r
+USING: tools.test byte-vectors vectors sequences kernel ;\r
+\r
+[ 0 ] [ 123 <byte-vector> length ] unit-test\r
+\r
+: do-it\r
+    123 [ over push ] each ;\r
+\r
+[ t ] [\r
+    3 <byte-vector> do-it\r
+    3 <vector> do-it sequence=\r
+] unit-test\r
+\r
+[ t ] [ BV{ } byte-vector? ] unit-test\r
diff --git a/extra/byte-vectors/byte-vectors.factor b/extra/byte-vectors/byte-vectors.factor
new file mode 100755 (executable)
index 0000000..a8351dc
--- /dev/null
@@ -0,0 +1,51 @@
+! Copyright (C) 2008 Slava Pestov.\r
+! See http://factorcode.org/license.txt for BSD license.\r
+USING: arrays kernel kernel.private math sequences\r
+sequences.private growable byte-arrays prettyprint.backend\r
+parser accessors ;\r
+IN: byte-vectors\r
+\r
+TUPLE: byte-vector underlying fill ;\r
+\r
+M: byte-vector underlying underlying>> { byte-array } declare ;\r
+\r
+M: byte-vector set-underlying (>>underlying) ;\r
+\r
+M: byte-vector length fill>> { array-capacity } declare ;\r
+\r
+M: byte-vector set-fill (>>fill) ;\r
+\r
+<PRIVATE\r
+\r
+: byte-array>vector ( byte-array length -- byte-vector )\r
+    byte-vector boa ; inline\r
+\r
+PRIVATE>\r
+\r
+: <byte-vector> ( n -- byte-vector )\r
+    <byte-array> 0 byte-array>vector ; inline\r
+\r
+: >byte-vector ( seq -- byte-vector )\r
+    T{ byte-vector f B{ } 0 } clone-like ;\r
+\r
+M: byte-vector like\r
+    drop dup byte-vector? [\r
+        dup byte-array?\r
+        [ dup length byte-array>vector ] [ >byte-vector ] if\r
+    ] unless ;\r
+\r
+M: byte-vector new-sequence\r
+    drop [ <byte-array> ] keep >fixnum byte-array>vector ;\r
+\r
+M: byte-vector equal?\r
+    over byte-vector? [ sequence= ] [ 2drop f ] if ;\r
+\r
+M: byte-array new-resizable drop <byte-vector> ;\r
+\r
+INSTANCE: byte-vector growable\r
+\r
+: BV{ \ } [ >byte-vector ] parse-literal ; parsing\r
+\r
+M: byte-vector >pprint-sequence ;\r
+\r
+M: byte-vector pprint-delims drop \ BV{ \ } ;\r
diff --git a/extra/byte-vectors/summary.txt b/extra/byte-vectors/summary.txt
new file mode 100644 (file)
index 0000000..e914ebb
--- /dev/null
@@ -0,0 +1 @@
+Growable byte arrays
diff --git a/extra/byte-vectors/tags.txt b/extra/byte-vectors/tags.txt
new file mode 100644 (file)
index 0000000..42d711b
--- /dev/null
@@ -0,0 +1 @@
+collections
index e49d3ad894c8e3255479b2d896d30573881d6243..c05d4f60eb4a676bec309ec8842fd1abce8a8dae 100755 (executable)
@@ -2,6 +2,10 @@ USING: arrays calendar kernel math sequences tools.test
 continuations system ;
 IN: calendar.tests
 
+\ time+ must-infer
+\ time* must-infer
+\ time- must-infer
+
 [ f ] [ 2004 12 32 0   0  0 instant <timestamp> valid-timestamp? ] unit-test
 [ f ] [ 2004  2 30 0   0  0 instant <timestamp> valid-timestamp? ] unit-test
 [ f ] [ 2003  2 29 0   0  0 instant <timestamp> valid-timestamp? ] unit-test
index 8dcb4af7f1f520f59c39a85e100511f8c93d3b47..2f93bf821852d371b8b00948db6c1ae0e48776fc 100755 (executable)
@@ -211,12 +211,14 @@ M: duration time+
     #! Uses average month/year length since dt loses calendar
     #! data
     0 swap
-    [ year>> + ] keep
-    [ month>> months-per-year / + ] keep
-    [ day>> days-per-year / + ] keep
-    [ hour>> hours-per-year / + ] keep
-    [ minute>> minutes-per-year / + ] keep
-    second>> seconds-per-year / + ;
+    {
+        [ year>> + ]
+        [ month>> months-per-year / + ]
+        [ day>> days-per-year / + ]
+        [ hour>> hours-per-year / + ]
+        [ minute>> minutes-per-year / + ]
+        [ second>> seconds-per-year / + ]
+    } cleave ;
 
 M: duration <=> [ dt>years ] compare ;
 
@@ -252,14 +254,21 @@ M: timestamp time-
     #! Exact calendar-time difference
     (time-) seconds ;
 
+: time* ( obj1 obj2 -- obj3 )
+    dup real? [ swap ] when
+    dup real? [ * ] [
+        {
+            [   year>> * ]
+            [  month>> * ]
+            [    day>> * ]
+            [   hour>> * ]
+            [ minute>> * ]
+            [ second>> * ]
+        } 2cleave <duration>
+    ] if ;
+
 : before ( dt -- -dt )
-    [ year>>   neg ] keep
-    [ month>>  neg ] keep
-    [ day>>    neg ] keep
-    [ hour>>   neg ] keep
-    [ minute>> neg ] keep
-      second>> neg
-    <duration> ;
+    -1 time* ;
 
 M: duration time-
     before time+ ;
index 88bd0733c0e99f1112058d22a379fe75785626bf..1ba892bef3fc08e1ff0e7520575cf10070fd2957 100755 (executable)
@@ -1,26 +1,45 @@
-USING: calendar.format calendar kernel tools.test\r
-io.streams.string ;\r
+USING: calendar.format calendar kernel math tools.test\r
+io.streams.string accessors io ;\r
 IN: calendar.format.tests\r
 \r
 [ 0 ] [\r
-    "Z" [ read-rfc3339-gmt-offset ] with-string-reader\r
+    "Z" [ read1 read-rfc3339-gmt-offset ] with-string-reader dt>hours\r
 ] unit-test\r
 \r
 [ 1 ] [\r
-    "+01" [ read-rfc3339-gmt-offset ] with-string-reader\r
+    "+01" [ read1 read-rfc3339-gmt-offset ] with-string-reader dt>hours\r
 ] unit-test\r
 \r
 [ -1 ] [\r
-    "-01" [ read-rfc3339-gmt-offset ] with-string-reader\r
+    "-01" [ read1 read-rfc3339-gmt-offset ] with-string-reader dt>hours\r
 ] unit-test\r
 \r
 [ -1-1/2 ] [\r
-    "-01:30" [ read-rfc3339-gmt-offset ] with-string-reader\r
+    "-01:30" [ read1 read-rfc3339-gmt-offset ] with-string-reader dt>hours\r
 ] unit-test\r
 \r
 [ 1+1/2 ] [\r
-    "+01:30" [ read-rfc3339-gmt-offset ] with-string-reader\r
+    "+01:30" [ read1 read-rfc3339-gmt-offset ] with-string-reader dt>hours\r
 ] unit-test\r
 \r
 [ ] [ now timestamp>rfc3339 drop ] unit-test\r
 [ ] [ now timestamp>rfc822 drop ] unit-test\r
+\r
+[ 8/1000 -4 ] [\r
+    "2008-04-19T04:56:00.008-04:00" rfc3339>timestamp\r
+    [ second>> ] [ gmt-offset>> hour>> ] bi\r
+] unit-test\r
+\r
+[ T{ duration f 0 0 0 0 0 0 } ] [\r
+    "GMT" parse-rfc822-gmt-offset\r
+] unit-test\r
+\r
+[ T{ duration f 0 0 0 -5 0 0 } ] [\r
+    "-0500" parse-rfc822-gmt-offset\r
+] unit-test\r
+\r
+[ T{ timestamp f 2008 4 22 14 36 12 T{ duration f 0 0 0 0 0 0 } } ] [\r
+    "Tue, 22 Apr 2008 14:36:12 GMT" rfc822>timestamp\r
+] unit-test\r
+\r
+[ t ] [ now dup timestamp>rfc822 rfc822>timestamp time- 1 seconds before? ] unit-test\r
index 26ed873fd33541b573bcb89c252e5b8845cc8ffa..7bdaea70b55088fe05f7e612dc402ca972885a3d 100755 (executable)
@@ -1,5 +1,6 @@
 USING: math math.parser kernel sequences io calendar\r
-accessors arrays io.streams.string combinators accessors ;\r
+accessors arrays io.streams.string splitting\r
+combinators accessors debugger ;\r
 IN: calendar.format\r
 \r
 GENERIC: day. ( obj -- )\r
@@ -58,11 +59,11 @@ M: timestamp year. ( timestamp -- )
     [ hour>> write-00 ] [ minute>> write-00 ] bi ;\r
 \r
 : write-gmt-offset ( gmt-offset -- )\r
-    dup instant <=> {\r
-        { [ dup 0 = ] [ 2drop "GMT" write ] }\r
-        { [ dup 0 < ] [ drop "-" write before (write-gmt-offset) ] }\r
-        { [ dup 0 > ] [ drop "+" write (write-gmt-offset) ] }\r
-    } cond ;\r
+    dup instant <=> sgn {\r
+        {  0 [ drop "GMT" write ] }\r
+        { -1 [ "-" write before (write-gmt-offset) ] }\r
+        {  1 [ "+" write (write-gmt-offset) ] }\r
+    } case ;\r
 \r
 : timestamp>rfc822 ( timestamp -- str )\r
     #! RFC822 timestamp format\r
@@ -83,20 +84,22 @@ M: timestamp year. ( timestamp -- )
     [ minute>> write-00 ] bi ;\r
 \r
 : write-rfc3339-gmt-offset ( duration -- )\r
-    dup instant <=> {\r
-        { [ dup 0 = ] [ 2drop "Z" write ] }\r
-        { [ dup 0 < ] [ drop CHAR: - write1 before (write-rfc3339-gmt-offset) ] }\r
-        { [ dup 0 > ] [ drop CHAR: + write1 (write-rfc3339-gmt-offset) ] }\r
-    } cond ;\r
+    dup instant <=> sgn {\r
+        {  0 [ drop "Z" write ] }\r
+        { -1 [ CHAR: - write1 before (write-rfc3339-gmt-offset) ] }\r
+        {  1 [ CHAR: + write1 (write-rfc3339-gmt-offset) ] }\r
+    } case ;\r
     \r
 : (timestamp>rfc3339) ( timestamp -- )\r
-    dup year>> number>string write CHAR: - write1\r
-    dup month>> write-00 CHAR: - write1\r
-    dup day>> write-00 CHAR: T write1\r
-    dup hour>> write-00 CHAR: : write1\r
-    dup minute>> write-00 CHAR: : write1\r
-    dup second>> >fixnum write-00\r
-    gmt-offset>> write-rfc3339-gmt-offset ;\r
+    {\r
+        [ year>> number>string write CHAR: - write1 ]\r
+        [ month>> write-00 CHAR: - write1 ]\r
+        [ day>> write-00 CHAR: T write1 ]\r
+        [ hour>> write-00 CHAR: : write1 ]\r
+        [ minute>> write-00 CHAR: : write1 ]\r
+        [ second>> >fixnum write-00 ]\r
+        [ gmt-offset>> write-rfc3339-gmt-offset ]\r
+    } cleave ;\r
 \r
 : timestamp>rfc3339 ( timestamp -- str )\r
     [ (timestamp>rfc3339) ] with-string-writer ;\r
@@ -106,14 +109,20 @@ M: timestamp year. ( timestamp -- )
 \r
 : read-00 2 read string>number ;\r
 \r
+: read-000 3 read string>number ;\r
+\r
 : read-0000 4 read string>number ;\r
 \r
-: read-rfc3339-gmt-offset ( -- n )\r
-    read1 dup CHAR: Z = [ drop 0 ] [\r
-        { { CHAR: + [ 1 ] } { CHAR: - [ -1 ] } } case\r
-        read-00\r
-        read1 { { CHAR: : [ read-00 ] } { f [ 0 ] } } case\r
-        60 / + *\r
+: signed-gmt-offset ( dt ch -- dt' )\r
+    { { CHAR: + [ 1 ] } { CHAR: - [ -1 ] } } case time* ;\r
+\r
+: read-rfc3339-gmt-offset ( ch -- dt )\r
+    dup CHAR: Z = [ drop instant ] [\r
+        >r\r
+        read-00 hours\r
+        read1 { { CHAR: : [ read-00 ] } { f [ 0 ] } } case minutes\r
+        time+\r
+        r> signed-gmt-offset\r
     ] if ;\r
 \r
 : read-ymd ( -- y m d )\r
@@ -126,26 +135,61 @@ M: timestamp year. ( timestamp -- )
     read-ymd\r
     "Tt" expect\r
     read-hms\r
-    read-rfc3339-gmt-offset ! timezone\r
+    read1 { { CHAR: . [ read-000 1000 / + read1 ] } [ ] } case\r
+    read-rfc3339-gmt-offset\r
     <timestamp> ;\r
 \r
 : rfc3339>timestamp ( str -- timestamp )\r
     [ (rfc3339>timestamp) ] with-string-reader ;\r
 \r
+ERROR: invalid-rfc822-date ;\r
+\r
+: check-rfc822-date ( obj/f -- obj ) [ invalid-rfc822-date ] unless* ;\r
+\r
+: read-token ( seps -- token )\r
+    [ read-until ] keep member? check-rfc822-date drop ;\r
+\r
+: read-sp ( -- token ) " " read-token ;\r
+\r
+: checked-number ( str -- n )\r
+    string>number check-rfc822-date ;\r
+\r
+: parse-rfc822-gmt-offset ( string -- dt )\r
+    dup "GMT" = [ drop instant ] [\r
+        unclip >r\r
+        2 cut [ string>number ] bi@ [ hours ] [ minutes ] bi* time+\r
+        r> signed-gmt-offset\r
+    ] if ;\r
+\r
+: (rfc822>timestamp) ( -- timestamp )\r
+    timestamp new\r
+        "," read-token day-abbreviations3 member? check-rfc822-date drop\r
+        read1 CHAR: \s assert=\r
+        read-sp checked-number >>day\r
+        read-sp month-abbreviations index check-rfc822-date >>month\r
+        read-sp checked-number >>year\r
+        ":" read-token checked-number >>hour\r
+        ":" read-token checked-number >>minute\r
+        " " read-token checked-number >>second\r
+        readln parse-rfc822-gmt-offset >>gmt-offset ;\r
+\r
+: rfc822>timestamp ( str -- timestamp )\r
+    [ (rfc822>timestamp) ] with-string-reader ;\r
+\r
 : (ymdhms>timestamp) ( -- timestamp )\r
-    read-ymd " " expect read-hms 0 <timestamp> ;\r
+    read-ymd " " expect read-hms instant <timestamp> ;\r
 \r
 : ymdhms>timestamp ( str -- timestamp )\r
     [ (ymdhms>timestamp) ] with-string-reader ;\r
 \r
 : (hms>timestamp) ( -- timestamp )\r
-    f f f read-hms f <timestamp> ;\r
+    f f f read-hms instant <timestamp> ;\r
 \r
 : hms>timestamp ( str -- timestamp )\r
     [ (hms>timestamp) ] with-string-reader ;\r
 \r
 : (ymd>timestamp) ( -- timestamp )\r
-    read-ymd f f f f <timestamp> ;\r
+    read-ymd f f f instant <timestamp> ;\r
 \r
 : ymd>timestamp ( str -- timestamp )\r
     [ (ymd>timestamp) ] with-string-reader ;\r
index ca9509c3ec917bd8ee16939af932d04c2073ce9c..df3f84d45121b203dc013ae1db66f23eff329c02 100755 (executable)
@@ -1,10 +1,10 @@
-! Copyright (C) 2006, 2007 Slava Pestov.
+! Copyright (C) 2006, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien alien.c-types alien.compiler
+USING: alien alien.c-types alien.strings alien.compiler
 arrays assocs combinators compiler inference.transforms kernel
 math namespaces parser prettyprint prettyprint.sections
 quotations sequences strings words cocoa.runtime io macros
-memoize debugger ;
+memoize debugger io.encodings.ascii ;
 IN: cocoa.messages
 
 : make-sender ( method function -- quot )
@@ -104,7 +104,7 @@ MACRO: (send) ( selector super? -- quot )
 : method-arg-type ( method i -- type )
     f <void*> 0 <int> over
     >r method_getArgumentInfo drop
-    r> *char* ;
+    r> *void* ascii alien>string ;
 
 SYMBOL: objc>alien-types
 
index 48f45f21c0e3ac28a4e9f8b0dad6945d1ecd6931..6b3e1d330ee155b3ecbd0482806d33e90f9577c9 100755 (executable)
@@ -1,14 +1,15 @@
 ! Copyright (C) 2006, 2008 Slava Pestov
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien alien.c-types arrays assocs combinators compiler
-hashtables kernel libc math namespaces parser sequences words
-cocoa.messages cocoa.runtime compiler.units ;
+USING: alien alien.c-types alien.strings arrays assocs
+combinators compiler hashtables kernel libc math namespaces
+parser sequences words cocoa.messages cocoa.runtime
+compiler.units io.encodings.ascii ;
 IN: cocoa.subclassing
 
 : init-method ( method alien -- )
     >r first3 r>
     [ >r execute r> set-objc-method-imp ] keep
-    [ >r malloc-char-string r> set-objc-method-types ] keep
+    [ >r ascii malloc-string r> set-objc-method-types ] keep
     >r sel_registerName r> set-objc-method-name ;
 
 : <empty-method-list> ( n -- alien )
@@ -26,7 +27,7 @@ IN: cocoa.subclassing
 : <objc-class> ( name info -- class )
     "objc-class" malloc-object
     [ set-objc-class-info ] keep
-    [ >r malloc-char-string r> set-objc-class-name ] keep ;
+    [ >r ascii malloc-string r> set-objc-class-name ] keep ;
 
 : <protocol-list> ( name -- protocol-list )
     "objc-protocol-list" malloc-object
diff --git a/extra/columns/authors.txt b/extra/columns/authors.txt
new file mode 100644 (file)
index 0000000..a44f8d7
--- /dev/null
@@ -0,0 +1,2 @@
+Slava Pestov
+Daniel Ehrenberg
diff --git a/extra/columns/columns-docs.factor b/extra/columns/columns-docs.factor
new file mode 100644 (file)
index 0000000..a2f0ccc
--- /dev/null
@@ -0,0 +1,26 @@
+USING: help.markup help.syntax sequences ;
+IN: columns
+
+ARTICLE: "columns" "Column sequences"
+"A " { $emphasis "column" } " presents a column of a matrix represented as a sequence of rows:"
+{ $subsection column }
+{ $subsection <column> } ;
+
+HELP: column
+{ $class-description "A virtual sequence which presents a fixed column of a matrix represented as a sequence of rows. New instances can be created by calling " { $link <column> } "." } ;
+
+HELP: <column> ( seq n -- column )
+{ $values { "seq" sequence } { "n" "a non-negative integer" } { "column" column } }
+{ $description "Outputs a new virtual sequence which presents a fixed column of a matrix represented as a sequence of rows." "The " { $snippet "i" } "th element of a column is the " { $snippet "n" } "th element of the " { $snippet "i" } "th element of" { $snippet "seq" } ". Every element of " { $snippet "seq" } " must be a sequence, and all sequences must have equal length." }
+{ $examples
+    { $example
+        "USING: arrays prettyprint columns ;"
+        "{ { 1 2 3 } { 4 5 6 } { 7 8 9 } } 0 <column> >array ."
+        "{ 1 4 7 }"
+    }
+}
+{ $notes
+    "In the same sense that " { $link <reversed> } " is a virtual variant of " { $link reverse } ", " { $link <column> } " is a virtual variant of " { $snippet "swap [ nth ] curry map" } "."
+} ;
+
+ABOUT: "columns"
diff --git a/extra/columns/columns-tests.factor b/extra/columns/columns-tests.factor
new file mode 100644 (file)
index 0000000..657b9e0
--- /dev/null
@@ -0,0 +1,9 @@
+IN: columns.tests
+USING: columns sequences kernel namespaces arrays tools.test math ;
+
+! Columns
+{ { 1 2 3 } { 4 5 6 } { 7 8 9 } } [ clone ] map "seq" set
+
+[ { 1 4 7 } ] [ "seq" get 0 <column> >array ] unit-test
+[ ] [ "seq" get 1 <column> [ sq ] change-each ] unit-test
+[ { 4 25 64 } ] [ "seq" get 1 <column> >array ] unit-test
diff --git a/extra/columns/columns.factor b/extra/columns/columns.factor
new file mode 100644 (file)
index 0000000..7e4a7fd
--- /dev/null
@@ -0,0 +1,15 @@
+! Copyright (C) 2005, 2008 Slava Pestov, Daniel Ehrenberg.
+! See http://factorcode.org/license.txt for BSD license.
+USING: sequences kernel accessors ;
+IN: columns
+
+! A column of a matrix
+TUPLE: column seq col ;
+
+C: <column> column
+
+M: column virtual-seq seq>> ;
+M: column virtual@ dup col>> -rot seq>> nth bounds-check ;
+M: column length seq>> length ;
+
+INSTANCE: column virtual-sequence
diff --git a/extra/columns/summary.txt b/extra/columns/summary.txt
new file mode 100644 (file)
index 0000000..c4ade7f
--- /dev/null
@@ -0,0 +1 @@
+Virtual sequence view of a matrix column
diff --git a/extra/columns/tags.txt b/extra/columns/tags.txt
new file mode 100644 (file)
index 0000000..42d711b
--- /dev/null
@@ -0,0 +1 @@
+collections
index 77ad30ad8ff4acdbc4793d1795f8183c569e3f9b..a4bd24ccca94b602ab43a814d6a32f17fba465e3 100644 (file)
@@ -1,6 +1,7 @@
 ! Copyright (C) 2006, 2008 Slava Pestov
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien alien.c-types alien.syntax kernel math sequences ;
+USING: alien alien.c-types alien.strings alien.syntax kernel
+math sequences io.encodings.utf16 ;
 IN: core-foundation
 
 TYPEDEF: void* CFAllocatorRef
@@ -31,7 +32,7 @@ FUNCTION: CFURLRef CFURLCreateWithString ( CFAllocatorRef allocator, CFStringRef
 
 FUNCTION: CFURLRef CFURLCopyFileSystemPath ( CFURLRef url, int pathStyle ) ;
 
-FUNCTION: CFStringRef CFStringCreateWithCharacters ( CFAllocatorRef allocator, ushort* cStr, CFIndex numChars ) ;
+FUNCTION: CFStringRef CFStringCreateWithCharacters ( CFAllocatorRef allocator, wchar_t* cStr, CFIndex numChars ) ;
 
 FUNCTION: CFIndex CFStringGetLength ( CFStringRef theString ) ;
 
@@ -57,7 +58,7 @@ FUNCTION: void CFRelease ( void* cf ) ;
 : CF>string ( alien -- string )
     dup CFStringGetLength 1+ "ushort" <c-array> [
         >r 0 over CFStringGetLength r> CFStringGetCharacters
-    ] keep alien>u16-string ;
+    ] keep utf16n alien>string ;
 
 : CF>string-array ( alien -- seq )
     CF>array [ CF>string ] map ;
index 3c9dbdbef021928e24871ecd6a6d481b07e06de9..67a4e59d04151ba90e840319da4a156efcbed380 100644 (file)
@@ -1,8 +1,9 @@
 ! Copyright (C) 2008 Slava Pestov
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien alien.c-types alien.syntax kernel math sequences
-namespaces assocs init accessors continuations combinators
-core-foundation core-foundation.run-loop ;
+USING: alien alien.c-types alien.strings alien.syntax kernel
+math sequences namespaces assocs init accessors continuations
+combinators core-foundation core-foundation.run-loop
+io.encodings.utf8 ;
 IN: core-foundation.fsevents
 
 ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
@@ -165,7 +166,7 @@ SYMBOL: event-stream-callbacks
 : >event-triple ( n eventPaths eventFlags eventIds -- triple )
     [
         >r >r >r dup dup
-        r> char*-nth ,
+        r> void*-nth utf8 alien>string ,
         r> int-nth ,
         r> longlong-nth ,
     ] { } make ;
index baf4e9db5acb7afdb654b1fb830f50ca1d3c4ca0..82193ed4678c460159785e7555b84491d394de27 100755 (executable)
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays assocs classes continuations kernel math
 namespaces sequences sequences.lib classes.tuple words strings
-tools.walker accessors ;
+tools.walker accessors combinators.lib ;
 IN: db
 
 TUPLE: db
@@ -11,7 +11,7 @@ TUPLE: db
     update-statements
     delete-statements ;
 
-: construct-db ( class -- obj )
+: new-db ( class -- obj )
     new
         H{ } clone >>insert-statements
         H{ } clone >>update-statements
@@ -20,7 +20,7 @@ TUPLE: db
 GENERIC: make-db* ( seq class -- db )
 
 : make-db ( seq class -- db )
-    construct-db make-db* ;
+    new-db make-db* ;
 
 GENERIC: db-open ( db -- db )
 HOOK: db-close db ( handle -- )
@@ -36,17 +36,25 @@ HOOK: db-close db ( handle -- )
     ] with-variable ;
 
 ! TUPLE: sql sql in-params out-params ;
-TUPLE: statement handle sql in-params out-params bind-params bound? ;
+TUPLE: statement handle sql in-params out-params bind-params bound? type ;
 TUPLE: simple-statement < statement ;
 TUPLE: prepared-statement < statement ;
-TUPLE: nonthrowable-statement < statement ;
-TUPLE: throwable-statement < statement ;
+
+SINGLETON: throwable
+SINGLETON: nonthrowable
+
+: make-throwable ( obj -- obj' )
+    dup sequence? [
+        [ make-throwable ] map
+    ] [
+        throwable >>type
+    ] if ;
 
 : make-nonthrowable ( obj -- obj' )
     dup sequence? [
         [ make-nonthrowable ] map
     ] [
-        nonthrowable-statement construct-delegate
+        nonthrowable >>type
     ] if ;
 
 TUPLE: result-set sql in-params out-params handle n max ;
@@ -55,12 +63,14 @@ TUPLE: result-set sql in-params out-params handle n max ;
     new
         swap >>out-params
         swap >>in-params
-        swap >>sql ;
+        swap >>sql
+        throwable >>type ;
 
 HOOK: <simple-statement> db ( str in out -- statement )
 HOOK: <prepared-statement> db ( str in out -- statement )
 GENERIC: prepare-statement ( statement -- )
 GENERIC: bind-statement* ( statement -- )
+GENERIC: low-level-bind ( statement -- )
 GENERIC: bind-tuple ( tuple statement -- )
 GENERIC: query-results ( query -- result-set )
 GENERIC: #rows ( result-set -- n )
@@ -70,20 +80,19 @@ GENERIC# row-column-typed 1 ( result-set column -- sql )
 GENERIC: advance-row ( result-set -- )
 GENERIC: more-rows? ( result-set -- ? )
 
-GENERIC: execute-statement ( statement -- )
+GENERIC: execute-statement* ( statement type -- )
 
-M: throwable-statement execute-statement ( statement -- )
-    dup sequence? [
-        [ execute-statement ] each
-    ] [
-        query-results dispose
-    ] if ;
+M: throwable execute-statement* ( statement type -- )
+    drop query-results dispose ;
+
+M: nonthrowable execute-statement* ( statement type -- )
+    drop [ query-results dispose ] [ 2drop ] recover ;
 
-M: nonthrowable-statement execute-statement ( statement -- )
+: execute-statement ( statement -- )
     dup sequence? [
         [ execute-statement ] each
     ] [
-        [ query-results dispose ] [ 2drop ] recover
+        dup type>> execute-statement*
     ] if ;
 
 : bind-statement ( obj statement -- )
index bfe7dab3ce21344abfe35aebd62c9d2d72303ddb..d270e6f40d8ea6a7a2fa4c67e03f4bfdbac5b179 100755 (executable)
@@ -4,8 +4,8 @@ USING: arrays continuations db io kernel math namespaces
 quotations sequences db.postgresql.ffi alien alien.c-types
 db.types tools.walker ascii splitting math.parser combinators
 libc shuffle calendar.format byte-arrays destructors prettyprint
-accessors strings serialize io.encodings.binary
-io.streams.byte-array ;
+accessors strings serialize io.encodings.binary io.encodings.utf8
+alien.strings io.streams.byte-array inspector ;
 IN: db.postgresql.lib
 
 : postgresql-result-error-message ( res -- str/f )
@@ -23,12 +23,18 @@ IN: db.postgresql.lib
     "\n" split [ [ blank? ] trim ] map "\n" join ;
 
 : postgresql-error-message ( -- str )
-    db get db-handle (postgresql-error-message) ;
+    db get handle>> (postgresql-error-message) ;
 
 : postgresql-error ( res -- res )
     dup [ postgresql-error-message throw ] unless ;
 
-: postgresql-result-ok? ( n -- ? )
+ERROR: postgresql-result-null ;
+
+M: postgresql-result-null summary ( obj -- str )
+    drop "PQexec returned f." ;
+
+: postgresql-result-ok? ( res -- ? )
+    [ postgresql-result-null ] unless*
     PQresultStatus
     PGRES_COMMAND_OK PGRES_TUPLES_OK 2array member? ;
 
@@ -37,8 +43,8 @@ IN: db.postgresql.lib
     dup PQstatus zero? [ (postgresql-error-message) throw ] unless ;
 
 : do-postgresql-statement ( statement -- res )
-    db get db-handle swap statement-sql PQexec dup postgresql-result-ok? [
-        dup postgresql-result-error-message swap PQclear throw
+    db get handle>> swap sql>> PQexec dup postgresql-result-ok? [
+        [ postgresql-result-error-message ] [ PQclear ] bi throw
     ] unless ;
 
 : type>oid ( symbol -- n )
@@ -58,28 +64,22 @@ IN: db.postgresql.lib
     } case ;
 
 : param-types ( statement -- seq )
-    statement-in-params
-    [ sql-spec-type type>oid ] map
-    >c-uint-array ;
+    in-params>> [ type>> type>oid ] map >c-uint-array ;
 
 : malloc-byte-array/length
     [ malloc-byte-array dup free-always ] [ length ] bi ;
-    
 
 : param-values ( statement -- seq seq2 )
-    [ statement-bind-params ]
-    [ statement-in-params ] bi
+    [ bind-params>> ] [ in-params>> ] bi
     [
-        sql-spec-type {
+        >r value>> r> type>> {
             { FACTOR-BLOB [
-                dup [
-                    object>bytes
-                    malloc-byte-array/length ] [ 0 ] if ] }
-            { BLOB [
-                dup [ malloc-byte-array/length ] [ 0 ] if ] }
+                dup [ object>bytes malloc-byte-array/length ] [ 0 ] if
+            ] }
+            { BLOB [ dup [ malloc-byte-array/length ] [ 0 ] if ] }
             [
                 drop number>string* dup [
-                    malloc-char-string dup free-always
+                    utf8 malloc-string dup free-always
                 ] when 0
             ]
         } case 2array
@@ -90,22 +90,20 @@ IN: db.postgresql.lib
     ] if ;
 
 : param-formats ( statement -- seq )
-    statement-in-params
-    [ sql-spec-type type>param-format ] map
-    >c-uint-array ;
+    in-params>> [ type>> type>param-format ] map >c-uint-array ;
 
 : do-postgresql-bound-statement ( statement -- res )
     [
-        >r db get db-handle r>
+        >r db get handle>> r>
         {
-            [ statement-sql ]
-            [ statement-bind-params length ]
+            [ sql>> ]
+            [ bind-params>> length ]
             [ param-types ]
             [ param-values ]
             [ param-formats ]
         } cleave
         0 PQexecParams dup postgresql-result-ok? [
-            dup postgresql-result-error-message swap PQclear throw
+            [ postgresql-result-error-message ] [ PQclear ] bi throw
         ] unless
     ] with-destructors ;
 
@@ -113,8 +111,8 @@ IN: db.postgresql.lib
     PQgetisnull 1 = ;
 
 : pq-get-string ( handle row column -- obj )
-    3dup PQgetvalue alien>char-string
-    dup "" = [ >r pq-get-is-null f r> ? ] [ 3nip ] if ;
+    3dup PQgetvalue utf8 alien>string
+    dup empty? [ >r pq-get-is-null f r> ? ] [ 3nip ] if ;
 
 : pq-get-number ( handle row column -- obj )
     pq-get-string dup [ string>number ] when ;
@@ -152,6 +150,7 @@ M: postgresql-malloc-destructor dispose ( obj -- )
     dup array? [ first ] when
     {
         { +native-id+ [ pq-get-number ] }
+        { +random-id+ [ pq-get-number ] }
         { INTEGER [ pq-get-number ] }
         { BIG-INTEGER [ pq-get-number ] }
         { DOUBLE [ pq-get-number ] }
@@ -167,4 +166,3 @@ M: postgresql-malloc-destructor dispose ( obj -- )
             dup [ bytes>object ] when ] }
         [ no-sql-type ]
     } case ;
-    ! PQgetlength PQgetisnull
index 322143e7a2f1535b382974b05917d2b76f2028ec..687146af11db5d8f7dd4918979cb0af95d322c63 100755 (executable)
@@ -5,19 +5,16 @@ kernel math math.parser namespaces prettyprint quotations
 sequences debugger db db.postgresql.lib db.postgresql.ffi
 db.tuples db.types tools.annotations math.ranges
 combinators sequences.lib classes locals words tools.walker
-namespaces.lib accessors ;
+namespaces.lib accessors random db.queries ;
 IN: db.postgresql
 
 TUPLE: postgresql-db < db
     host port pgopts pgtty db user pass ;
 
-TUPLE: postgresql-statement < throwable-statement ;
+TUPLE: postgresql-statement < statement ;
 
 TUPLE: postgresql-result-set < result-set ;
 
-: <postgresql-statement> ( statement in out -- postgresql-statement )
-    postgresql-statement construct-statement ;
-
 M: postgresql-db make-db* ( seq tuple -- db )
     >r first4 r>
         swap >>db
@@ -42,11 +39,21 @@ M: postgresql-db dispose ( db -- )
 M: postgresql-statement bind-statement* ( statement -- )
     drop ;
 
+GENERIC: postgresql-bind-conversion ( tuple obj -- low-level-binding )
+
+M: sql-spec postgresql-bind-conversion ( tuple spec -- obj )
+    slot-name>> swap get-slot-named <low-level-binding> ;
+
+M: literal-bind postgresql-bind-conversion ( tuple literal-bind -- obj )
+    nip value>> <low-level-binding> ;
+
+M: generator-bind postgresql-bind-conversion ( tuple generate-bind -- obj )
+    nip singleton>> eval-generator <low-level-binding> ;
+
 M: postgresql-statement bind-tuple ( tuple statement -- )
-    [
-        statement-in-params
-        [ sql-spec-slot-name swap get-slot-named ] with map
-    ] keep set-statement-bind-params ;
+    tuck in-params>>
+    [ postgresql-bind-conversion ] with map
+    >>bind-params drop ;
 
 M: postgresql-result-set #rows ( result-set -- n )
     handle>> PQntuples ;
@@ -54,15 +61,18 @@ M: postgresql-result-set #rows ( result-set -- n )
 M: postgresql-result-set #columns ( result-set -- n )
     handle>> PQnfields ;
 
+: result-handle-n ( result-set -- handle n )
+    [ handle>> ] [ n>> ] bi ;
+
 M: postgresql-result-set row-column ( result-set column -- obj )
-    >r dup result-set-handle swap result-set-n r> pq-get-string ;
+    >r result-handle-n r> pq-get-string ;
 
 M: postgresql-result-set row-column-typed ( result-set column -- obj )
-    dup pick result-set-out-params nth sql-spec-type
-    >r >r [ result-set-handle ] [ result-set-n ] bi r> r> postgresql-column-typed ;
+    dup pick out-params>> nth type>>
+    >r >r result-handle-n r> r> postgresql-column-typed ;
 
 M: postgresql-statement query-results ( query -- result-set )
-    dup statement-bind-params [
+    dup bind-params>> [
         over [ bind-statement ] keep
         do-postgresql-bound-statement
     ] [
@@ -72,67 +82,56 @@ M: postgresql-statement query-results ( query -- result-set )
     dup init-result-set ;
 
 M: postgresql-result-set advance-row ( result-set -- )
-    dup result-set-n 1+ swap set-result-set-n ;
+    [ 1+ ] change-n drop ;
 
 M: postgresql-result-set more-rows? ( result-set -- ? )
-    dup result-set-n swap result-set-max < ;
+    [ n>> ] [ max>> ] bi < ;
 
 M: postgresql-statement dispose ( query -- )
-    dup statement-handle PQclear
-    f swap set-statement-handle ;
+    dup handle>> PQclear
+    f >>handle drop ;
 
 M: postgresql-result-set dispose ( result-set -- )
-    dup result-set-handle PQclear
-    0 0 f roll {
-        set-result-set-n set-result-set-max set-result-set-handle
-    } set-slots ;
+    [ handle>> PQclear ]
+    [
+        0 >>n
+        0 >>max
+        f >>handle drop
+    ] bi ;
 
 M: postgresql-statement prepare-statement ( statement -- )
-    [
-        >r db get handle>> "" r>
-        dup statement-sql swap statement-in-params
-        length f PQprepare postgresql-error
-    ] keep set-statement-handle ;
+    dup
+    >r db get handle>> f r>
+    [ sql>> ] [ in-params>> ] bi
+    length f PQprepare postgresql-error
+    >>handle drop ;
 
 M: postgresql-db <simple-statement> ( sql in out -- statement )
-    <postgresql-statement> ;
+    postgresql-statement construct-statement ;
 
 M: postgresql-db <prepared-statement> ( sql in out -- statement )
-    <postgresql-statement> dup prepare-statement ;
-
-M: postgresql-db begin-transaction ( -- )
-    "BEGIN" sql-command ;
+    <simple-statement> dup prepare-statement ;
 
-M: postgresql-db commit-transaction ( -- )
-    "COMMIT" sql-command ;
-
-M: postgresql-db rollback-transaction ( -- )
-    "ROLLBACK" sql-command ;
-
-SYMBOL: postgresql-counter
 : bind-name% ( -- )
     CHAR: $ 0,
-    postgresql-counter [ inc ] keep get 0# ;
+    sql-counter [ inc ] [ get 0# ] bi ;
 
 M: postgresql-db bind% ( spec -- )
-    1, bind-name% ;
+    bind-name% 1, ;
 
-: postgresql-make ( class quot -- )
-    >r sql-props r>
-    [ postgresql-counter off call ] { "" { } { } } nmake
-    <postgresql-statement> ; inline
+M: postgresql-db bind# ( spec obj -- )
+    >r bind-name% f swap type>> r> <literal-bind> 1, ;
 
 : create-table-sql ( class -- statement )
     [
         "create table " 0% 0%
-        "(" 0%
-        [ ", " 0% ] [
-            dup sql-spec-column-name 0%
+        "(" 0% [ ", " 0% ] [
+            dup column-name>> 0%
             " " 0%
-            dup sql-spec-type t lookup-type 0%
+            dup type>> lookup-create-type 0%
             modifiers 0%
         ] interleave ");" 0%
-    ] postgresql-make ;
+    ] query-make ;
 
 : create-function-sql ( class -- statement )
     [
@@ -141,7 +140,7 @@ M: postgresql-db bind% ( spec -- )
         "(" 0%
         over [ "," 0% ]
         [
-            sql-spec-type f lookup-type 0%
+            type>> lookup-type 0%
         ] interleave
         ")" 0%
         " returns bigint as '" 0%
@@ -149,12 +148,12 @@ M: postgresql-db bind% ( spec -- )
         "insert into " 0%
         dup 0%
         "(" 0%
-        over [ ", " 0% ] [ sql-spec-column-name 0% ] interleave
+        over [ ", " 0% ] [ column-name>> 0% ] interleave
         ") values(" 0%
         swap [ ", " 0% ] [ drop bind-name% ] interleave
         "); " 0%
         "select currval(''" 0% 0% "_id_seq'');' language sql;" 0%
-    ] postgresql-make ;
+    ] query-make ;
 
 M: postgresql-db create-sql-statement ( class -- seq )
     [
@@ -168,14 +167,14 @@ M: postgresql-db create-sql-statement ( class -- seq )
         "drop function add_" 0% 0%
         "(" 0%
         remove-id
-        [ ", " 0% ] [ sql-spec-type f lookup-type 0% ] interleave
+        [ ", " 0% ] [ type>> lookup-type 0% ] interleave
         ");" 0%
-    ] postgresql-make ;
+    ] query-make ;
 
 : drop-table-sql ( table -- statement )
     [
         "drop table " 0% 0% ";" 0% drop
-    ] postgresql-make ;
+    ] query-make ;
 
 M: postgresql-db drop-sql-statement ( class -- seq )
     [
@@ -192,107 +191,69 @@ M: postgresql-db <insert-native-statement> ( class -- statement )
         remove-id
         [ ", " 0% ] [ bind% ] interleave
         ");" 0%
-    ] postgresql-make ;
+    ] query-make ;
 
 M: postgresql-db <insert-nonnative-statement> ( class -- statement )
     [
         "insert into " 0% 0%
         "(" 0%
-        dup [ ", " 0% ] [ sql-spec-column-name 0% ] interleave
+        dup [ ", " 0% ] [ column-name>> 0% ] interleave
         ")" 0%
 
         " values(" 0%
-        [ ", " 0% ] [ bind% ] interleave
+        [ ", " 0% ] [
+            dup type>> +random-id+ = [
+                [
+                    drop bind-name%
+                    f random-id-generator
+                ] [ type>> ] bi <generator-bind> 1,
+            ] [
+                bind%
+            ] if
+        ] interleave
         ");" 0%
-    ] postgresql-make ;
+    ] query-make ;
 
 M: postgresql-db insert-tuple* ( tuple statement -- )
     query-modify-tuple ;
 
-M: postgresql-db <update-tuple-statement> ( class -- statement )
-    [
-        "update " 0% 0%
-        " set " 0%
-        dup remove-id
-        [ ", " 0% ]
-        [ dup sql-spec-column-name 0% " = " 0% bind% ] interleave
-        " where " 0%
-        find-primary-key
-        dup sql-spec-column-name 0% " = " 0% bind%
-    ] postgresql-make ;
-
-M: postgresql-db <delete-tuple-statement> ( class -- statement )
-    [
-        "delete from " 0% 0%
-        " where " 0%
-        find-primary-key
-        dup sql-spec-column-name 0% " = " 0% bind%
-    ] postgresql-make ;
-
-M: postgresql-db <select-by-slots-statement> ( tuple class -- statement )
-    [
-    ! tuple columns table
-        "select " 0%
-        over [ ", " 0% ]
-        [ dup sql-spec-column-name 0% 2, ] interleave
-
-        " from " 0% 0%
-        [ sql-spec-slot-name swap get-slot-named ] with subset
-        dup empty? [
-            drop
-        ] [
-            " where " 0%
-            [ " and " 0% ]
-            [ dup sql-spec-column-name 0% " = " 0% bind% ] interleave
-        ] if ";" 0%
-    ] postgresql-make ;
-
-M: postgresql-db type-table ( -- hash )
+M: postgresql-db persistent-table ( -- hashtable )
     H{
-        { +native-id+ "integer" }
-        { TEXT "text" }
-        { VARCHAR "varchar" }
-        { INTEGER "integer" }
-        { DOUBLE "real" }
-        { DATE "date" }
-        { TIME "time" }
-        { DATETIME "timestamp" }
-        { TIMESTAMP "timestamp" }
-        { BLOB "bytea" }
-        { FACTOR-BLOB "bytea" }
+        { +native-id+ { "integer" "serial primary key" f } }
+        { +assigned-id+ { f f "primary key" } }
+        { +random-id+ { "bigint" "bigint primary key" f } }
+        { TEXT { "text" "text" f } }
+        { VARCHAR { "varchar" "varchar" f } }
+        { INTEGER { "integer" "integer" f } }
+        { BIG-INTEGER { "bigint" "bigint" f } }
+        { UNSIGNED-BIG-INTEGER { "bigint" "bigint" f } }
+        { SIGNED-BIG-INTEGER { "bigint" "bigint" f } }
+        { DOUBLE { "real" "real" f } }
+        { DATE { "date" "date" f } }
+        { TIME { "time" "time" f } }
+        { DATETIME { "timestamp" "timestamp" f } }
+        { TIMESTAMP { "timestamp" "timestamp" f } }
+        { BLOB { "bytea" "bytea" f } }
+        { FACTOR-BLOB { "bytea" "bytea" f } }
+        { +foreign-id+ { f f "references" } }
+        { +autoincrement+ { f f "autoincrement" } }
+        { +unique+ { f f "unique" } }
+        { +default+ { f f "default" } }
+        { +null+ { f f "null" } }
+        { +not-null+ { f f "not null" } }
+        { system-random-generator { f f f } }
+        { secure-random-generator { f f f } }
+        { random-generator { f f f } }
     } ;
 
-M: postgresql-db create-type-table ( -- hash )
-    H{
-        { +native-id+ "serial primary key" }
-    } ;
-
-: postgresql-compound ( str n -- newstr )
+M: postgresql-db compound ( str obj -- str' )
     over {
         { "default" [ first number>string join-space ] }
         { "varchar" [ first number>string paren append ] }
         { "references" [
                 first2 >r [ unparse join-space ] keep db-columns r>
-                swap [ sql-spec-slot-name = ] with find nip
-                sql-spec-column-name paren append
+                swap [ slot-name>> = ] with find nip
+                column-name>> paren append
             ] }
         [ "no compound found" 3array throw ]
     } case ;
-
-M: postgresql-db compound-modifier ( str seq -- newstr )
-    postgresql-compound ;
-    
-M: postgresql-db modifier-table ( -- hashtable )
-    H{
-        { +native-id+ "primary key" }
-        { +assigned-id+ "primary key" }
-        { +foreign-id+ "references" }
-        { +autoincrement+ "autoincrement" }
-        { +unique+ "unique" }
-        { +default+ "default" }
-        { +null+ "null" }
-        { +not-null+ "not null" }
-    } ;
-
-M: postgresql-db compound-type ( str n -- newstr )
-    postgresql-compound ;
diff --git a/extra/db/queries/queries.factor b/extra/db/queries/queries.factor
new file mode 100644 (file)
index 0000000..c9fd9a3
--- /dev/null
@@ -0,0 +1,100 @@
+! Copyright (C) 2008 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors kernel math namespaces sequences random
+strings
+math.bitfields.lib namespaces.lib db db.tuples db.types
+math.intervals ;
+IN: db.queries
+
+GENERIC: where ( specs obj -- )
+
+: maybe-make-retryable ( statement -- statement )
+    dup in-params>> [ generator-bind? ] contains? [
+        make-retryable
+    ] when ;
+
+: query-make ( class quot -- )
+    >r sql-props r>
+    [ 0 sql-counter rot with-variable ] { "" { } { } } nmake
+    <simple-statement> maybe-make-retryable ; inline
+
+M: db begin-transaction ( -- ) "BEGIN" sql-command ;
+M: db commit-transaction ( -- ) "COMMIT" sql-command ;
+M: db rollback-transaction ( -- ) "ROLLBACK" sql-command ;
+
+: where-primary-key% ( specs -- )
+    " where " 0%
+    find-primary-key dup column-name>> 0% " = " 0% bind% ;
+
+M: db <update-tuple-statement> ( class -- statement )
+    [
+        "update " 0% 0%
+        " set " 0%
+        dup remove-id
+        [ ", " 0% ] [ dup column-name>> 0% " = " 0% bind% ] interleave
+        where-primary-key%
+    ] query-make ;
+
+M: db <delete-tuple-statement> ( specs table -- sql )
+    [
+        "delete from " 0% 0%
+        " where " 0%
+        find-primary-key
+        dup column-name>> 0% " = " 0% bind%
+    ] query-make ;
+
+M: random-id-generator eval-generator ( singleton -- obj )
+    drop
+    system-random-generator get [
+        63 [ 2^ random ] keep 1 - set-bit
+    ] with-random ;
+
+: interval-comparison ( ? str -- str )
+    "from" = " >" " <" ? swap [ "= " append ] when ;
+
+: where-interval ( spec obj from/to -- )
+    pick column-name>> 0%
+    >r first2 r> interval-comparison 0%
+    bind# ;
+
+: in-parens ( quot -- )
+    "(" 0% call ")" 0% ; inline
+
+M: interval where ( spec obj -- )
+    [
+        [ from>> "from" where-interval " and " 0% ]
+        [ to>> "to" where-interval ] 2bi
+    ] in-parens ;
+
+M: sequence where ( spec obj -- )
+    [
+        [ " or " 0% ] [ dupd where ] interleave drop
+    ] in-parens ;
+
+: object-where ( spec obj -- )
+    over column-name>> 0% " = " 0% bind# ;
+
+M: object where ( spec obj -- ) object-where ;
+
+M: integer where ( spec obj -- ) object-where ;
+
+M: string where ( spec obj -- ) object-where ;
+
+: where-clause ( tuple specs -- )
+    " where " 0% [
+        " and " 0%
+    ] [
+        2dup slot-name>> swap get-slot-named where
+    ] interleave drop ;
+
+M: db <select-by-slots-statement> ( tuple class -- statement )
+    [
+        "select " 0%
+        over [ ", " 0% ]
+        [ dup column-name>> 0% 2, ] interleave
+
+        " from " 0% 0%
+        dupd
+        [ slot-name>> swap get-slot-named ] with subset
+        dup empty? [ 2drop ] [ where-clause ] if ";" 0%
+    ] query-make ;
index 488026fcc7c989402ac9f0cc3a60da642bed63ec..cab7b83ced9c6981a37e213e9630901459db413e 100644 (file)
@@ -1,7 +1,7 @@
 USING: kernel namespaces db.sql sequences math ;
 IN: db.sql.tests
 
-TUPLE: person name age ;
+TUPLE: person name age ;
 : insert-1
     { insert
         { table "person" }
@@ -28,7 +28,7 @@ TUPLE: person name age ;
                     { select
                         { columns "salary" }
                         { from "staff" }
-                        { where { "branchno" "b003" } }
+                        { where { "branchno" "b003" } }
                     }
                 }
                 { "branchno" > 3 } }
index 26e8429efdbb90def0395abc71d461b2318747a5..4561424a9dc21b692579435452acd7a23a7de865 100755 (executable)
@@ -27,27 +27,27 @@ DEFER: sql%
 : sql-array% ( array -- )
     unclip
     {
-        { columns [ "," (sql-interleave) ] }
-        { from [ "from" "," sql-interleave ] }
-        { where [ "where" "and" sql-interleave ] }
-        { group-by [ "group by" "," sql-interleave ] }
-        { having [ "having" "," sql-interleave ] }
-        { order-by [ "order by" "," sql-interleave ] }
-        { offset [ "offset" sql% sql% ] }
-        { limit [ "limit" sql% sql% ] }
-        { select [ "(select" sql% sql% ")" sql% ] }
-        { table [ sql% ] }
-        { set [ "set" "," sql-interleave ] }
-        { values [ "values(" sql% "," (sql-interleave) ")" sql% ] }
-        { count [ "count" sql-function, ] }
-        { sum [ "sum" sql-function, ] }
-        { avg [ "avg" sql-function, ] }
-        { min [ "min" sql-function, ] }
-        { max [ "max" sql-function, ] }
+        { columns [ "," (sql-interleave) ] }
+        { from [ "from" "," sql-interleave ] }
+        { where [ "where" "and" sql-interleave ] }
+        { group-by [ "group by" "," sql-interleave ] }
+        { having [ "having" "," sql-interleave ] }
+        { order-by [ "order by" "," sql-interleave ] }
+        { offset [ "offset" sql% sql% ] }
+        { limit [ "limit" sql% sql% ] }
+        { select [ "(select" sql% sql% ")" sql% ] }
+        { table [ sql% ] }
+        { set [ "set" "," sql-interleave ] }
+        { values [ "values(" sql% "," (sql-interleave) ")" sql% ] }
+        { count [ "count" sql-function, ] }
+        { sum [ "sum" sql-function, ] }
+        { avg [ "avg" sql-function, ] }
+        { min [ "min" sql-function, ] }
+        { max [ "max" sql-function, ] }
         [ sql% [ sql% ] each ]
     } case ;
 
-TUPLE: no-sql-match ;
+ERROR: no-sql-match ;
 : sql% ( obj -- )
     {
         { [ dup string? ] [ " " 0% 0% ] }
@@ -55,15 +55,18 @@ TUPLE: no-sql-match ;
         { [ dup number? ] [ number>string sql% ] }
         { [ dup symbol? ] [ unparse sql% ] }
         { [ dup word? ] [ unparse sql% ] }
-        [ T{ no-sql-match } throw ]
+        { [ dup quotation? ] [ call ] }
+        [ no-sql-match ]
     } cond ;
 
 : parse-sql ( obj -- sql in-spec out-spec in out )
     [
         unclip {
-            { insert [ "insert into" sql% ] }
-            { update [ "update" sql% ] }
-            { delete [ "delete" sql% ] }
-            { select [ "select" sql% ] }
+            { \ create [ "create table" sql% ] }
+            { \ drop [ "drop table" sql% ] }
+            { \ insert [ "insert into" sql% ] }
+            { \ update [ "update" sql% ] }
+            { \ delete [ "delete" sql% ] }
+            { \ select [ "select" sql% ] }
         } case [ sql% ] each
     ] { "" { } { } { } { } } nmake ;
index c724025874f5d79be4f10f852eaba0ecf05834ff..b443f53e78adf08b15183183280e87702de89575 100755 (executable)
@@ -3,7 +3,7 @@
 ! An interface to the sqlite database. Tested against sqlite v3.1.3.
 ! Not all functions have been wrapped.
 USING: alien compiler kernel math namespaces sequences strings alien.syntax
-    system combinators ;
+    system combinators alien.c-types ;
 IN: db.sqlite.ffi
 
 << "sqlite" {
@@ -109,23 +109,31 @@ FUNCTION: int sqlite3_open ( char* filename, void* ppDb ) ;
 FUNCTION: int sqlite3_close ( sqlite3* pDb ) ;
 FUNCTION: char* sqlite3_errmsg ( sqlite3* pDb ) ;
 FUNCTION: int sqlite3_prepare ( sqlite3* pDb, char* zSql, int nBytes, void* ppStmt, void* pzTail ) ;
+FUNCTION: int sqlite3_prepare_v2 ( sqlite3* pDb, char* zSql, int nBytes, void* ppStmt, void* pzTail ) ;
 FUNCTION: int sqlite3_finalize ( sqlite3_stmt* pStmt ) ;
 FUNCTION: int sqlite3_reset ( sqlite3_stmt* pStmt ) ;
 FUNCTION: int sqlite3_step ( sqlite3_stmt* pStmt ) ;
-FUNCTION: sqlite3_int64 sqlite3_last_insert_rowid ( sqlite3* pStmt ) ;
+FUNCTION: sqlite3_uint64 sqlite3_last_insert_rowid ( sqlite3* pStmt ) ;
 FUNCTION: int sqlite3_bind_blob ( sqlite3_stmt* pStmt, int index, void* ptr, int len, int destructor ) ;
 FUNCTION: int sqlite3_bind_double ( sqlite3_stmt* pStmt, int index, double x ) ;
 FUNCTION: int sqlite3_bind_int ( sqlite3_stmt* pStmt, int index, int n ) ;
 FUNCTION: int sqlite3_bind_int64 ( sqlite3_stmt* pStmt, int index, sqlite3_int64 n ) ;
+: sqlite3-bind-uint64 ( pStmt index in64 -- int )
+    "int" "sqlite" "sqlite3_bind_int64"
+    { "sqlite3_stmt*" "int" "sqlite3_uint64" } alien-invoke ;
 FUNCTION: int sqlite3_bind_null ( sqlite3_stmt* pStmt, int n ) ;
 FUNCTION: int sqlite3_bind_text ( sqlite3_stmt* pStmt, int index, char* text, int len, int destructor ) ;
 FUNCTION: int sqlite3_bind_parameter_index ( sqlite3_stmt* pStmt, char* name ) ;
+FUNCTION: int sqlite3_clear_bindings ( sqlite3_stmt* pStmt ) ;
 FUNCTION: int sqlite3_column_count ( sqlite3_stmt* pStmt ) ;
 FUNCTION: void* sqlite3_column_blob ( sqlite3_stmt* pStmt, int col ) ;
 FUNCTION: int sqlite3_column_bytes ( sqlite3_stmt* pStmt, int col ) ;
 FUNCTION: char* sqlite3_column_decltype ( sqlite3_stmt* pStmt, int col ) ;
 FUNCTION: int sqlite3_column_int ( sqlite3_stmt* pStmt, int col ) ;
 FUNCTION: sqlite3_int64 sqlite3_column_int64 ( sqlite3_stmt* pStmt, int col ) ;
+: sqlite3-column-uint64 ( pStmt col -- uint64 )
+    "sqlite3_uint64" "sqlite" "sqlite3_column_int64"
+    { "sqlite3_stmt*" "int" } alien-invoke ;
 FUNCTION: double sqlite3_column_double ( sqlite3_stmt* pStmt, int col ) ;
 FUNCTION: char* sqlite3_column_name ( sqlite3_stmt* pStmt, int col ) ;
 FUNCTION: char* sqlite3_column_text ( sqlite3_stmt* pStmt, int col ) ;
index e66accd7e90f08369402b67066af85daf0d97660..e5562700c9bde928f8f63d0c911f99b431350b2a 100755 (executable)
@@ -4,7 +4,7 @@ USING: alien.c-types arrays assocs kernel math math.parser
 namespaces sequences db.sqlite.ffi db combinators
 continuations db.types calendar.format serialize
 io.streams.byte-array byte-arrays io.encodings.binary
-tools.walker ;
+tools.walker io.backend ;
 IN: db.sqlite.lib
 
 : sqlite-error ( n -- * )
@@ -23,7 +23,8 @@ IN: db.sqlite.lib
         [ sqlite-error ]
     } cond ;
 
-: sqlite-open ( filename -- db )
+: sqlite-open ( path -- db )
+    normalize-path
     "void*" <c-object>
     [ sqlite3_open sqlite-check-result ] keep *void* ;
 
@@ -51,6 +52,9 @@ IN: db.sqlite.lib
 : sqlite-bind-int64 ( handle i n -- )
     sqlite3_bind_int64 sqlite-check-result ;
 
+: sqlite-bind-uint64 ( handle i n -- )
+    sqlite3-bind-uint64 sqlite-check-result ;
+
 : sqlite-bind-double ( handle i x -- )
     sqlite3_bind_double sqlite-check-result ;
 
@@ -68,7 +72,10 @@ IN: db.sqlite.lib
     parameter-index sqlite-bind-int ;
 
 : sqlite-bind-int64-by-name ( handle name int64 -- )
-    parameter-index sqlite-bind-int ;
+    parameter-index sqlite-bind-int64 ;
+
+: sqlite-bind-uint64-by-name ( handle name int64 -- )
+    parameter-index sqlite-bind-uint64 ;
 
 : sqlite-bind-double-by-name ( handle name double -- )
     parameter-index sqlite-bind-double ;
@@ -85,6 +92,8 @@ IN: db.sqlite.lib
     {
         { INTEGER [ sqlite-bind-int-by-name ] }
         { BIG-INTEGER [ sqlite-bind-int64-by-name ] }
+        { SIGNED-BIG-INTEGER [ sqlite-bind-int64-by-name ] }
+        { UNSIGNED-BIG-INTEGER [ sqlite-bind-uint64-by-name ] }
         { TEXT [ sqlite-bind-text-by-name ] }
         { VARCHAR [ sqlite-bind-text-by-name ] }
         { DOUBLE [ sqlite-bind-double-by-name ] }
@@ -98,12 +107,15 @@ IN: db.sqlite.lib
             sqlite-bind-blob-by-name
         ] }
         { +native-id+ [ sqlite-bind-int-by-name ] }
+        { +random-id+ [ sqlite-bind-int64-by-name ] }
         { NULL [ sqlite-bind-null-by-name ] }
         [ no-sql-type ]
     } case ;
 
 : sqlite-finalize ( handle -- ) sqlite3_finalize sqlite-check-result ;
 : sqlite-reset ( handle -- ) sqlite3_reset sqlite-check-result ;
+: sqlite-clear-bindings ( handle -- )
+    sqlite3_clear_bindings sqlite-check-result ;
 : sqlite-#columns ( query -- int ) sqlite3_column_count ;
 : sqlite-column ( handle index -- string ) sqlite3_column_text ;
 : sqlite-column-name ( handle index -- string ) sqlite3_column_name ;
@@ -120,10 +132,12 @@ IN: db.sqlite.lib
 : sqlite-column-typed ( handle index type -- obj )
     dup array? [ first ] when
     {
-        { +native-id+ [ sqlite3_column_int64 ] }
-        { +random-id+ [ sqlite3_column_int64 ] }
+        { +native-id+ [ sqlite3_column_int64  ] }
+        { +random-id+ [ sqlite3-column-uint64 ] }
         { INTEGER [ sqlite3_column_int ] }
         { BIG-INTEGER [ sqlite3_column_int64 ] }
+        { SIGNED-BIG-INTEGER [ sqlite3_column_int64 ] }
+        { UNSIGNED-BIG-INTEGER [ sqlite3-column-uint64 ] }
         { DOUBLE [ sqlite3_column_double ] }
         { TEXT [ sqlite3_column_text ] }
         { VARCHAR [ sqlite3_column_text ] }
index 11c0150cd20b89729e5e9c2798aca346e61804c9..2407613eca9d710d1d113ae8d5ff1dd452e4f7a3 100755 (executable)
@@ -4,8 +4,10 @@ USING: alien arrays assocs classes compiler db
 hashtables io.files kernel math math.parser namespaces
 prettyprint sequences strings classes.tuple alien.c-types
 continuations db.sqlite.lib db.sqlite.ffi db.tuples
-words combinators.lib db.types combinators
-io namespaces.lib accessors ;
+words combinators.lib db.types combinators math.intervals
+io namespaces.lib accessors vectors math.ranges random
+math.bitfields.lib db.queries ;
+USE: tools.walker
 IN: db.sqlite
 
 TUPLE: sqlite-db < db path ;
@@ -19,7 +21,7 @@ M: sqlite-db db-open ( db -- db )
 M: sqlite-db db-close ( handle -- ) sqlite-close ;
 M: sqlite-db dispose ( db -- ) dispose-db ;
 
-TUPLE: sqlite-statement < throwable-statement ;
+TUPLE: sqlite-statement < statement ;
 
 TUPLE: sqlite-result-set < result-set has-more? ;
 
@@ -42,28 +44,48 @@ M: sqlite-statement dispose ( statement -- )
 M: sqlite-result-set dispose ( result-set -- )
     f >>handle drop ;
 
-: sqlite-bind ( triples handle -- )
-    swap [ first3 sqlite-bind-type ] with each ;
-
 : reset-statement ( statement -- )
     sqlite-maybe-prepare handle>> sqlite-reset ;
 
-M: sqlite-statement bind-statement* ( statement -- )
+: reset-bindings ( statement -- )
     sqlite-maybe-prepare
-    dup statement-bound? [ dup reset-statement ] when
+    handle>> [ sqlite3_reset drop ] [ sqlite3_clear_bindings drop ] bi ;
+
+M: sqlite-statement low-level-bind ( statement -- )
     [ statement-bind-params ] [ statement-handle ] bi
-    sqlite-bind ;
+    swap [ [ key>> ] [ value>> ] [ type>> ] tri sqlite-bind-type ] with each ;
+
+M: sqlite-statement bind-statement* ( statement -- )
+    sqlite-maybe-prepare
+    dup statement-bound? [ dup reset-bindings ] when
+    low-level-bind ;
+
+GENERIC: sqlite-bind-conversion ( tuple obj -- array )
+
+TUPLE: sqlite-low-level-binding < low-level-binding key type ;
+: <sqlite-low-level-binding> ( key value type -- obj )
+    sqlite-low-level-binding new
+        swap >>type
+        swap >>value
+        swap >>key ;
+
+M: sql-spec sqlite-bind-conversion ( tuple spec -- array )
+    [ column-name>> ":" prepend ]
+    [ slot-name>> rot get-slot-named ]
+    [ type>> ] tri <sqlite-low-level-binding> ;
+
+M: literal-bind sqlite-bind-conversion ( tuple literal-bind -- array )
+    nip [ key>> ] [ value>> ] [ type>> ] tri
+    <sqlite-low-level-binding> ;
+
+M: generator-bind sqlite-bind-conversion ( tuple generate-bind -- array )
+    nip [ key>> ] [ singleton>> eval-generator ] [ type>> ] tri
+    <sqlite-low-level-binding> ;
 
 M: sqlite-statement bind-tuple ( tuple statement -- )
     [
-        in-params>>
-        [
-            [ column-name>> ":" prepend ]
-            [ slot-name>> rot get-slot-named ]
-            [ type>> ] tri 3array
-        ] with map
-    ] keep
-    bind-statement ;
+        in-params>> [ sqlite-bind-conversion ] with map
+    ] keep bind-statement ;
 
 : last-insert-id ( -- id )
     db get db-handle sqlite3_last_insert_rowid
@@ -93,27 +115,19 @@ M: sqlite-statement query-results ( query -- result-set )
     dup handle>> sqlite-result-set construct-result-set
     dup advance-row ;
 
-M: sqlite-db begin-transaction ( -- ) "BEGIN" sql-command ;
-M: sqlite-db commit-transaction ( -- ) "COMMIT" sql-command ;
-M: sqlite-db rollback-transaction ( -- ) "ROLLBACK" sql-command ;
-
-: sqlite-make ( class quot -- )
-    >r sql-props r>
-    { "" { } { } } nmake <simple-statement> ; inline
-
 M: sqlite-db create-sql-statement ( class -- statement )
     [
         "create table " 0% 0%
         "(" 0% [ ", " 0% ] [
             dup column-name>> 0%
             " " 0%
-            dup type>> t lookup-type 0%
+            dup type>> lookup-create-type 0%
             modifiers 0%
         ] interleave ");" 0%
-    ] sqlite-make ;
+    ] query-make ;
 
 M: sqlite-db drop-sql-statement ( class -- statement )
-    [ "drop table " 0% 0% ";" 0% drop ] sqlite-make ;
+    [ "drop table " 0% 0% ";" 0% drop ] query-make ;
 
 M: sqlite-db <insert-native-statement> ( tuple -- statement )
     [
@@ -122,91 +136,62 @@ M: sqlite-db <insert-native-statement> ( tuple -- statement )
         maybe-remove-id
         dup [ ", " 0% ] [ column-name>> 0% ] interleave
         ") values(" 0%
-        [ ", " 0% ] [ bind% ] interleave
+        [ ", " 0% ] [
+            dup type>> +random-id+ = [
+                [
+                    column-name>> ":" prepend dup 0%
+                    random-id-generator
+                ] [ type>> ] bi <generator-bind> 1,
+            ] [
+                bind%
+            ] if
+        ] interleave
         ");" 0%
-    ] sqlite-make ;
+    ] query-make ;
 
 M: sqlite-db <insert-nonnative-statement> ( tuple -- statement )
     <insert-native-statement> ;
 
-: where-primary-key% ( specs -- )
-    " where " 0%
-    find-primary-key dup column-name>> 0% " = " 0% bind% ;
-
-: where-clause ( specs -- )
-    " where " 0%
-    [ " and " 0% ] [ dup column-name>> 0% " = " 0% bind% ] interleave ;
-
-M: sqlite-db <update-tuple-statement> ( class -- statement )
-    [
-        "update " 0%
-        0%
-        " set " 0%
-        dup remove-id
-        [ ", " 0% ] [ dup column-name>> 0% " = " 0% bind% ] interleave
-        where-primary-key%
-    ] sqlite-make ;
-
-M: sqlite-db <delete-tuple-statement> ( specs table -- sql )
-    [
-        "delete from " 0% 0%
-        " where " 0%
-        find-primary-key
-        dup column-name>> 0% " = " 0% bind%
-    ] sqlite-make ;
-
-! : select-interval ( interval name -- ) ;
-! : select-sequence ( seq name -- ) ;
+M: sqlite-db bind# ( spec obj -- )
+    >r
+    [ column-name>> ":" swap next-sql-counter 3append dup 0% ]
+    [ type>> ] bi
+    r> <literal-bind> 1, ;
 
 M: sqlite-db bind% ( spec -- )
     dup 1, column-name>> ":" prepend 0% ;
 
-M: sqlite-db <select-by-slots-statement> ( tuple class -- statement )
-    [
-        "select " 0%
-        over [ ", " 0% ]
-        [ dup column-name>> 0% 2, ] interleave
-
-        " from " 0% 0%
-        [ slot-name>> swap get-slot-named ] with subset
-        dup empty? [ drop ] [ where-clause ] if ";" 0%
-    ] sqlite-make ;
-
-M: sqlite-db modifier-table ( -- hashtable )
+M: sqlite-db persistent-table ( -- assoc )
     H{
-        { +native-id+ "primary key" }
-        { +assigned-id+ "primary key" }
-        { +random-id+ "primary key" }
-        ! { +nonnative-id+ "primary key" }
-        { +autoincrement+ "autoincrement" }
-        { +unique+ "unique" }
-        { +default+ "default" }
-        { +null+ "null" }
-        { +not-null+ "not null" }
+        { +native-id+ { "integer primary key" "integer primary key" "primary key" } }
+        { +assigned-id+ { f f "primary key" } }
+        { +random-id+ { "integer primary key" "integer primary key" "primary key" } }
+        { INTEGER { "integer" "integer" "primary key" } }
+        { BIG-INTEGER { "bigint" "bigint" } }
+        { SIGNED-BIG-INTEGER { "bigint" "bigint" } }
+        { UNSIGNED-BIG-INTEGER { "bigint" "bigint" } }
+        { TEXT { "text" "text" } }
+        { VARCHAR { "text" "text" } }
+        { DATE { "date" "date" } }
+        { TIME { "time" "time" } }
+        { DATETIME { "datetime" "datetime" } }
+        { TIMESTAMP { "timestamp" "timestamp" } }
+        { DOUBLE { "real" "real" } }
+        { BLOB { "blob" "blob" } }
+        { FACTOR-BLOB { "blob" "blob" } }
+        { +autoincrement+ { f f "autoincrement" } }
+        { +unique+ { f f "unique" } }
+        { +default+ { f f "default" } }
+        { +null+ { f f "null" } }
+        { +not-null+ { f f "not null" } }
+        { system-random-generator { f f f } }
+        { secure-random-generator { f f f } }
+        { random-generator { f f f } }
     } ;
 
-M: sqlite-db compound-modifier ( str obj -- str' ) compound-type ;
-
-M: sqlite-db compound-type ( str seq -- str' )
+M: sqlite-db compound ( str seq -- str' )
     over {
         { "default" [ first number>string join-space ] }
-        [ 2drop ] !  "no sqlite compound data type" 3array throw ]
+        [ 2drop ] 
     } case ;
 
-M: sqlite-db type-table ( -- assoc )
-    H{
-        { +native-id+ "integer primary key" }
-        { +random-id+ "integer primary key" }
-        { INTEGER "integer" }
-        { TEXT "text" }
-        { VARCHAR "text" }
-        { DATE "date" }
-        { TIME "time" }
-        { DATETIME "datetime" }
-        { TIMESTAMP "timestamp" }
-        { DOUBLE "real" }
-        { BLOB "blob" }
-        { FACTOR-BLOB "blob" }
-    } ;
-
-M: sqlite-db create-type-table ( symbol -- str ) type-table ;
index 951ded32ea402806eccd7c00cfe179a8b7e3aa68..32562a4ae85b0980afc0801e7e2a2c6855d9bf90 100755 (executable)
@@ -1,9 +1,9 @@
 ! Copyright (C) 2008 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: io.files kernel tools.test db db.tuples
-db.types continuations namespaces math
-prettyprint tools.walker db.sqlite calendar
-math.intervals db.postgresql ;
+USING: io.files kernel tools.test db db.tuples classes
+db.types continuations namespaces math math.ranges
+prettyprint tools.walker calendar sequences db.sqlite
+math.intervals db.postgresql accessors random math.bitfields.lib ;
 IN: db.tuples.tests
 
 TUPLE: person the-id the-name the-number the-real
@@ -80,9 +80,9 @@ SYMBOL: person4
             "teddy"
             10
             3.14
-            T{ timestamp f 2008 3 5 16 24 11 0 }
-            T{ timestamp f 2008 11 22 f f f f }
-            T{ timestamp f f f f 12 34 56 f }
+            T{ timestamp f 2008 3 5 16 24 11 T{ duration f 0 0 0 0 0 0 } }
+            T{ timestamp f 2008 11 22 f f f T{ duration f 0 0 0 0 0 0 } }
+            T{ timestamp f f f f 12 34 56 T{ duration f 0 0 0 0 0 0 } }
             B{ 115 116 111 114 101 105 110 97 98 108 111 98 }
         }
     ] [ T{ person f 3 } select-tuple ] unit-test
@@ -96,9 +96,9 @@ SYMBOL: person4
             "eddie"
             10
             3.14
-            T{ timestamp f 2008 3 5 16 24 11 0 }
-            T{ timestamp f 2008 11 22 f f f f }
-            T{ timestamp f f f f 12 34 56 f }
+            T{ timestamp f 2008 3 5 16 24 11 T{ duration f 0 0 0 0 0 0 } }
+            T{ timestamp f 2008 11 22 f f f T{ duration f 0 0 0 0 0 0 } }
+            T{ timestamp f f f f 12 34 56 T{ duration f 0 0 0 0 0 0 } }
             f
             H{ { 1 2 } { 3 4 } { 5 "lol" } }
         }
@@ -106,13 +106,6 @@ SYMBOL: person4
 
     [ ] [ person drop-table ] unit-test ;
 
-: make-native-person-table ( -- )
-    [ person drop-table ] [ drop ] recover
-    person create-table
-    T{ person f f "billy" 200 3.14 } insert-tuple
-    T{ person f f "johnny" 10 3.14 } insert-tuple
-    ;
-
 : native-person-schema ( -- )
     person "PERSON"
     {
@@ -192,7 +185,6 @@ TUPLE: annotation n paste-id summary author mode contents ;
 
 : test-repeated-insert
     [ ] [ person ensure-table ] unit-test
-    
     [ ] [ person1 get insert-tuple ] unit-test
     [ person1 get insert-tuple ] must-fail ;
 
@@ -212,12 +204,9 @@ TUPLE: serialize-me id data ;
         { T{ serialize-me f 1 H{ { 1 2 } } } }
     ] [ T{ serialize-me f 1 } select-tuples ] unit-test ;
 
-[ test-serialize ] test-sqlite
-! [ test-serialize ] test-postgresql
-
 TUPLE: exam id name score ; 
 
-: test-ranges ( -- )
+: test-intervals ( -- )
     exam "EXAM"
     {
         { "id" "ID" +native-id+ }
@@ -233,12 +222,84 @@ TUPLE: exam id name score ;
     [ ] [ T{ exam f f "Cartman" 41 } insert-tuple ] unit-test
 
     [
-        T{ exam f 3 "Kenny" 60 }
-        T{ exam f 4 "Cartman" 41 }
-    ] [ T{ exam f 4 f T{ interval f { 0 t } { 70 t } } } select-tuples ] unit-test
-    ;
+        {
+            T{ exam f 3 "Kenny" 60 }
+            T{ exam f 4 "Cartman" 41 }
+        }
+    ] [
+        T{ exam f f f T{ interval f { 0 t } { 70 t } } } select-tuples
+    ] unit-test
 
-! [ test-ranges ] test-sqlite
+    [
+        { }
+    ] [
+        T{ exam f T{ interval f { 3 f } { 4 f } } f } select-tuples
+    ] unit-test
+    [
+        {
+            T{ exam f 4 "Cartman" 41 }
+        }
+    ] [
+        T{ exam f T{ interval f { 3 f } { 4 t } } f } select-tuples
+    ] unit-test
+    [
+        {
+            T{ exam f 3 "Kenny" 60 }
+        }
+    ] [
+        T{ exam f T{ interval f { 3 t } { 4 f } } f } select-tuples
+    ] unit-test
+    [
+        {
+            T{ exam f 3 "Kenny" 60 }
+            T{ exam f 4 "Cartman" 41 }
+        }
+    ] [
+        T{ exam f T{ interval f { 3 t } { 4 t } } f } select-tuples
+    ] unit-test
+
+    [
+        {
+            T{ exam f 1 "Kyle" 100 }
+            T{ exam f 2 "Stan" 80 }
+        }
+    ] [
+        T{ exam f f { "Stan" "Kyle" } } select-tuples
+    ] unit-test
+
+    [
+        {
+            T{ exam f 1 "Kyle" 100 }
+            T{ exam f 2 "Stan" 80 }
+            T{ exam f 3 "Kenny" 60 }
+        }
+    ] [
+        T{ exam f T{ range f 1 3 1 } } select-tuples
+    ] unit-test ;
+
+TUPLE: bignum-test id m n o ;
+: <bignum-test> ( m n o -- obj )
+    bignum-test new
+        swap >>o
+        swap >>n
+        swap >>m ;
+
+: test-bignum
+    bignum-test "BIGNUM_TEST"
+    {
+        { "id" "ID" +native-id+ }
+        { "m" "M" BIG-INTEGER }
+        { "n" "N" UNSIGNED-BIG-INTEGER }
+        { "o" "O" SIGNED-BIG-INTEGER }
+    } define-persistent
+    [ bignum-test drop-table ] ignore-errors
+    [ ] [ bignum-test ensure-table ] unit-test
+    [ ] [ 63 2^ 1- dup dup <bignum-test> insert-tuple ] unit-test ;
+
+    ! sqlite only
+    ! [ T{ bignum-test f 1
+        ! -9223372036854775808 9223372036854775808 -9223372036854775808 } ]
+    ! [ T{ bignum-test f 1 } select-tuple ] unit-test ;
 
 TUPLE: secret n message ;
 C: <secret> secret
@@ -246,27 +307,59 @@ C: <secret> secret
 : test-random-id
     secret "SECRET"
     {
-        { "n" "ID" +random-id+ }
+        { "n" "ID" +random-id+ system-random-generator }
         { "message" "MESSAGE" TEXT }
     } define-persistent
 
     [ ] [ secret ensure-table ] unit-test
+
     [ ] [ f "kilroy was here" <secret> insert-tuple ] unit-test
-    [ ] [ T{ secret } select-tuples ] unit-test
-    ;
 
+    [ ] [ f "kilroy was here2" <secret> insert-tuple ] unit-test
+
+    [ ] [ f "kilroy was here3" <secret> insert-tuple ] unit-test
 
+    [ t ] [
+        T{ secret } select-tuples
+        first message>> "kilroy was here" head?
+    ] unit-test
 
-! [ test-random-id ] test-sqlite
- [ native-person-schema test-tuples ] test-sqlite
- [ assigned-person-schema test-tuples ] test-sqlite
- [ assigned-person-schema test-repeated-insert ] test-sqlite
- [ native-person-schema test-tuples ] test-postgresql
- [ assigned-person-schema test-tuples ] test-postgresql
- [ assigned-person-schema test-repeated-insert ] test-postgresql
+    [ t ] [
+        T{ secret } select-tuples length 3 =
+    ] unit-test ;
 
-! \ insert-tuple must-infer
-! \ update-tuple must-infer
-! \ delete-tuple must-infer
-! \ select-tuple must-infer
-! \ define-persistent must-infer
+[ native-person-schema test-tuples ] test-sqlite
+[ assigned-person-schema test-tuples ] test-sqlite
+[ assigned-person-schema test-repeated-insert ] test-sqlite
+[ test-bignum ] test-sqlite
+[ test-serialize ] test-sqlite
+[ test-intervals ] test-sqlite
+[ test-random-id ] test-sqlite
+
+[ native-person-schema test-tuples ] test-postgresql
+[ assigned-person-schema test-tuples ] test-postgresql
+[ assigned-person-schema test-repeated-insert ] test-postgresql
+[ test-bignum ] test-postgresql
+[ test-serialize ] test-postgresql
+[ test-intervals ] test-postgresql
+[ test-random-id ] test-postgresql
+
+TUPLE: does-not-persist ;
+
+[
+    [ does-not-persist create-sql-statement ]
+    [ class \ not-persistent = ] must-fail-with
+] test-sqlite
+
+[
+    [ does-not-persist create-sql-statement ]
+    [ class \ not-persistent = ] must-fail-with
+] test-postgresql
+
+! Don't comment these out. These words must infer
+\ bind-tuple must-infer
+\ insert-tuple must-infer
+\ update-tuple must-infer
+\ delete-tuple must-infer
+\ select-tuple must-infer
+\ define-persistent must-infer
index 311f18daa924461ef1fdd177aef7b0b3366f629a..fd4cfb906f1cb0b578e493ddc13efe50b707ae7e 100755 (executable)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2008 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays assocs classes db kernel namespaces
-classes.tuple words sequences slots math
+classes.tuple words sequences slots math accessors
 math.parser io prettyprint db.types continuations
 mirrors sequences.lib tools.walker combinators.lib ;
 IN: db.tuples
@@ -13,15 +13,26 @@ IN: db.tuples
     "db-columns" set-word-prop
     "db-relations" set-word-prop ;
 
-: db-table ( class -- obj ) "db-table" word-prop ;
-: db-columns ( class -- obj ) "db-columns" word-prop ;
-: db-relations ( class -- obj ) "db-relations" word-prop ;
+ERROR: not-persistent ;
+
+: db-table ( class -- obj )
+    "db-table" word-prop [ not-persistent ] unless* ;
+
+: db-columns ( class -- obj )
+    "db-columns" word-prop ;
+
+: db-relations ( class -- obj )
+    "db-relations" word-prop ;
 
 : set-primary-key ( key tuple -- )
     [
-        class db-columns find-primary-key sql-spec-slot-name
+        class db-columns find-primary-key slot-name>>
     ] keep set-slot-named ;
 
+SYMBOL: sql-counter
+: next-sql-counter ( -- str )
+    sql-counter [ inc ] [ get ] bi number>string ;
+
 ! returns a sequence of prepared-statements
 HOOK: create-sql-statement db ( class -- obj )
 HOOK: drop-sql-statement db ( class -- obj )
@@ -39,26 +50,55 @@ HOOK: <select-by-slots-statement> db ( tuple class -- tuple )
 
 HOOK: insert-tuple* db ( tuple statement -- )
 
+GENERIC: eval-generator ( singleton -- obj )
+SINGLETON: retryable
+
+: make-retryable ( obj -- obj' )
+    dup sequence? [
+        [ make-retryable ] map
+    ] [
+        retryable >>type
+    ] if ;
+
+: regenerate-params ( statement -- statement )
+    dup
+    [ bind-params>> ] [ in-params>> ] bi
+    [
+        dup generator-bind? [
+            singleton>> eval-generator >>value
+        ] [
+            drop
+        ] if
+    ] 2map >>bind-params ;
+
+M: retryable execute-statement* ( statement type -- )
+    drop
+    [
+        [ query-results dispose t ]
+        [ ]
+        [ regenerate-params bind-statement* f ] cleanup
+    ] curry 10 retry drop ;
+
 : resulting-tuple ( row out-params -- tuple )
-    dup first sql-spec-class new [
+    dup first class>> new [
         [
-            >r sql-spec-slot-name r> set-slot-named
+            >r slot-name>> r> set-slot-named
         ] curry 2each
     ] keep ;
 
 : query-tuples ( statement -- seq )
-    [ statement-out-params ] keep query-results [
+    [ out-params>> ] keep query-results [
         [ sql-row-typed swap resulting-tuple ] with query-map
     ] with-disposal ;
  
 : query-modify-tuple ( tuple statement -- )
     [ query-results [ sql-row-typed ] with-disposal ] keep
-    statement-out-params rot [
-        >r sql-spec-slot-name r> set-slot-named
+    out-params>> rot [
+        >r slot-name>> r> set-slot-named
     ] curry 2each ;
 
 : sql-props ( class -- columns table )
-    dup db-columns swap db-table ;
+    [ db-columns ] [ db-table ] bi ;
 
 : with-disposals ( seq quot -- )
     over sequence? [
@@ -85,17 +125,13 @@ HOOK: insert-tuple* db ( tuple statement -- )
     [ bind-tuple ] 2keep insert-tuple* ;
 
 : insert-nonnative ( tuple -- )
-! TODO logic here for unique ids
     dup class
     db get db-insert-statements [ <insert-nonnative-statement> ] cache
     [ bind-tuple ] keep execute-statement ;
 
 : insert-tuple ( tuple -- )
-    dup class db-columns find-primary-key nonnative-id? [
-        insert-nonnative
-    ] [
-        insert-native
-    ] if ;
+    dup class db-columns find-primary-key nonnative-id?
+    [ insert-nonnative ] [ insert-native ] if ;
 
 : update-tuple ( tuple -- )
     dup class
index 98bc451a6f3a486c9d47f7ed39cf3e611da8346a..110a8a388aa525ebecd81bbb877875c3d43b6e38 100755 (executable)
@@ -4,16 +4,23 @@ USING: arrays assocs db kernel math math.parser
 sequences continuations sequences.deep sequences.lib
 words namespaces tools.walker slots slots.private classes
 mirrors classes.tuple combinators calendar.format symbols
-classes.singleton ;
+classes.singleton accessors quotations random ;
 IN: db.types
 
-HOOK: modifier-table db ( -- hash )
-HOOK: compound-modifier db ( str seq -- hash )
-HOOK: type-table db ( -- hash )
-HOOK: create-type-table db ( -- hash )
-HOOK: compound-type db ( str n -- hash )
+HOOK: persistent-table db ( -- hash )
+HOOK: compound db ( str obj -- hash )
 
-TUPLE: sql-spec class slot-name column-name type modifiers primary-key ;
+TUPLE: sql-spec class slot-name column-name type primary-key modifiers ;
+
+TUPLE: literal-bind key type value ;
+C: <literal-bind> literal-bind
+
+TUPLE: generator-bind key singleton type ;
+C: <generator-bind> generator-bind
+SINGLETON: random-id-generator
+
+TUPLE: low-level-binding value ;
+C: <low-level-binding> low-level-binding
 
 SINGLETON: +native-id+
 SINGLETON: +assigned-id+
@@ -24,50 +31,54 @@ UNION: +nonnative-id+ +random-id+ +assigned-id+ ;
 SYMBOLS: +autoincrement+ +serial+ +unique+ +default+ +null+ +not-null+
 +foreign-id+ +has-many+ ;
 
+: find-random-generator ( seq -- obj )
+    [
+        {
+            random-generator
+            system-random-generator
+            secure-random-generator
+        } member?
+    ] find nip [ system-random-generator ] unless* ;
+
 : primary-key? ( spec -- ? )
-    sql-spec-primary-key +primary-key+? ;
+    primary-key>> +primary-key+? ;
 
 : native-id? ( spec -- ? )
-    sql-spec-primary-key +native-id+? ;
+    primary-key>> +native-id+? ;
 
 : nonnative-id? ( spec -- ? )
-    sql-spec-primary-key +nonnative-id+? ;
+    primary-key>> +nonnative-id+? ;
 
 : normalize-spec ( spec -- )
-    dup sql-spec-type dup +primary-key+? [
-        swap set-sql-spec-primary-key
+    dup type>> dup +primary-key+? [
+        >>primary-key drop
     ] [
-        drop dup sql-spec-modifiers [
+        drop dup modifiers>> [
             +primary-key+?
         ] deep-find
-        [ swap set-sql-spec-primary-key ] [ drop ] if*
+        [ >>primary-key drop ] [ drop ] if*
     ] if ;
 
 : find-primary-key ( specs -- obj )
-    [ sql-spec-primary-key ] find nip ;
+    [ primary-key>> ] find nip ;
 
 : relation? ( spec -- ? ) [ +has-many+ = ] deep-find ;
 
-SYMBOLS: INTEGER BIG-INTEGER DOUBLE REAL BOOLEAN TEXT VARCHAR
-DATE TIME DATETIME TIMESTAMP BLOB FACTOR-BLOB NULL ;
+SYMBOLS: INTEGER BIG-INTEGER SIGNED-BIG-INTEGER UNSIGNED-BIG-INTEGER
+DOUBLE REAL BOOLEAN TEXT VARCHAR DATE TIME DATETIME TIMESTAMP BLOB
+FACTOR-BLOB NULL ;
 
 : spec>tuple ( class spec -- tuple )
-    [ ?first3 ] keep 3 ?tail*
-    {
-        set-sql-spec-class
-        set-sql-spec-slot-name
-        set-sql-spec-column-name
-        set-sql-spec-type
-        set-sql-spec-modifiers
-    } sql-spec construct
+    3 f pad-right
+    [ first3 ] keep 3 tail
+    sql-spec new
+        swap >>modifiers
+        swap >>type
+        swap >>column-name
+        swap >>slot-name
+        swap >>class
     dup normalize-spec ;
 
-TUPLE: no-sql-type ;
-: no-sql-type ( -- * ) T{ no-sql-type } throw ;
-
-TUPLE: no-sql-modifier ;
-: no-sql-modifier ( -- * ) T{ no-sql-modifier } throw ;
-
 : number>string* ( n/str -- str )
     dup number? [ number>string ] when ;
 
@@ -78,40 +89,40 @@ TUPLE: no-sql-modifier ;
     [ relation? not ] subset ;
 
 : remove-id ( specs -- obj )
-    [ sql-spec-primary-key not ] subset ;
+    [ primary-key>> not ] subset ;
 
 ! SQLite Types: http://www.sqlite.org/datatype3.html
 ! NULL INTEGER REAL TEXT BLOB
 ! PostgreSQL Types:
 ! http://developer.postgresql.org/pgdocs/postgres/datatype.html
 
+ERROR: unknown-modifier ;
+
 : lookup-modifier ( obj -- str )
-    dup array? [
-        unclip lookup-modifier swap compound-modifier
-    ] [
-        modifier-table at*
-        [ "unknown modifier" throw ] unless
-    ] if ;
+    {
+        { [ dup array? ] [ unclip lookup-modifier swap compound ] }
+        [ persistent-table at* [ unknown-modifier ] unless third ]
+    } cond ;
+
+ERROR: no-sql-type ;
 
-: lookup-type* ( obj -- str )
+: (lookup-type) ( obj -- str )
+    persistent-table at* [ no-sql-type ] unless ;
+
+: lookup-type ( obj -- str )
     dup array? [
-        first lookup-type*
+        unclip (lookup-type) first nip
     ] [
-        type-table at*
-        [ no-sql-type ] unless
+        (lookup-type) first
     ] if ;
 
 : lookup-create-type ( obj -- str )
     dup array? [
-        unclip lookup-create-type swap compound-type
+        unclip (lookup-type) second swap compound
     ] [
-        dup create-type-table at*
-        [ nip ] [ drop lookup-type* ] if
+        (lookup-type) second
     ] if ;
 
-: lookup-type ( obj create? -- str )
-    [ lookup-create-type ] [ lookup-type* ] if ;
-
 : single-quote ( str -- newstr )
     "'" swap "'" 3append ;
 
@@ -125,11 +136,11 @@ TUPLE: no-sql-modifier ;
     " " swap 3append ;
 
 : modifiers ( spec -- str )
-    sql-spec-modifiers 
-    [ lookup-modifier ] map " " join
+    modifiers>> [ lookup-modifier ] map " " join
     dup empty? [ " " prepend ] unless ;
 
 HOOK: bind% db ( spec -- )
+HOOK: bind# db ( spec obj -- )
 
 : offset-of-slot ( str obj -- n )
     class "slots" word-prop slot-named slot-spec-offset ;
@@ -145,6 +156,6 @@ HOOK: bind% db ( spec -- )
 
 : tuple>params ( specs tuple -- obj )
     [
-        >r dup sql-spec-type swap sql-spec-slot-name r>
+        >r [ type>> ] [ slot-name>> ] bi r>
         get-slot-named swap
     ] curry { } map>assoc ;
index 178a1b3b8b9a5931fe8cb7b9615615766161f9c8..325a451a0b3686a242485d4486bde1cd7b71e9c3 100644 (file)
@@ -1,9 +1,10 @@
 ! Generate a new factor.vim file for syntax highlighting
-USING: http.server.templating.fhtml io.files ;
+USING: http.server.templating http.server.templating.fhtml
+io.files ;
 IN: editors.vim.generate-syntax
 
 : generate-vim-syntax ( -- )
-    "misc/factor.vim.fgen" resource-path
+    "misc/factor.vim.fgen" resource-path <fhtml>
     "misc/factor.vim" resource-path
     template-convert ;
 
index 8d60942d67a2f63ea4ab01ae43577deff0da6d10..9ce256868b23b21b05e79b6507bed4aa9839d86e 100755 (executable)
@@ -1,5 +1,5 @@
 USING: definitions io io.launcher kernel math math.parser
-namespaces parser prettyprint sequences editors ;
+namespaces parser prettyprint sequences editors accessors ;
 IN: editors.vim
 
 SYMBOL: vim-path
@@ -17,8 +17,9 @@ M: vim vim-command ( file line -- array )
 
 : vim-location ( file line -- )
     vim-command
-    vim-detach get-global
-    [ run-detached ] [ run-process ] if drop ;
+    <process> swap >>command
+    vim-detach get-global [ t >>detached ] when
+    try-process ;
 
 "vim" vim-path set-global
 [ vim-location ] edit-hook set-global
index af4ddd8839c83d6480a733eba8bb6c87c91ced01..7176486f8e86ea0d209fdf4a2ac6b2ca5515cda4 100755 (executable)
@@ -54,10 +54,12 @@ IN: farkup.tests
 [ "<p>=</p><h2>foo</h2>" ] [ "===foo==" convert-farkup ] unit-test
 [ "<h1>foo</h1><p>=</p>" ] [ "=foo==" convert-farkup ] unit-test
 
-[ "<span class='KEYWORD3'>int</span> <span class='FUNCTION'>main</span><span class='OPERATOR'>(</span><span class='OPERATOR'>)</span><br/>" ]
+[ "<div style='white-space: pre; font-family: monospace; '><span class='KEYWORD3'>int</span> <span class='FUNCTION'>main</span><span class='OPERATOR'>(</span><span class='OPERATOR'>)</span><br/></div>" ]
 [ "[c{int main()}]" convert-farkup ] unit-test
 
 [ "<p><img src=\"lol.jpg\"/></p>" ] [ "[[image:lol.jpg]]" convert-farkup ] unit-test
 [ "<p><img src=\"lol.jpg\" alt=\"teh lol\"/></p>" ] [ "[[image:lol.jpg|teh lol]]" convert-farkup ] unit-test
 [ "<p><a href=\"lol.com\"></a></p>" ] [ "[[lol.com]]" convert-farkup ] unit-test
 [ "<p><a href=\"lol.com\">haha</a></p>" ] [ "[[lol.com|haha]]" convert-farkup ] unit-test
+
+[ ] [ "[{}]" convert-farkup drop ] unit-test
index f876c9569b6a226b9731b8b27a586276996b8e4a..527ba8b4fa403c0be3640ec93cbcf7cf09fccf3b 100755 (executable)
@@ -1,9 +1,9 @@
 ! Copyright (C) 2008 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: arrays io kernel memoize namespaces peg sequences strings
-html.elements xml.entities xmode.code2html splitting
-io.streams.string html peg.parsers html.elements sequences.deep
-unicode.categories ;
+USING: arrays io io.styles kernel memoize namespaces peg
+sequences strings html.elements xml.entities xmode.code2html
+splitting io.streams.string html peg.parsers html.elements
+sequences.deep unicode.categories ;
 IN: farkup
 
 <PRIVATE
@@ -55,7 +55,13 @@ MEMO: eq ( -- parser )
 
 : render-code ( string mode -- string' )
     >r string-lines r>
-    [ [ htmlize-lines ] with-html-stream ] with-string-writer ;
+    [
+        [
+            H{ { wrap-margin f } } [
+                htmlize-lines
+            ] with-nesting
+        ] with-html-stream
+    ] with-string-writer ;
 
 : escape-link ( href text -- href-esc text-esc )
     >r escape-quoted-string r> escape-string ;
diff --git a/extra/float-vectors/float-vectors-docs.factor b/extra/float-vectors/float-vectors-docs.factor
new file mode 100755 (executable)
index 0000000..5e06f05
--- /dev/null
@@ -0,0 +1,42 @@
+USING: arrays float-arrays help.markup help.syntax kernel\r
+float-vectors.private combinators ;\r
+IN: float-vectors\r
+\r
+ARTICLE: "float-vectors" "Float vectors"\r
+"A float vector is a resizable mutable sequence of unsigned floats. Float vector words are found in the " { $vocab-link "float-vectors" } " vocabulary."\r
+$nl\r
+"Float vectors form a class:"\r
+{ $subsection float-vector }\r
+{ $subsection float-vector? }\r
+"Creating float vectors:"\r
+{ $subsection >float-vector }\r
+{ $subsection <float-vector> }\r
+"Literal syntax:"\r
+{ $subsection POSTPONE: FV{ }\r
+"If you don't care about initial capacity, a more elegant way to create a new float vector is to write:"\r
+{ $code "FV{ } clone" } ;\r
+\r
+ABOUT: "float-vectors"\r
+\r
+HELP: float-vector\r
+{ $description "The class of resizable float vectors. See " { $link "float-vectors" } " for information." } ;\r
+\r
+HELP: <float-vector>\r
+{ $values { "n" "a positive integer specifying initial capacity" } { "float-vector" float-vector } }\r
+{ $description "Creates a new float vector that can hold " { $snippet "n" } " floats before resizing." } ;\r
+\r
+HELP: >float-vector\r
+{ $values { "seq" "a sequence" } { "float-vector" float-vector } }\r
+{ $description "Outputs a freshly-allocated float vector with the same elements as a given sequence." }\r
+{ $errors "Throws an error if the sequence contains elements other than real numbers." } ;\r
+\r
+HELP: float-array>vector\r
+{ $values { "float-array" "an array" } { "length" "a non-negative integer" } { "float-vector" float-vector } }\r
+{ $description "Creates a new float vector using the array for underlying storage with the specified initial length." }\r
+{ $warning "This word is in the " { $vocab-link "float-vectors.private" } " vocabulary because it does not perform type or bounds checks. User code should call " { $link >float-vector } " instead." } ;\r
+\r
+HELP: FV{\r
+{ $syntax "FV{ elements... }" }\r
+{ $values { "elements" "a list of real numbers" } }\r
+{ $description "Marks the beginning of a literal float vector. Literal float vectors are terminated by " { $link POSTPONE: } } "." } \r
+{ $examples { $code "FV{ 1.0 2.0 3.0 }" } } ;\r
diff --git a/extra/float-vectors/float-vectors-tests.factor b/extra/float-vectors/float-vectors-tests.factor
new file mode 100755 (executable)
index 0000000..383dd4b
--- /dev/null
@@ -0,0 +1,14 @@
+IN: float-vectors.tests\r
+USING: tools.test float-vectors vectors sequences kernel ;\r
+\r
+[ 0 ] [ 123 <float-vector> length ] unit-test\r
+\r
+: do-it\r
+    12345 [ over push ] each ;\r
+\r
+[ t ] [\r
+    3 <float-vector> do-it\r
+    3 <vector> do-it sequence=\r
+] unit-test\r
+\r
+[ t ] [ FV{ } float-vector? ] unit-test\r
diff --git a/extra/float-vectors/float-vectors.factor b/extra/float-vectors/float-vectors.factor
new file mode 100755 (executable)
index 0000000..d51f0d4
--- /dev/null
@@ -0,0 +1,51 @@
+! Copyright (C) 2008 Slava Pestov.\r
+! See http://factorcode.org/license.txt for BSD license.\r
+USING: arrays kernel kernel.private math sequences\r
+sequences.private growable float-arrays prettyprint.backend\r
+parser accessors ;\r
+IN: float-vectors\r
+\r
+TUPLE: float-vector underlying fill ;\r
+\r
+M: float-vector underlying underlying>> { float-array } declare ;\r
+\r
+M: float-vector set-underlying (>>underlying) ;\r
+\r
+M: float-vector length fill>> { array-capacity } declare ;\r
+\r
+M: float-vector set-fill (>>fill) ;\r
+\r
+<PRIVATE\r
+\r
+: float-array>vector ( float-array length -- float-vector )\r
+    float-vector boa ; inline\r
+\r
+PRIVATE>\r
+\r
+: <float-vector> ( n -- float-vector )\r
+    0.0 <float-array> 0 float-array>vector ; inline\r
+\r
+: >float-vector ( seq -- float-vector )\r
+    T{ float-vector f F{ } 0 } clone-like ;\r
+\r
+M: float-vector like\r
+    drop dup float-vector? [\r
+        dup float-array?\r
+        [ dup length float-array>vector ] [ >float-vector ] if\r
+    ] unless ;\r
+\r
+M: float-vector new-sequence\r
+    drop [ 0.0 <float-array> ] keep >fixnum float-array>vector ;\r
+\r
+M: float-vector equal?\r
+    over float-vector? [ sequence= ] [ 2drop f ] if ;\r
+\r
+M: float-array new-resizable drop <float-vector> ;\r
+\r
+INSTANCE: float-vector growable\r
+\r
+: FV{ \ } [ >float-vector ] parse-literal ; parsing\r
+\r
+M: float-vector >pprint-sequence ;\r
+\r
+M: float-vector pprint-delims drop \ FV{ \ } ;\r
diff --git a/extra/float-vectors/summary.txt b/extra/float-vectors/summary.txt
new file mode 100644 (file)
index 0000000..c476f41
--- /dev/null
@@ -0,0 +1 @@
+Growable float arrays
diff --git a/extra/float-vectors/tags.txt b/extra/float-vectors/tags.txt
new file mode 100644 (file)
index 0000000..42d711b
--- /dev/null
@@ -0,0 +1 @@
+collections
index 4d2c9fe1c819ce462ed1cd7ff3c2bd8b9caab833..7586e254b2ee0b8048b906e9cb01a9dfd43611a6 100755 (executable)
@@ -44,3 +44,7 @@ sequences ;
 : funny-dip '[ @ _ ] call ; inline
 
 [ "hi" 3 ] [ "h" "i" 3 [ append ] funny-dip ] unit-test
+
+[ { 1 2 3 } ] [
+    3 1 '[ , [ , + ] map ] call
+] unit-test
index 6c20aac7f2dcd08232592525f62ca1bd91bbe726..7621af68997e4ff3993cf918dfc01e84fa593417 100755 (executable)
@@ -9,41 +9,54 @@ IN: fry
 : @ "Only valid inside a fry" throw ;
 : _ "Only valid inside a fry" throw ;
 
-DEFER: (fry)
+DEFER: (shallow-fry)
 
-: ((fry)) ( accum quot adder -- result )
-    >r [ ] swap (fry) r>
+: ((shallow-fry)) ( accum quot adder -- result )
+    >r [ ] swap (shallow-fry) r>
     append swap dup empty? [ drop ] [
         [ swap compose ] curry append
     ] if ; inline
 
-: (fry) ( accum quot -- result )
+: (shallow-fry) ( accum quot -- result )
     dup empty? [
         drop 1quotation
     ] [
         unclip {
-            { \ , [ [ curry ] ((fry)) ] }
-            { \ @ [ [ compose ] ((fry)) ] }
+            { \ , [ [ curry ] ((shallow-fry)) ] }
+            { \ @ [ [ compose ] ((shallow-fry)) ] }
 
             ! to avoid confusion, remove if fry goes core
-            { \ namespaces:, [ [ curry ] ((fry)) ] }
+            { \ namespaces:, [ [ curry ] ((shallow-fry)) ] }
 
-            [ swap >r suffix r> (fry) ]
+            [ swap >r suffix r> (shallow-fry) ]
         } case
     ] if ;
 
-: trivial-fry ( quot -- quot' ) [ ] swap (fry) ;
+: shallow-fry ( quot -- quot' ) [ ] swap (shallow-fry) ;
 
-: fry ( quot -- quot' )
+: deep-fry ( quot -- quot' )
     { _ } last-split1 [
         [
-            trivial-fry %
+            shallow-fry %
             [ >r ] %
-            fry %
+            deep-fry %
             [ [ dip ] curry r> compose ] %
         ] [ ] make
     ] [
-        trivial-fry
+        shallow-fry
     ] if* ;
 
+: fry ( quot -- quot' )
+    [
+        [
+            dup callable? [
+                [
+                    [ { , namespaces:, @ } member? ] subset length
+                    \ , <repetition> %
+                ]
+                [ deep-fry % ] bi
+            ] [ namespaces:, ] if
+        ] each
+    ] [ ] make deep-fry ;
+
 : '[ \ ] parse-until fry over push-all ; parsing
index 91838d2a53f194ca4cf30baed31adcce4b9ae7e8..fe1fd72a21437133628a4f2a55e31eb121bf657d 100644 (file)
@@ -1,6 +1,7 @@
-USING: alien alien.c-types alien.syntax byte-arrays kernel
-namespaces sequences unix hardware-info.backend system
-io.unix.backend ;
+USING: alien alien.c-types alien.strings alien.syntax
+byte-arrays kernel namespaces sequences unix
+hardware-info.backend system io.unix.backend io.encodings.ascii
+;
 IN: hardware-info.macosx
 
 ! See /usr/include/sys/sysctl.h for constants
@@ -19,7 +20,7 @@ FUNCTION: int sysctl ( int* name, uint namelen, void* oldp, size_t* oldlenp, voi
     [ <byte-array> ] [ <uint> ] bi (sysctl-query) ;
 
 : sysctl-query-string ( seq -- n )
-    4096 sysctl-query alien>char-string ;
+    4096 sysctl-query ascii malloc-string ;
 
 : sysctl-query-uint ( seq -- n )
     4 sysctl-query *uint ;
index ba9c1d74b516fe29248f713287073e01e1b64314..2599a33754635672ea80dff94f7e0655dbe88377 100755 (executable)
@@ -1,4 +1,4 @@
-USING: alien alien.c-types
+USING: alien alien.c-types alien.strings
 kernel libc math namespaces hardware-info.backend
 windows windows.advapi32 windows.kernel32 system ;
 IN: hardware-info.windows.nt
@@ -35,12 +35,14 @@ M: winnt total-virtual-mem ( -- n )
 M: winnt available-virtual-mem ( -- n )
     memory-status MEMORYSTATUSEX-ullAvailVirtual ;
 
+: pull-win32-string [ utf16n alien>string ] keep free ;
+
 : computer-name ( -- string )
     MAX_COMPUTERNAME_LENGTH 1+ [ malloc ] keep
     <int> dupd GetComputerName zero? [
         free win32-error f
     ] [
-        [ alien>u16-string ] keep free
+        pull-win32-string
     ] if ;
  
 : username ( -- string )
@@ -48,5 +50,5 @@ M: winnt available-virtual-mem ( -- n )
     <int> dupd GetUserName zero? [
         free win32-error f
     ] [
-        [ alien>u16-string ] keep free
+        pull-win32-string
     ] if ;
index 807fd158baea16682b912f4ece057f579be326e6..10474c09f75e393132072bc0d2015e3eeed9c10e 100755 (executable)
@@ -36,7 +36,7 @@ IN: hardware-info.windows
     os-version OSVERSIONINFO-dwPlatformId ;
 
 : windows-service-pack ( -- string )
-    os-version OSVERSIONINFO-szCSDVersion alien>u16-string ;
+    os-version OSVERSIONINFO-szCSDVersion utf16n alien>string ;
 
 : feature-present? ( n -- ? )
     IsProcessorFeaturePresent zero? not ;
@@ -52,7 +52,7 @@ IN: hardware-info.windows
 
 : get-directory ( word -- str )
     >r MAX_UNICODE_PATH [ <u16-string-object> ] keep dupd r>
-    execute win32-error=0/f alien>u16-string ; inline
+    execute win32-error=0/f utf16n alien>string ; inline
 
 : windows-directory ( -- str )
     \ GetWindowsDirectory get-directory ;
index 4e6bfe48881153f52d84b860c438700af278b261..15e3b8be1d48efe2596088bd8d28bf0f7c279464 100755 (executable)
@@ -145,9 +145,9 @@ ARTICLE: "collections" "Collections"
 { $subsection "vectors" }
 "Resizable specialized sequences:"
 { $subsection "sbufs" }
-{ $subsection "bit-vectors" }
-{ $subsection "byte-vectors" }
-{ $subsection "float-vectors" }
+{ $vocab-subsection "Bit vectors" "bit-vectors" }
+{ $vocab-subsection "Byte vectors" "byte-vectors" }
+{ $vocab-subsection "Float vectors" "float-vectors" }
 { $heading "Associative mappings" }
 { $subsection "assocs" }
 { $subsection "namespaces" }
@@ -163,7 +163,7 @@ ARTICLE: "collections" "Collections"
 { $subsection "buffers" } ;
 
 USING: io.sockets io.launcher io.mmap io.monitors
-io.encodings.utf8 io.encodings.binary io.encodings.ascii io.files ;
+io.encodings.utf8 io.encodings.utf16 io.encodings.binary io.encodings.ascii io.files ;
 
 ARTICLE: "encodings-introduction" "An introduction to encodings"
 "In order to express text in terms of binary, some sort of encoding has to be used. In a modern context, this is understood as a two-way mapping between Unicode code points (characters) and some amount of binary. Since English isn't the only language in the world, ASCII is not sufficient as a mapping from binary to Unicode; it can't even express em-dashes or curly quotes. Unicode was designed as a universal character set that could potentially represent everything." $nl
index aa2704a799fc1b17831a99a8487e8e793d1c29c5..e0b27099329974b4714e356455c8ab0bf65be80e 100755 (executable)
@@ -38,7 +38,7 @@ M: predicate word-help* drop \ $predicate ;
     \ $error-description swap word-help elements empty? not ;
 
 : sort-articles ( seq -- newseq )
-    [ dup article-title ] { } map>assoc sort-values 0 <column> ;
+    [ dup article-title ] { } map>assoc sort-values keys ;
 
 : all-errors ( -- seq )
     all-words [ error? ] subset sort-articles ;
index 754afb1ea7581a2231315f69b1dc108458d85322..41e29fc7128ae4d2e727f6cec88db34ccc18e929 100644 (file)
@@ -161,6 +161,6 @@ SYMBOL: html
         "id" "onclick" "style" "valign" "accesskey"
         "src" "language" "colspan" "onchange" "rel"
         "width" "selected" "onsubmit" "xmlns" "lang" "xml:lang"
-        "media"
+        "media" "title"
     ] [ define-attribute-word ] each
 ] with-compilation-unit
index 0f684f782af39a08cca1770eba11c4b9e8568f9d..1d947b99e526f21f6ed56f3a0d624668984e96d4 100755 (executable)
@@ -6,9 +6,9 @@ tuple-syntax namespaces ;
 [ "/" "localhost" 8888 ] [ "http://localhost:8888" parse-url ] unit-test
 
 [ "foo.txt" ] [ "http://www.paulgraham.com/foo.txt" download-name ] unit-test
-[ "foo.txt" ] [ "http://www.arcsucks.com/foo.txt?xxx" download-name ] unit-test
-[ "foo.txt" ] [ "http://www.arcsucks.com/foo.txt/" download-name ] unit-test
-[ "www.arcsucks.com" ] [ "http://www.arcsucks.com////" download-name ] unit-test
+[ "foo.txt" ] [ "http://www.arc.com/foo.txt?xxx" download-name ] unit-test
+[ "foo.txt" ] [ "http://www.arc.com/foo.txt/" download-name ] unit-test
+[ "www.arc.com" ] [ "http://www.arc.com////" download-name ] unit-test
 
 [
     TUPLE{ request
@@ -18,7 +18,7 @@ tuple-syntax namespaces ;
         port: 80
         version: "1.1"
         cookies: V{ }
-        header: H{ }
+        header: H{ { "connection" "close" } }
     }
 ] [
     [
index e4bbf0279f1e4992933ae717ae6d72ae76419cec..cc356ca8e378f0cf15640ca317a902519dd1f7f5 100755 (executable)
@@ -3,9 +3,17 @@
 USING: assocs http kernel math math.parser namespaces sequences
 io io.sockets io.streams.string io.files io.timeouts strings
 splitting calendar continuations accessors vectors
-io.encodings.8-bit io.encodings.binary fry ;
+io.encodings.8-bit io.encodings.binary fry debugger inspector ;
 IN: http.client
 
+: max-redirects 10 ;
+
+ERROR: too-many-redirects ;
+
+M: too-many-redirects summary
+    drop
+    [ "Redirection limit of " % max-redirects # " exceeded" % ] "" make ;
+
 DEFER: http-request
 
 <PRIVATE
@@ -29,22 +37,29 @@ DEFER: http-request
 : relative-redirect ( path -- request )
     request get swap store-path ;
 
+SYMBOL: redirects
+
+: absolute-url? ( url -- ? )
+    [ "http://" head? ] [ "https://" head? ] bi or ;
+
 : do-redirect ( response -- response stream )
     dup response-code 300 399 between? [
         stdio get dispose
-        header>> "location" swap at
-        dup "http://" head? [
-            absolute-redirect
+        redirects inc
+        redirects get max-redirects < [
+            header>> "location" swap at
+            dup absolute-url? [
+                absolute-redirect
+            ] [
+                relative-redirect
+            ] if "GET" >>method http-request
         ] [
-            relative-redirect
-        ] if "GET" >>method http-request
+            too-many-redirects
+        ] if
     ] [
         stdio get
     ] if ;
 
-: request-addr ( request -- addr )
-    dup host>> swap port>> <inet> ;
-
 : close-on-error ( stream quot -- )
     '[ , with-stream* ] [ ] pick '[ , dispose ] cleanup ; inline
 
@@ -61,28 +76,55 @@ PRIVATE>
         ] close-on-error
     ] with-variable ;
 
+: read-chunks ( -- )
+    read-crlf ";" split1 drop hex> dup { f 0 } member?
+    [ drop ] [ read % read-crlf "" assert= read-chunks ] if ;
+
+: do-chunked-encoding ( response stream -- response stream/string )
+    over "transfer-encoding" header "chunked" = [
+        [ [ read-chunks ] "" make ] with-stream
+    ] when ;
+
 : <get-request> ( url -- request )
     <request> request-with-url "GET" >>method ;
 
-: http-get-stream ( url -- response stream )
-    <get-request> http-request ;
+: string-or-contents ( stream/string -- string )
+    dup string? [ contents ] unless ;
+
+: http-get-stream ( url -- response stream/string )
+    <get-request> http-request do-chunked-encoding ;
 
 : success? ( code -- ? ) 200 = ;
 
-: check-response ( response -- )
-    code>> success?
-    [ "HTTP download failed" throw ] unless ;
+ERROR: download-failed response body ;
+
+M: download-failed error.
+    "HTTP download failed:" print nl
+    [
+        response>>
+            write-response-code
+            write-response-message nl
+        drop
+    ]
+    [ body>> write ] bi ;
+
+: check-response ( response string -- string )
+    over code>> success? [ nip ] [ download-failed ] if ;
 
 : http-get ( url -- string )
-    http-get-stream contents swap check-response ;
+    http-get-stream string-or-contents check-response ;
 
 : download-name ( url -- name )
     file-name "?" split1 drop "/" ?tail drop ;
 
 : download-to ( url file -- )
     #! Downloads the contents of a URL to a file.
-    swap http-get-stream swap check-response
-    [ swap latin1 <file-writer> stream-copy ] with-disposal ;
+    swap http-get-stream check-response
+    dup string? [
+        latin1 [ write ] with-file-writer
+    ] [
+        [ swap latin1 <file-writer> stream-copy ] with-disposal
+    ] if ;
 
 : download ( url -- )
     dup download-name download-to ;
@@ -95,4 +137,4 @@ PRIVATE>
     swap >>post-data-type ;
 
 : http-post ( content-type content url -- response string )
-    <post-request> http-request contents ;
+    <post-request> http-request do-chunked-encoding string-or-contents ;
index d1ffce721d9854026bdba407dda9ff57ad21e782..3a5063033545d464c99852a0fc93b33560d51fb1 100755 (executable)
@@ -24,6 +24,8 @@ IN: http.tests
 [ "/bar" ] [ "http://foo.com/bar" url>path ] unit-test
 [ "/bar" ] [ "/bar" url>path ] unit-test
 
+: lf>crlf "\n" split "\r\n" join ;
+
 STRING: read-request-test-1
 GET http://foo/bar HTTP/1.1
 Some-Header: 1
@@ -45,7 +47,7 @@ blah
         cookies: V{ }
     }
 ] [
-    read-request-test-1 [
+    read-request-test-1 lf>crlf [
         read-request
     ] with-string-reader
 ] unit-test
@@ -59,7 +61,7 @@ blah
 ;
 
 read-request-test-1' 1array [
-    read-request-test-1
+    read-request-test-1 lf>crlf
     [ read-request ] with-string-reader
     [ write-request ] with-string-writer
     ! normalize crlf
@@ -69,6 +71,7 @@ read-request-test-1' 1array [
 STRING: read-request-test-2
 HEAD  http://foo/bar   HTTP/1.1
 Host: www.sex.com
+
 ;
 
 [
@@ -83,7 +86,7 @@ Host: www.sex.com
         cookies: V{ }
     }
 ] [
-    read-request-test-2 [
+    read-request-test-2 lf>crlf [
         read-request
     ] with-string-reader
 ] unit-test
@@ -104,7 +107,7 @@ blah
         cookies: V{ }
     }
 ] [
-    read-response-test-1
+    read-response-test-1 lf>crlf
     [ read-response ] with-string-reader
 ] unit-test
 
@@ -117,7 +120,7 @@ content-type: text/html
 ;
 
 read-response-test-1' 1array [
-    read-response-test-1
+    read-response-test-1 lf>crlf
     [ read-response ] with-string-reader
     [ write-response ] with-string-writer
     ! normalize crlf
@@ -143,6 +146,9 @@ io.encodings.ascii ;
             <dispatcher>
                 "extra/http/test" resource-path <static> >>default
             "nested" add-responder
+            <action>
+                [ "redirect-loop" f <permanent-redirect> ] >>display
+            "redirect-loop" add-responder
         main-responder set
 
         [ 1237 httpd ] "HTTPD test" spawn drop
@@ -159,11 +165,14 @@ io.encodings.ascii ;
     "localhost" 1237 <inet> ascii <client> [
         "GET nested HTTP/1.0\r\n" write flush
         "\r\n" write flush
-        readln drop
-        read-header USE: prettyprint
-    ] with-stream dup . "location" swap at "/" head?
+        read-crlf drop
+        read-header
+    ] with-stream "location" swap at "/" head?
 ] unit-test
 
+[ "http://localhost:1237/redirect-loop" http-get ]
+[ too-many-redirects? ] must-fail-with
+
 [ "Goodbye" ] [
     "http://localhost:1237/quit" http-get
 ] unit-test
index e792802b5abaa1eb645ab2a69ad236fc79d0186f..3e81fccd24b620cb61551f3eb6dc106a06477f35 100755 (executable)
@@ -1,10 +1,18 @@
 ! Copyright (C) 2003, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: fry hashtables io io.streams.string kernel math sets
-namespaces math.parser assocs sequences strings splitting ascii
-io.encodings.utf8 io.encodings.string namespaces unicode.case
-combinators vectors sorting accessors calendar
-calendar.format quotations arrays combinators.lib byte-arrays ;
+USING: accessors kernel combinators math namespaces
+
+assocs sequences splitting sorting sets debugger
+strings vectors hashtables quotations arrays byte-arrays
+math.parser calendar calendar.format
+
+io io.streams.string io.encodings.utf8 io.encodings.string
+io.sockets
+
+unicode.case unicode.categories qualified ;
+
+EXCLUDE: fry => , ;
+
 IN: http
 
 : http-port 80 ; inline
@@ -13,11 +21,12 @@ IN: http
     #! In a URL, can this character be used without
     #! URL-encoding?
     {
-        [ dup letter? ]
-        [ dup LETTER? ]
-        [ dup digit? ]
-        [ dup "/_-.:" member? ]
-    } || nip ; foldable
+        { [ dup letter? ] [ t ] }
+        { [ dup LETTER? ] [ t ] }
+        { [ dup digit? ] [ t ] }
+        { [ dup "/_-.:" member? ] [ t ] }
+        [ f ]
+    } cond nip ; foldable
 
 : push-utf8 ( ch -- )
     1string utf8 encode
@@ -75,8 +84,15 @@ IN: http
         ] if
     ] if ;
 
+: read-lf ( -- string )
+    "\n" read-until CHAR: \n assert= ;
+
+: read-crlf ( -- string )
+    "\r" read-until
+    [ CHAR: \r assert= read1 CHAR: \n assert= ] when* ;
+
 : read-header-line ( -- )
-    readln dup
+    read-crlf dup
     empty? [ drop ] [ header-line read-header-line ] if ;
 
 : read-header ( -- assoc )
@@ -175,13 +191,17 @@ post-data
 post-data-type
 cookies ;
 
+: set-header ( request/response value key -- request/response )
+    pick header>> set-at ;
+
 : <request>
     request new
         "1.1" >>version
         http-port >>port
         H{ } clone >>header
         H{ } clone >>query
-        V{ } clone >>cookies ;
+        V{ } clone >>cookies
+        "close" "connection" set-header ;
 
 : query-param ( request key -- value )
     swap query>> at ;
@@ -220,7 +240,7 @@ cookies ;
     dup { "1.0" "1.1" } member? [ "Bad version" throw ] unless ;
 
 : read-request-version ( request -- request )
-    readln [ CHAR: \s = ] left-trim
+    read-crlf [ CHAR: \s = ] left-trim
     parse-version
     >>version ;
 
@@ -295,9 +315,15 @@ SYMBOL: max-post-request
         "application/x-www-form-urlencoded" >>post-data-type
     ] if ;
 
+: request-addr ( request -- addr )
+    [ host>> ] [ port>> ] bi <inet> ;
+
+: request-host ( request -- string )
+    [ host>> ] [ drop ":" ] [ port>> number>string ] tri 3append ;
+
 : write-request-header ( request -- request )
     dup header>> >hashtable
-    over host>> [ "host" pick set-at ] when*
+    over host>> [ over request-host "host" pick set-at ] when
     over post-data>> [ length "content-length" pick set-at ] when*
     over post-data-type>> [ "content-type" pick set-at ] when*
     over cookies>> f like [ unparse-cookies "cookie" pick set-at ] when*
@@ -330,9 +356,6 @@ SYMBOL: max-post-request
         tri
     ] with-string-writer ;
 
-: set-header ( request/response value key -- request/response )
-    pick header>> set-at ;
-
 GENERIC: write-response ( response -- )
 
 GENERIC: write-full-response ( request response -- )
@@ -347,11 +370,11 @@ body ;
 
 : <response>
     response new
-    "1.1" >>version
-    H{ } clone >>header
-    "close" "connection" set-header
-    now timestamp>http-string "date" set-header
-    V{ } clone >>cookies ;
+        "1.1" >>version
+        H{ } clone >>header
+        "close" "connection" set-header
+        now timestamp>http-string "date" set-header
+        V{ } clone >>cookies ;
 
 : read-response-version
     " \t" read-until
@@ -365,7 +388,7 @@ body ;
     >>code ;
 
 : read-response-message
-    readln >>message ;
+    read-crlf >>message ;
 
 : read-response-header
     read-header >>header
@@ -394,13 +417,18 @@ body ;
     [ unparse-cookies "set-cookie" pick set-at ] when*
     write-header ;
 
+GENERIC: write-response-body* ( body -- )
+
+M: f write-response-body* drop ;
+
+M: string write-response-body* write ;
+
+M: callable write-response-body* call ;
+
+M: object write-response-body* stdio get stream-copy ;
+
 : write-response-body ( response -- response )
-    dup body>> {
-        { [ dup not ] [ drop ] }
-        { [ dup string? ] [ write ] }
-        { [ dup callable? ] [ call ] }
-        [ stdio get stream-copy ]
-    } cond ;
+    dup body>> write-response-body* ;
 
 M: response write-response ( respose -- )
     write-response-version
index ebf8e8770b53049752fec800e1a09ae21ebd1335..90e632d7f5445042fe7454fd94b378482a7eaef0 100755 (executable)
@@ -1,7 +1,7 @@
 IN: http.server.actions.tests
 USING: http.server.actions http.server.validators
 tools.test math math.parser multiline namespaces http
-io.streams.string http.server sequences accessors ;
+io.streams.string http.server sequences splitting accessors ;
 
 [
     "a" [ v-number ] { { "a" "123" } } validate-param
@@ -13,6 +13,8 @@ io.streams.string http.server sequences accessors ;
     { { "a" [ v-number ] } { "b" [ v-number ] } } >>get-params
 "action-1" set
 
+: lf>crlf "\n" split "\r\n" join ;
+
 STRING: action-request-test-1
 GET http://foo/bar?a=12&b=13 HTTP/1.1
 
@@ -20,7 +22,8 @@ blah
 ;
 
 [ 25 ] [
-    action-request-test-1 [ read-request ] with-string-reader
+    action-request-test-1 lf>crlf
+    [ read-request ] with-string-reader
     request set
     "/blah"
     "action-1" get call-responder
@@ -40,7 +43,8 @@ xxx=4
 ;
 
 [ "/blahXXXX" ] [
-    action-request-test-2 [ read-request ] with-string-reader
+    action-request-test-2 lf>crlf
+    [ read-request ] with-string-reader
     request set
     "/blah"
     "action-2" get call-responder
diff --git a/extra/http/server/auth/login/boilerplate.xml b/extra/http/server/auth/login/boilerplate.xml
new file mode 100644 (file)
index 0000000..edc8c32
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <h1><t:write-title /></h1>
+
+       <t:call-next-template />
+
+</t:chloe>
diff --git a/extra/http/server/auth/login/edit-profile.fhtml b/extra/http/server/auth/login/edit-profile.fhtml
deleted file mode 100755 (executable)
index 7d94ca1..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-<% USING: http.server.components http.server.auth.login\r
-http.server namespaces kernel combinators ; %>\r
-<html>\r
-<body>\r
-<h1>Edit profile</h1>\r
-\r
-<form method="POST" action="edit-profile">\r
-<% hidden-form-field %>\r
-\r
-<table>\r
-\r
-<tr>\r
-<td>User name:</td>\r
-<td><% "username" component render-view %></td>\r
-</tr>\r
-\r
-<tr>\r
-<td>Real name:</td>\r
-<td><% "realname" component render-edit %></td>\r
-</tr>\r
-\r
-<tr>\r
-<td></td>\r
-<td>Specifying a real name is optional.</td>\r
-</tr>\r
-\r
-<tr>\r
-<td>Current password:</td>\r
-<td><% "password" component render-edit %></td>\r
-</tr>\r
-\r
-<tr>\r
-<td></td>\r
-<td>If you don't want to change your current password, leave this field blank.</td>\r
-</tr>\r
-\r
-<tr>\r
-<td>New password:</td>\r
-<td><% "new-password" component render-edit %></td>\r
-</tr>\r
-\r
-<tr>\r
-<td>Verify:</td>\r
-<td><% "verify-password" component render-edit %></td>\r
-</tr>\r
-\r
-<tr>\r
-<td></td>\r
-<td>If you are changing your password, enter it twice to ensure it is correct.</td>\r
-</tr>\r
-\r
-<tr>\r
-<td>E-mail:</td>\r
-<td><% "email" component render-edit %></td>\r
-</tr>\r
-\r
-<tr>\r
-<td></td>\r
-<td>Specifying an e-mail address is optional. It enables the "recover password" feature.</td>\r
-</tr>\r
-\r
-</table>\r
-\r
-<p><input type="submit" value="Update" />\r
-\r
-<% {\r
-    { [ login-failed? get ] [ "invalid password" render-error ] }\r
-    { [ password-mismatch? get ] [ "passwords do not match" render-error ] }\r
-    { [ t ] [ ] }\r
-} cond %>\r
-\r
-</p>\r
-\r
-</form>\r
-\r
-</body>\r
-</html>\r
diff --git a/extra/http/server/auth/login/edit-profile.xml b/extra/http/server/auth/login/edit-profile.xml
new file mode 100644 (file)
index 0000000..86a4e86
--- /dev/null
@@ -0,0 +1,77 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <t:title>Edit Profile</t:title>
+
+       <t:form action="edit-profile">
+
+       <table>
+       
+       <tr>
+               <th class="field-label">User name:</th>
+               <td><t:view component="username" /></td>
+       </tr>
+       
+       <tr>
+               <th class="field-label">Real name:</th>
+               <td><t:edit component="realname" /></td>
+       </tr>
+       
+       <tr>
+               <td></td>
+               <td>Specifying a real name is optional.</td>
+       </tr>
+       
+       <tr>
+               <th class="field-label">Current password:</th>
+               <td><t:edit component="password" /></td>
+       </tr>
+       
+       <tr>
+               <td></td>
+               <td>If you don't want to change your current password, leave this field blank.</td>
+       </tr>
+       
+       <tr>
+               <th class="field-label">New password:</th>
+               <td><t:edit component="new-password" /></td>
+       </tr>
+       
+       <tr>
+               <th class="field-label">Verify:</th>
+               <td><t:edit component="verify-password" /></td>
+       </tr>
+       
+       <tr>
+               <td></td>
+               <td>If you are changing your password, enter it twice to ensure it is correct.</td>
+       </tr>
+       
+       <tr>
+               <th class="field-label">E-mail:</th>
+               <td><t:edit component="email" /></td>
+       </tr>
+       
+       <tr>
+               <td></td>
+               <td>Specifying an e-mail address is optional. It enables the "recover password" feature.</td>
+       </tr>
+       
+       </table>
+
+       <p>
+               <input type="submit" value="Update" />
+
+               <t:if var="http.server.auth.login:login-failed?">
+                       <t:error>invalid password</t:error>
+               </t:if>
+               
+               <t:if var="http.server.auth.login:password-mismatch?">
+                       <t:error>passwords do not match</t:error>
+               </t:if>
+       </p>
+
+       </t:form>
+       
+</t:chloe>
index 4f04a1ff9b853e50b9dae245a7d4527e70b545c8..7593f217f7dd17a7655d5a935065e2a89cbb1226 100755 (executable)
@@ -15,7 +15,9 @@ http.server.actions
 http.server.components\r
 http.server.forms\r
 http.server.sessions\r
-http.server.templating.fhtml\r
+http.server.boilerplate\r
+http.server.templating\r
+http.server.templating.chloe\r
 http.server.validators ;\r
 IN: http.server.auth.login\r
 QUALIFIED: smtp\r
@@ -40,11 +42,15 @@ M: user-saver dispose
 : save-user-after ( user -- )\r
     <user-saver> add-always-destructor ;\r
 \r
+: login-template ( name -- template )\r
+    "resource:extra/http/server/auth/login/" swap ".xml"\r
+    3append <chloe> ;\r
+\r
 ! ! ! Login\r
 \r
 : <login-form>\r
     "login" <form>\r
-        "resource:extra/http/server/auth/login/login.fhtml" >>edit-template\r
+        "login" login-template >>edit-template\r
         "username" <username>\r
             t >>required\r
             add-field\r
@@ -62,10 +68,7 @@ M: user-saver dispose
         <action>\r
             [ blank-values ] >>init\r
 \r
-            [\r
-                "text/html" <content>\r
-                [ form edit-form ] >>body\r
-            ] >>display\r
+            [ form edit-form ] >>display\r
 \r
             [\r
                 blank-values\r
@@ -86,7 +89,7 @@ M: user-saver dispose
 \r
 : <register-form> ( -- form )\r
     "register" <form>\r
-        "resource:extra/http/server/auth/login/register.fhtml" >>edit-template\r
+        "register" login-template >>edit-template\r
         "username" <username>\r
             t >>required\r
             add-field\r
@@ -114,10 +117,7 @@ SYMBOL: user-exists?
         <action>\r
             [ blank-values ] >>init\r
 \r
-            [\r
-                "text/html" <content>\r
-                [ form edit-form ] >>body\r
-            ] >>display\r
+            [ form edit-form ] >>display\r
 \r
             [\r
                 blank-values\r
@@ -147,7 +147,7 @@ SYMBOL: user-exists?
 \r
 : <edit-profile-form> ( -- form )\r
     "edit-profile" <form>\r
-        "resource:extra/http/server/auth/login/edit-profile.fhtml" >>edit-template\r
+        "edit-profile" login-template >>edit-template\r
         "username" <username> add-field\r
         "realname" <string> add-field\r
         "password" <password> add-field\r
@@ -168,10 +168,7 @@ SYMBOL: previous-page
                 dup email>> "email" set-value\r
             ] >>init\r
 \r
-            [\r
-                "text/html" <content>\r
-                [ form edit-form ] >>body\r
-            ] >>display\r
+            [ form edit-form ] >>display\r
 \r
             [\r
                 blank-values\r
@@ -242,7 +239,7 @@ SYMBOL: lost-password-from
 \r
 : <recover-form-1> ( -- form )\r
     "register" <form>\r
-        "resource:extra/http/server/auth/login/recover-1.fhtml" >>edit-template\r
+        "recover-1" login-template >>edit-template\r
         "username" <username>\r
             t >>required\r
             add-field\r
@@ -256,10 +253,7 @@ SYMBOL: lost-password-from
         <action>\r
             [ blank-values ] >>init\r
 \r
-            [\r
-                "text/html" <content>\r
-                [ form edit-form ] >>body\r
-            ] >>display\r
+            [ form edit-form ] >>display\r
 \r
             [\r
                 blank-values\r
@@ -271,13 +265,13 @@ SYMBOL: lost-password-from
                     send-password-email\r
                 ] when*\r
 \r
-                "resource:extra/http/server/auth/login/recover-2.fhtml" serve-template\r
+                "recover-2" login-template serve-template\r
             ] >>submit\r
     ] ;\r
 \r
 : <recover-form-3>\r
     "new-password" <form>\r
-        "resource:extra/http/server/auth/login/recover-3.fhtml" >>edit-template\r
+        "recover-3" login-template >>edit-template\r
         "username" <username>\r
             hidden >>renderer\r
             t >>required\r
@@ -308,10 +302,7 @@ SYMBOL: lost-password-from
                 ] H{ } make-assoc values set\r
             ] >>init\r
 \r
-            [\r
-                "text/html" <content>\r
-                [ <recover-form-3> edit-form ] >>body\r
-            ] >>display\r
+            [ <recover-form-3> edit-form ] >>display\r
 \r
             [\r
                 blank-values\r
@@ -326,8 +317,7 @@ SYMBOL: lost-password-from
                     "new-password" value >>password\r
                     users update-user\r
 \r
-                    "resource:extra/http/server/auth/login/recover-4.fhtml"\r
-                    serve-template\r
+                    "recover-4" login-template serve-template\r
                 ] [\r
                     <400>\r
                 ] if*\r
@@ -367,24 +357,32 @@ M: login call-responder ( path responder -- response )
     dup login set\r
     call-next-method ;\r
 \r
+: <login-boilerplate> ( responder -- responder' )\r
+    <boilerplate>\r
+        "boilerplate" login-template >>template ;\r
+\r
 : <login> ( responder -- auth )\r
     login new-dispatcher\r
-        swap <protected> >>default\r
-        <login-action> "login" add-responder\r
-        <logout-action> "logout" add-responder\r
+        swap >>default\r
+        <login-action> <login-boilerplate> "login" add-responder\r
+        <logout-action> <login-boilerplate> "logout" add-responder\r
         no-users >>users ;\r
 \r
 ! ! ! Configuration\r
 \r
 : allow-edit-profile ( login -- login )\r
-    <edit-profile-action> <protected> "edit-profile" add-responder ;\r
+    <edit-profile-action> <protected> <login-boilerplate>\r
+        "edit-profile" add-responder ;\r
 \r
 : allow-registration ( login -- login )\r
-    <register-action> "register" add-responder ;\r
+    <register-action> <login-boilerplate>\r
+        "register" add-responder ;\r
 \r
 : allow-password-recovery ( login -- login )\r
-    <recover-action-1> "recover-password" add-responder\r
-    <recover-action-3> "new-password" add-responder ;\r
+    <recover-action-1> <login-boilerplate>\r
+        "recover-password" add-responder\r
+    <recover-action-3> <login-boilerplate>\r
+        "new-password" add-responder ;\r
 \r
 : allow-edit-profile? ( -- ? )\r
     login get responders>> "edit-profile" swap key? ;\r
diff --git a/extra/http/server/auth/login/login.fhtml b/extra/http/server/auth/login/login.fhtml
deleted file mode 100755 (executable)
index 0720171..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-<% USING: http.server.auth.login http.server.components http.server\r
-kernel namespaces ; %>\r
-<html>\r
-<body>\r
-<h1>Login required</h1>\r
-\r
-<form method="POST" action="login">\r
-\r
-<% hidden-form-field %>\r
-\r
-<table>\r
-\r
-<tr>\r
-<td>User name:</td>\r
-<td><% "username" component render-edit %></td>\r
-</tr>\r
-\r
-<tr>\r
-<td>Password:</td>\r
-<td><% "password" component render-edit %></td>\r
-</tr>\r
-\r
-</table>\r
-\r
-<p><input type="submit" value="Log in" />\r
-<%\r
-login-failed? get\r
-[ "Invalid username or password" render-error ] when\r
-%>\r
-</p>\r
-\r
-</form>\r
-\r
-<p>\r
-<% allow-registration? [ %>\r
-    <a href="<% "register" f write-link %>">Register</a>\r
-<% ] when %>\r
-<% allow-password-recovery? [ %>\r
-    <a href="<% "recover-password" f write-link %>">\r
-       Recover Password\r
-    </a>\r
-<% ] when %>\r
-</p>\r
-\r
-</body>\r
-</html>\r
diff --git a/extra/http/server/auth/login/login.xml b/extra/http/server/auth/login/login.xml
new file mode 100644 (file)
index 0000000..2f16c09
--- /dev/null
@@ -0,0 +1,44 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <t:title>Login</t:title>
+
+       <t:form action="login">
+
+               <table>
+
+                       <tr>
+                               <th class="field-label">User name:</th>
+                               <td><t:edit component="username" /></td>
+                       </tr>
+
+                       <tr>
+                               <th class="field-label">Password:</th>
+                               <td><t:edit component="password" /></td>
+                       </tr>
+
+               </table>
+
+               <p>
+
+                       <input type="submit" value="Log in" />
+
+                       <t:if var="http.server.auth.login:login-failed?">
+                               <t:error>invalid username or password</t:error>
+                       </t:if>
+               </p>
+
+       </t:form>
+
+       <p>
+               <t:if code="http.server.auth.login:login-failed?">
+                       <t:a href="register">Register</t:a>
+               </t:if>
+               |
+               <t:if code="http.server.auth.login:allow-password-recovery?">
+                       <t:a href="recover-password">Recover Password</t:a>
+               </t:if>
+       </p>
+
+</t:chloe>
diff --git a/extra/http/server/auth/login/recover-1.fhtml b/extra/http/server/auth/login/recover-1.fhtml
deleted file mode 100755 (executable)
index 8ec01f2..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-<% USING: http.server.components http.server ; %>\r
-<html>\r
-<body>\r
-<h1>Recover lost password: step 1 of 4</h1>\r
-\r
-<p>Enter the username and e-mail address you used to register for this site, and you will receive a link for activating a new password.</p>\r
-\r
-<form method="POST" action="recover-password">\r
-\r
-<% hidden-form-field %>\r
-\r
-<table>\r
-\r
-<tr>\r
-<td>User name:</td>\r
-<td><% "username" component render-edit %></td>\r
-</tr>\r
-\r
-<tr>\r
-<td>E-mail:</td>\r
-<td><% "email" component render-edit %></td>\r
-</tr>\r
-\r
-<tr>\r
-<td>Captcha:</td>\r
-<td><% "captcha" component render-edit %></td>\r
-</tr>\r
-\r
-<tr>\r
-<td></td>\r
-<td>Leave the captcha blank. Spam-bots will fill it indiscriminantly, so their attempts to e-mail you will be blocked.</td>\r
-</tr>\r
-\r
-</table>\r
-\r
-<input type="submit" value="Recover password" />\r
-\r
-</form>\r
-\r
-</body>\r
-</html>\r
diff --git a/extra/http/server/auth/login/recover-1.xml b/extra/http/server/auth/login/recover-1.xml
new file mode 100644 (file)
index 0000000..dd3a60f
--- /dev/null
@@ -0,0 +1,39 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <t:title>Recover lost password: step 1 of 4</t:title>
+
+       <p>Enter the username and e-mail address you used to register for this site, and you will receive a link for activating a new password.</p>
+
+       <t:form action="recover-password">
+
+               <table>
+
+               <tr>
+               <th class="field-label">User name:</th>
+               <td><t:edit component="username" /></td>
+               </tr>
+
+               <tr>
+               <th class="field-label">E-mail:</th>
+               <td><t:edit component="email" /></td>
+               </tr>
+
+               <tr>
+               <th class="field-label">Captcha:</th>
+               <td><t:edit component="captcha" /></td>
+               </tr>
+
+               <tr>
+               <td></td>
+               <td>Leave the captcha blank. Spam-bots will fill it indiscriminantly, so their attempts to e-mail you will be blocked.</td>
+               </tr>
+
+               </table>
+
+               <input type="submit" value="Recover password" />
+
+       </t:form>
+
+</t:chloe>
diff --git a/extra/http/server/auth/login/recover-2.fhtml b/extra/http/server/auth/login/recover-2.fhtml
deleted file mode 100755 (executable)
index 9b13734..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<% USING: http.server.components ; %>\r
-<html>\r
-<body>\r
-<h1>Recover lost password: step 2 of 4</h1>\r
-\r
-<p>If you entered the correct username and e-mail address, you should receive an e-mail shortly. Click the link in the e-mail for further instructions.</p>\r
-\r
-</body>\r
-</html>\r
diff --git a/extra/http/server/auth/login/recover-2.xml b/extra/http/server/auth/login/recover-2.xml
new file mode 100644 (file)
index 0000000..c7819bd
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <t:title>Recover lost password: step 2 of 4</t:title>
+
+       <p>If you entered the correct username and e-mail address, you should receive an e-mail shortly. Click the link in the e-mail for further instructions.</p>
+
+</t:chloe>
diff --git a/extra/http/server/auth/login/recover-3.fhtml b/extra/http/server/auth/login/recover-3.fhtml
deleted file mode 100755 (executable)
index ca4823b..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-<% USING: http.server.components http.server.auth.login http.server\r
-namespaces kernel combinators ; %>\r
-<html>\r
-<body>\r
-<h1>Recover lost password: step 3 of 4</h1>\r
-\r
-<p>Choose a new password for your account.</p>\r
-\r
-<form method="POST" action="new-password">\r
-\r
-<% hidden-form-field %>\r
-\r
-<table>\r
-\r
-<% "username" component render-edit %>\r
-<% "ticket" component render-edit %>\r
-\r
-<tr>\r
-<td>Password:</td>\r
-<td><% "new-password" component render-edit %></td>\r
-</tr>\r
-\r
-<tr>\r
-<td>Verify password:</td>\r
-<td><% "verify-password" component render-edit %></td>\r
-</tr>\r
-\r
-<tr>\r
-<td></td>\r
-<td>Enter your password twice to ensure it is correct.</td>\r
-</tr>\r
-\r
-</table>\r
-\r
-<p><input type="submit" value="Set password" />\r
-\r
-<% password-mismatch? get [\r
-    "passwords do not match" render-error\r
-] when %>\r
-\r
-</p>\r
-\r
-</form>\r
-\r
-</body>\r
-</html>\r
diff --git a/extra/http/server/auth/login/recover-3.xml b/extra/http/server/auth/login/recover-3.xml
new file mode 100644 (file)
index 0000000..115c2ce
--- /dev/null
@@ -0,0 +1,43 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <t:title>Recover lost password: step 3 of 4</t:title>
+
+       <p>Choose a new password for your account.</p>
+
+       <t:form action="new-password">
+
+               <table>
+
+                       <t:edit component="username" />
+                       <t:edit component="ticket" />
+
+                       <tr>
+                       <th class="field-label">Password:</th>
+                       <td><t:edit component="new-password" /></td>
+                       </tr>
+
+                       <tr>
+                       <th class="field-label">Verify password:</th>
+                       <td><t:edit component="verify-password" /></td>
+                       </tr>
+
+                       <tr>
+                       <td></td>
+                       <td>Enter your password twice to ensure it is correct.</td>
+                       </tr>
+
+               </table>
+
+               <p>
+                       <input type="submit" value="Set password" />
+
+                       <t:if var="http.server.auth.login:password-mismatch?">
+                               <t:error>passwords do not match</t:error>
+                       </t:if>
+               </p>
+
+       </t:form>
+
+</t:chloe>
diff --git a/extra/http/server/auth/login/recover-4.fhtml b/extra/http/server/auth/login/recover-4.fhtml
deleted file mode 100755 (executable)
index 239d71d..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<% USING: http.server ; %>\r
-<html>\r
-<body>\r
-<h1>Recover lost password: step 4 of 4</h1>\r
-\r
-<p>Your password has been reset.\r
-You may now <a href="<% "login" f write-link %>">log in</a>.</p>\r
-\r
-</body>\r
-</html>\r
diff --git a/extra/http/server/auth/login/recover-4.xml b/extra/http/server/auth/login/recover-4.xml
new file mode 100755 (executable)
index 0000000..3c10869
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version='1.0' ?>\r
+\r
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">\r
+\r
+       <t:title>Recover lost password: step 4 of 4</t:title>\r
+\r
+       <p>Your password has been reset. You may now <t:a href="login">log in</t:a>.</p>\r
+\r
+</t:chloe>\r
diff --git a/extra/http/server/auth/login/register.fhtml b/extra/http/server/auth/login/register.fhtml
deleted file mode 100755 (executable)
index 9106497..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-<% USING: http.server.components http.server.auth.login\r
-http.server namespaces kernel combinators ; %>\r
-<html>\r
-<body>\r
-<h1>New user registration</h1>\r
-\r
-<form method="POST" action="register">\r
-<% hidden-form-field %>\r
-\r
-<table>\r
-\r
-<tr>\r
-<td>User name:</td>\r
-<td><% "username" component render-edit %></td>\r
-</tr>\r
-\r
-<tr>\r
-<td>Real name:</td>\r
-<td><% "realname" component render-edit %></td>\r
-</tr>\r
-\r
-<tr>\r
-<td></td>\r
-<td>Specifying a real name is optional.</td>\r
-</tr>\r
-\r
-<tr>\r
-<td>Password:</td>\r
-<td><% "new-password" component render-edit %></td>\r
-</tr>\r
-\r
-<tr>\r
-<td>Verify:</td>\r
-<td><% "verify-password" component render-edit %></td>\r
-</tr>\r
-\r
-<tr>\r
-<td></td>\r
-<td>Enter your password twice to ensure it is correct.</td>\r
-</tr>\r
-\r
-<tr>\r
-<td>E-mail:</td>\r
-<td><% "email" component render-edit %></td>\r
-</tr>\r
-\r
-<tr>\r
-<td></td>\r
-<td>Specifying an e-mail address is optional. It enables the "recover password" feature.</td>\r
-</tr>\r
-\r
-<tr>\r
-<td>Captcha:</td>\r
-<td><% "captcha" component render-edit %></td>\r
-</tr>\r
-\r
-<tr>\r
-<td></td>\r
-<td>Leave the captcha blank. Spam-bots will fill it indiscriminantly, so their attempts to register will be blocked.</td>\r
-</tr>\r
-\r
-</table>\r
-\r
-<p><input type="submit" value="Register" />\r
-\r
-<% {\r
-    { [ password-mismatch? get ] [ "passwords do not match" render-error ] }\r
-    { [ user-exists? get ] [ "username taken" render-error ] }\r
-    { [ t ] [ ] }\r
-} cond %>\r
-\r
-</p>\r
-\r
-</form>\r
-\r
-</body>\r
-</html>\r
diff --git a/extra/http/server/auth/login/register.xml b/extra/http/server/auth/login/register.xml
new file mode 100644 (file)
index 0000000..1bacf71
--- /dev/null
@@ -0,0 +1,79 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <t:title>New User Registration</t:title>
+
+       <t:form action="register">
+
+               <table>
+
+               <tr>
+               <th class="field-label">User name:</th>
+               <td><t:edit component="username" /></td>
+               </tr>
+
+               <tr>
+               <th class="field-label">Real name:</th>
+               <td><t:edit component="realname" /></td>
+               </tr>
+
+               <tr>
+               <td></td>
+               <td>Specifying a real name is optional.</td>
+               </tr>
+
+               <tr>
+               <th class="field-label">Password:</th>
+               <td><t:edit component="new-password" /></td>
+               </tr>
+
+               <tr>
+               <th class="field-label">Verify:</th>
+               <td><t:edit component="verify-password" /></td>
+               </tr>
+
+               <tr>
+               <td></td>
+               <td>Enter your password twice to ensure it is correct.</td>
+               </tr>
+
+               <tr>
+               <th class="field-label">E-mail:</th>
+               <td><t:edit component="email" /></td>
+               </tr>
+
+               <tr>
+               <td></td>
+               <td>Specifying an e-mail address is optional. It enables the "recover password" feature.</td>
+               </tr>
+
+               <tr>
+               <th class="field-label">Captcha:</th>
+               <td><t:edit component="captcha" /></td>
+               </tr>
+
+               <tr>
+               <td></td>
+               <td>Leave the captcha blank. Spam-bots will fill it indiscriminantly, so their attempts to register will be blocked.</td>
+               </tr>
+
+               </table>
+
+               <p>
+
+                       <input type="submit" value="Register" />
+
+                       <t:if var="http.server.auth.login:user-exists?">
+                               <t:error>username taken</t:error>
+                       </t:if>
+
+                       <t:if var="http.server.auth.login:password-mismatch?">
+                               <t:error>passwords do not match</t:error>
+                       </t:if>
+
+               </p>
+
+       </t:form>
+
+</t:chloe>
diff --git a/extra/http/server/boilerplate/boilerplate.factor b/extra/http/server/boilerplate/boilerplate.factor
new file mode 100644 (file)
index 0000000..eabcefe
--- /dev/null
@@ -0,0 +1,75 @@
+! Copyright (c) 2008 Slava Pestov
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors kernel namespaces boxes sequences strings
+io io.streams.string arrays
+html.elements
+http
+http.server
+http.server.templating ;
+IN: http.server.boilerplate
+
+TUPLE: boilerplate responder template ;
+
+: <boilerplate> f boilerplate boa ;
+
+SYMBOL: title
+
+: set-title ( string -- )
+    title get >box ;
+
+: write-title ( -- )
+    title get value>> write ;
+
+SYMBOL: style
+
+: add-style ( string -- )
+    "\n" style get push-all
+         style get push-all ;
+
+: write-style ( -- )
+    style get >string write ;
+
+SYMBOL: atom-feed
+
+: set-atom-feed ( title url -- )
+    2array atom-feed get >box ;
+
+: write-atom-feed ( -- )
+    atom-feed get value>> [
+        <link "alternate" =rel "application/atom+xml" =type
+        [ first =title ] [ second =href ] bi
+        link/>
+    ] when* ;
+
+SYMBOL: nested-template?
+
+SYMBOL: next-template
+
+: call-next-template ( -- )
+    next-template get write ;
+
+M: f call-template* drop call-next-template ;
+
+: with-boilerplate ( body template -- )
+    [
+        title get [ <box> title set ] unless
+        atom-feed get [ <box> atom-feed set ] unless
+        style get [ SBUF" " clone style set ] unless
+
+        [
+            [
+                nested-template? on
+                write-response-body*
+            ] with-string-writer
+            next-template set
+        ]
+        [ call-template ]
+        bi*
+    ] with-scope ; inline
+
+M: boilerplate call-responder
+    tuck responder>> call-responder
+    dup "content-type" header "text/html" = [
+        clone swap template>>
+        [ [ with-boilerplate ] 2curry ] curry change-body
+    ] [ nip ] if ;
index f1c43fe8ae58a5207edf1594266f3f6263b0d551..ff87bb71fb4d86d4a95237e04c0fa6bc778b0b9f 100755 (executable)
@@ -1,11 +1,10 @@
 IN: http.server.components.tests\r
 USING: http.server.components http.server.forms\r
 http.server.validators namespaces tools.test kernel accessors\r
-tuple-syntax mirrors http.server.actions\r
+tuple-syntax mirrors\r
+http http.server.actions http.server.templating.fhtml\r
 io.streams.string io.streams.null ;\r
 \r
-\ render-edit must-infer\r
-\r
 validation-failed? off\r
 \r
 [ 3 ] [ "3" "n" <number> validate ] unit-test\r
@@ -49,8 +48,8 @@ TUPLE: test-tuple text number more-text ;
 \r
 : <test-form> ( -- form )\r
     "test" <form>\r
-        "resource:extra/http/server/components/test/form.fhtml" >>view-template\r
-        "resource:extra/http/server/components/test/form.fhtml" >>edit-template\r
+        "resource:extra/http/server/components/test/form.fhtml" <fhtml> >>view-template\r
+        "resource:extra/http/server/components/test/form.fhtml" <fhtml> >>edit-template\r
         "text" <string>\r
             t >>required\r
             add-field\r
@@ -64,9 +63,9 @@ TUPLE: test-tuple text number more-text ;
             "hi" >>default\r
             add-field ;\r
 \r
-[ ] [ <test-tuple> <mirror> values set <test-form> view-form ] unit-test\r
+[ ] [ <test-tuple> <mirror> values set <test-form> view-form write-response-body drop ] unit-test\r
 \r
-[ ] [ <test-tuple> <mirror> values set <test-form> edit-form ] unit-test\r
+[ ] [ <test-tuple> <mirror> values set <test-form> edit-form write-response-body drop ] unit-test\r
 \r
 [ TUPLE{ test-tuple number: 123 more-text: "hi" } ] [\r
     <test-tuple> from-tuple\r
@@ -130,3 +129,5 @@ TUPLE: test-tuple text number more-text ;
 [ t ] [ "wake up sheeple" dup "n" <text> validate = ] unit-test\r
 \r
 [ ] [ "password" <password> "p" set ] unit-test\r
+\r
+[ ] [ "pub-date" <date> "d" set ] unit-test\r
index 1e5e33c4a02ea296dcd93ae87f2a1852a3305632..331231dfb303d20004efdde56e3dfae2158f45b1 100755 (executable)
@@ -1,15 +1,19 @@
 ! Copyright (C) 2008 Slava Pestov
 ! See http://factorcode.org/license.txt for BSD license.
-USING: html.elements http.server.validators accessors namespaces
-kernel io math.parser assocs classes words classes.tuple arrays
-sequences splitting mirrors hashtables fry combinators
-continuations math ;
+USING: accessors namespaces kernel io math.parser assocs classes
+words classes.tuple arrays sequences splitting mirrors
+hashtables fry combinators continuations math
+calendar.format html.elements
+http.server.validators ;
 IN: http.server.components
 
 ! Renderer protocol
+GENERIC: render-summary* ( value renderer -- )
 GENERIC: render-view* ( value renderer -- )
 GENERIC: render-edit* ( value id renderer -- )
 
+M: object render-summary* render-view* ;
+
 TUPLE: field type ;
 
 C: <field> field
@@ -56,9 +60,14 @@ SYMBOL: values
 
 : values-tuple values get mirror-object ;
 
+: render-view-or-summary ( component -- value renderer )
+    [ id>> value ] [ component-string ] [ renderer>> ] tri ;
+
 : render-view ( component -- )
-    [ id>> value ] [ component-string ] [ renderer>> ] tri
-    render-view* ;
+    render-view-or-summary render-view* ;
+
+: render-summary ( component -- )
+    render-view-or-summary render-summary* ;
 
 <PRIVATE
 
@@ -144,6 +153,17 @@ TUPLE: email < string ;
 M: email validate*
     call-next-method dup empty? [ v-email ] unless ;
 
+! URL fields
+TUPLE: url < string ;
+
+: <url> ( id -- component )
+    url new-string
+        5 >>min-length
+        60 >>max-length ;
+
+M: url validate*
+    call-next-method dup empty? [ v-url ] unless ;
+
 ! Don't send passwords back to the user
 TUPLE: password-renderer < field ;
 
@@ -203,22 +223,116 @@ M: captcha validate*
     drop v-captcha ;
 
 ! Text areas
-TUPLE: textarea-renderer ;
+TUPLE: text-renderer rows cols ;
 
-: textarea-renderer T{ textarea-renderer } ;
+: new-text-renderer ( class -- renderer )
+    new
+        60 >>cols
+        20 >>rows ;
 
-M: textarea-renderer render-view*
+: <text-renderer> ( -- renderer )
+    text-renderer new-text-renderer ;
+
+M: text-renderer render-view*
     drop write ;
 
-M: textarea-renderer render-edit*
-    drop <textarea [ =id ] [ =name ] bi textarea> write </textarea> ;
+M: text-renderer render-edit*
+    <textarea
+        [ rows>> [ number>string =rows ] when* ]
+        [ cols>> [ number>string =cols ] when* ] bi
+        [ =id   ]
+        [ =name ] bi
+    textarea>
+        write
+    </textarea> ;
 
 TUPLE: text < string ;
 
 : new-text ( id class -- component )
     new-string
         f >>one-line
-        textarea-renderer >>renderer ;
+        <text-renderer> >>renderer ;
 
 : <text> ( id -- component )
     text new-text ;
+
+! HTML text component
+TUPLE: html-text-renderer < text-renderer ;
+
+: <html-text-renderer> ( -- renderer )
+    html-text-renderer new-text-renderer ;
+
+M: html-text-renderer render-view*
+    drop write ;
+
+TUPLE: html-text < text ;
+
+: <html-text> ( id -- component )
+    html-text new-text
+        <html-text-renderer> >>renderer ;
+
+! Date component
+TUPLE: date < string ;
+
+: <date> ( id -- component )
+    date new-string ;
+
+M: date component-string
+    drop timestamp>string ;
+
+! Link components
+
+GENERIC: link-title ( obj -- string )
+GENERIC: link-href ( obj -- url )
+
+SINGLETON: link-renderer
+
+M: link-renderer render-view*
+    drop <a dup link-href =href a> link-title write </a> ;
+
+TUPLE: link < string ;
+
+: <link> ( id -- component )
+    link new-string
+        link-renderer >>renderer ;
+
+! List components
+SYMBOL: +plain+
+SYMBOL: +ordered+
+SYMBOL: +unordered+
+
+TUPLE: list-renderer component type ;
+
+C: <list-renderer> list-renderer
+
+: render-plain-list ( seq component quot -- )
+    '[ , component>> renderer>> @ ] each ; inline
+
+: render-li-list ( seq component quot -- )
+    '[ <li> @ </li> ] render-plain-list ; inline
+
+: render-ordered-list ( seq quot component -- )
+    <ol> render-li-list </ol> ; inline
+
+: render-unordered-list ( seq quot component -- )
+    <ul> render-li-list </ul> ; inline
+
+: render-list ( value renderer quot -- )
+    over type>> {
+        { +plain+     [ render-plain-list ] }
+        { +ordered+   [ render-ordered-list ] }
+        { +unordered+ [ render-unordered-list ] }
+    } case ; inline
+
+M: list-renderer render-view*
+    [ render-view* ] render-list ;
+
+M: list-renderer render-summary*
+    [ render-summary* ] render-list ;
+
+TUPLE: list < component ;
+
+: <list> ( id component type -- list )
+    <list-renderer> list swap new-component ;
+
+M: list component-string drop ;
index 65e159513d544a1f5ae76229bced4b47b92f3edc..a8d320f82f7fca8afd734aef9f8ee0777cca2407 100755 (executable)
@@ -4,13 +4,14 @@ USING: splitting kernel io sequences farkup accessors
 http.server.components ;\r
 IN: http.server.components.farkup\r
 \r
-TUPLE: farkup-renderer < textarea-renderer ;\r
+TUPLE: farkup-renderer < text-renderer ;\r
 \r
-: farkup-renderer T{ farkup-renderer } ;\r
+: <farkup-renderer> ( -- renderer )\r
+    farkup-renderer new-text-renderer ;\r
 \r
 M: farkup-renderer render-view*\r
     drop string-lines "\n" join convert-farkup write ;\r
 \r
 : <farkup> ( id -- component )\r
     <text>\r
-        farkup-renderer >>renderer ;\r
+        <farkup-renderer> >>renderer ;\r
index eb8ff943c7fcbc3eb19b2425a104f8e1dceab45e..65de881adbfad022dcbde17b34b962780aefc9a9 100755 (executable)
@@ -15,49 +15,33 @@ IN: http.server.crud
 
         [ "id" get ctor call select-tuple from-tuple ] >>init
 
-        [
-            "text/html" <content>
-            [ form view-form ] >>body
-        ] >>display ;
+        [ form view-form ] >>display ;
 
 : <id-redirect> ( id next -- response )
     swap number>string "id" associate <permanent-redirect> ;
 
-:: <create-action> ( form ctor next -- action )
+:: <edit-action> ( form ctor next -- action )
     <action>
-        [ f ctor call from-tuple form set-defaults ] >>init
+        { { "id" [ [ v-number ] v-optional ] } } >>get-params
 
         [
-            "text/html" <content>
-            [ form edit-form ] >>body
-        ] >>display
-
-        [
-            f ctor call from-tuple
+            "id" get ctor call
 
-            form validate-form
-
-            values-tuple insert-tuple
+            "id" get
+            [ select-tuple from-tuple ]
+            [ from-tuple form set-defaults ]
+            if
+        ] >>init
 
-            "id" value next <id-redirect>
-        ] >>submit ;
-
-:: <edit-action> ( form ctor next -- action )
-    <action>
-        { { "id" [ v-number ] } } >>get-params
-        [ "id" get ctor call select-tuple from-tuple ] >>init
-
-        [
-            "text/html" <content>
-            [ form edit-form ] >>body
-        ] >>display
+        [ form edit-form ] >>display
 
         [
             f ctor call from-tuple
 
             form validate-form
 
-            values-tuple update-tuple
+            values-tuple
+            "id" value [ update-tuple ] [ insert-tuple ] if
 
             "id" value next <id-redirect>
         ] >>submit ;
@@ -71,3 +55,13 @@ IN: http.server.crud
 
             next f <permanent-redirect>
         ] >>submit ;
+
+:: <list-action> ( form ctor -- action )
+    <action>
+        [
+            blank-values
+
+            f ctor call select-tuples "list" set-value
+
+            form view-form
+        ] >>display ;
index cf8fd4ca8c4ee786b4d45c2da34b1c109cde0b56..60f3da25b6c418e72ed3d067030eb623c92f3b06 100644 (file)
@@ -1,22 +1,31 @@
-USING: kernel accessors assocs namespaces io.files fry
+! Copyright (C) 2008 Slava Pestov
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel accessors assocs namespaces io.files sequences fry
+http.server
 http.server.actions
 http.server.components
 http.server.validators
-http.server.templating.fhtml ;
+http.server.templating ;
 IN: http.server.forms
 
-TUPLE: form < component view-template edit-template components ;
+TUPLE: form < component
+view-template edit-template summary-template
+components ;
 
 M: form init V{ } clone >>components ;
 
 : <form> ( id -- form )
-    form f new-component ;
+    form f new-component
+        dup >>renderer ;
 
 : add-field ( form component -- form )
     dup id>> pick components>> set-at ;
 
+: set-components ( form -- )
+    components>> components set ;
+
 : with-form ( form quot -- )
-    >r components>> components r> with-variable ; inline
+    [ [ set-components ] [ call ] bi* ] with-scope ; inline
 
 : set-defaults ( form -- )
     [
@@ -27,11 +36,16 @@ M: form init V{ } clone >>components ;
         ] assoc-each
     ] with-form ;
 
-: view-form ( form -- )
-    dup view-template>> '[ , run-template ] with-form ;
+: <form-response> ( form template -- response )
+    [ components>> components set ]
+    [ "text/html" <content> swap >>body ]
+    bi* ;
+
+: view-form ( form -- response )
+    dup view-template>> <form-response> ;
 
-: edit-form ( form -- )
-    dup edit-template>> '[ , run-template ] with-form ;
+: edit-form ( form -- response )
+    dup edit-template>> <form-response> ;
 
 : validate-param ( id component -- )
     [ [ params get at ] [ validate ] bi* ]
@@ -46,3 +60,22 @@ M: form init V{ } clone >>components ;
 
 : validate-form ( form -- )
     (validate-form) [ validation-failed ] when ;
+
+: render-form ( value form template -- )
+    [
+        [ from-tuple ]
+        [ set-components ]
+        [ call-template ]
+        tri*
+    ] with-scope ;
+
+M: form component-string drop ;
+
+M: form render-summary*
+    dup summary-template>> render-form ;
+
+M: form render-view*
+    dup view-template>> render-form ;
+
+M: form render-edit*
+    nip dup edit-template>> render-form ;
index db03645a24f78b3fb0c7bb903c0f5cc120493b92..d3bd6c6bbe236f628657357ea7ed52da29f4f099 100755 (executable)
@@ -160,23 +160,30 @@ drop
 
 SYMBOL: development-mode
 
+: http-error. ( error -- )
+    "Internal server error" [
+        development-mode get [
+            [ print-error nl :c ] with-html-stream
+        ] [
+            500 "Internal server error"
+            trivial-response-body
+        ] if
+    ] simple-page ;
+
 : <500> ( error -- response )
     500 "Internal server error" <trivial-response>
-    swap '[
-        , "Internal server error" [
-            development-mode get [
-                [ print-error nl :c ] with-html-stream
-            ] [
-                500 "Internal server error"
-                trivial-response-body
-            ] if
-        ] simple-page
-    ] >>body ;
+    swap '[ , http-error. ] >>body ;
 
 : do-response ( response -- )
     dup write-response
     request get method>> "HEAD" =
-    [ drop ] [ write-response-body ] if ;
+    [ drop ] [
+        '[
+            , write-response-body
+        ] [
+            http-error.
+        ] recover
+    ] if ;
 
 LOG: httpd-hit NOTICE
 
diff --git a/extra/http/server/templating/chloe/chloe-tests.factor b/extra/http/server/templating/chloe/chloe-tests.factor
new file mode 100644 (file)
index 0000000..f517af4
--- /dev/null
@@ -0,0 +1,97 @@
+USING: http.server.templating http.server.templating.chloe
+http.server.components http.server.boilerplate tools.test
+io.streams.string kernel sequences ascii boxes namespaces xml
+splitting ;
+IN: http.server.templating.chloe.tests
+
+[ "foo" ]
+[ "<a href=\"foo\">blah</a>" string>xml "href" required-attr ]
+unit-test
+
+[ "<a name=\"foo\">blah</a>" string>xml "href" required-attr ]
+[ "href attribute is required" = ]
+must-fail-with
+
+[ f ] [ f parse-query-attr ] unit-test
+
+[ f ] [ "" parse-query-attr ] unit-test
+
+[ H{ { "a" "b" } } ] [
+    blank-values
+    "b" "a" set-value
+    "a" parse-query-attr
+] unit-test
+
+[ H{ { "a" "b" } { "c" "d" } } ] [
+    blank-values
+    "b" "a" set-value
+    "d" "c" set-value
+    "a,c" parse-query-attr
+] unit-test
+
+: run-template
+    with-string-writer [ "\r\n\t" member? not ] subset
+    "?>" split1 nip ; inline
+
+: test-template ( name -- template )
+    "resource:extra/http/server/templating/chloe/test/"
+    swap
+    ".xml" 3append <chloe> ;
+
+[ "Hello world" ] [
+    [
+        "test1" test-template call-template
+    ] run-template
+] unit-test
+
+[ "Blah blah" "Hello world" ] [
+    [
+        <box> title set
+        [
+            "test2" test-template call-template
+        ] run-template
+        title get box>
+    ] with-scope
+] unit-test
+
+[ "<html><head><title>Hello world</title></head><body>Blah blah</body></html>" ] [
+    [
+        [
+            "test2" test-template call-template
+        ] "test3" test-template with-boilerplate
+    ] run-template
+] unit-test
+
+: test4-aux? t ;
+
+[ "True" ] [
+    [
+        "test4" test-template call-template
+    ] run-template
+] unit-test
+
+: test5-aux? f ;
+
+[ "" ] [
+    [
+        "test5" test-template call-template
+    ] run-template
+] unit-test
+
+SYMBOL: test6-aux?
+
+[ "True" ] [
+    [
+        test6-aux? on
+        "test6" test-template call-template
+    ] run-template
+] unit-test
+
+SYMBOL: test7-aux?
+
+[ "" ] [
+    [
+        test7-aux? off
+        "test7" test-template call-template
+    ] run-template
+] unit-test
diff --git a/extra/http/server/templating/chloe/chloe.factor b/extra/http/server/templating/chloe/chloe.factor
new file mode 100644 (file)
index 0000000..685988d
--- /dev/null
@@ -0,0 +1,196 @@
+USING: accessors kernel sequences combinators kernel namespaces
+classes.tuple assocs splitting words arrays
+io io.files io.encodings.utf8 html.elements unicode.case
+tuple-syntax xml xml.data xml.writer xml.utilities
+http.server
+http.server.auth
+http.server.components
+http.server.sessions
+http.server.templating
+http.server.boilerplate ;
+IN: http.server.templating.chloe
+
+! Chloe is Ed's favorite web designer
+
+TUPLE: chloe path ;
+
+C: <chloe> chloe
+
+DEFER: process-template
+
+: chloe-ns TUPLE{ name url: "http://factorcode.org/chloe/1.0" } ;
+
+: chloe-tag? ( tag -- ? )
+    {
+        { [ dup tag? not ] [ f ] }
+        { [ dup chloe-ns names-match? not ] [ f ] }
+        [ t ]
+    } cond nip ;
+
+SYMBOL: tags
+
+: required-attr ( tag name -- value )
+    dup rot at*
+    [ nip ] [ drop " attribute is required" append throw ] if ;
+
+: optional-attr ( tag name -- value )
+    swap at ;
+
+: write-title-tag ( tag -- )
+    drop
+    "head" tags get member? "title" tags get member? not and
+    [ <title> write-title </title> ] [ write-title ] if ;
+
+: style-tag ( tag -- )
+    dup "include" optional-attr dup [
+        swap children>string empty? [
+            "style tag cannot have both an include attribute and a body" throw
+        ] unless
+        utf8 file-contents
+    ] [
+        drop children>string
+    ] if add-style ;
+
+: write-style-tag ( tag -- )
+    drop <style> write-style </style> ;
+
+: atom-tag ( tag -- )
+    [ "title" required-attr ]
+    [ "href" required-attr ]
+    bi set-atom-feed ;
+
+: write-atom-tag ( tag -- )
+    drop
+    "head" tags get member? [
+        write-atom-feed
+    ] [
+        atom-feed get value>> second write
+    ] if ;
+
+: component-attr ( tag -- name )
+    "component" required-attr ;
+
+: view-tag ( tag -- )
+    component-attr component render-view ;
+
+: edit-tag ( tag -- )
+    component-attr component render-edit ;
+
+: summary-tag ( tag -- )
+    component-attr component render-summary ;
+
+: parse-query-attr ( string -- assoc )
+    dup empty?
+    [ drop f ] [ "," split [ dup value ] H{ } map>assoc ] if ;
+
+: a-start-tag ( tag -- )
+    <a
+    dup "value" optional-attr [ value f ] [
+        [ "href" required-attr ]
+        [ "query" optional-attr parse-query-attr ]
+        bi
+    ] ?if link>string =href
+    a> ;
+
+: process-tag-children ( tag -- )
+    [ process-template ] each ;
+
+: a-tag ( tag -- )
+    [ a-start-tag ]
+    [ process-tag-children ]
+    [ drop </a> ]
+    tri ;
+
+: form-start-tag ( tag -- )
+    <form
+    "POST" =method
+    tag-attrs print-attrs
+    form>
+    hidden-form-field ;
+
+: form-tag ( tag -- )
+    [ form-start-tag ]
+    [ process-tag-children ]
+    [ drop </form> ]
+    tri ;
+
+: attr>word ( value -- word/f )
+    dup ":" split1 swap lookup
+    [ ] [ "No such word: " swap append throw ] ?if ;
+
+: attr>var ( value -- word/f )
+    attr>word dup symbol? [
+        "Must be a symbol: " swap append throw
+    ] unless ;
+
+: if-satisfied? ( tag -- ? )
+    {
+        [ "code" optional-attr [ attr>word execute ] [ t ] if* ]
+        [  "var" optional-attr [ attr>var      get ] [ t ] if* ]
+        [ "svar" optional-attr [ attr>var     sget ] [ t ] if* ]
+        [ "uvar" optional-attr [ attr>var     uget ] [ t ] if* ]
+    } cleave 4array [ ] all? ;
+
+: if-tag ( tag -- )
+    dup if-satisfied? [ process-tag-children ] [ drop ] if ;
+
+: error-tag ( tag -- )
+    children>string render-error ;
+
+: process-chloe-tag ( tag -- )
+    dup name-tag {
+        { "chloe" [ [ process-template ] each ] }
+        { "title" [ children>string set-title ] }
+        { "write-title" [ write-title-tag ] }
+        { "style" [ style-tag ] }
+        { "write-style" [ write-style-tag ] }
+        { "atom" [ atom-tag ] }
+        { "write-atom" [ write-atom-tag ] }
+        { "view" [ view-tag ] }
+        { "edit" [ edit-tag ] }
+        { "summary" [ summary-tag ] }
+        { "a" [ a-tag ] }
+        { "form" [ form-tag ] }
+        { "error" [ error-tag ] }
+        { "if" [ if-tag ] }
+        { "comment" [ drop ] }
+        { "call-next-template" [ drop call-next-template ] }
+        [ "Unknown chloe tag: " swap append throw ]
+    } case ;
+
+: process-tag ( tag -- )
+    {
+        [ name-tag >lower tags get push ]
+        [ write-start-tag ]
+        [ process-tag-children ]
+        [ write-end-tag ]
+        [ drop tags get pop* ]
+    } cleave ;
+
+: process-template ( xml -- )
+    {
+        { [ dup [ chloe-tag? ] is? ] [ process-chloe-tag ] }
+        { [ dup [ tag? ] is? ] [ process-tag ] }
+        { [ t ] [ write-item ] }
+    } cond ;
+
+: process-chloe ( xml -- )
+    [
+        V{ } clone tags set
+
+        nested-template? get [
+            process-template
+        ] [
+            {
+                [ xml-prolog write-prolog ]
+                [ xml-before write-chunk  ]
+                [ process-template        ]
+                [ xml-after write-chunk   ]
+            } cleave
+        ] if
+    ] with-scope ;
+
+M: chloe call-template*
+    path>> utf8 <file-reader> read-xml process-chloe ;
+
+INSTANCE: chloe template
diff --git a/extra/http/server/templating/chloe/test/test1.xml b/extra/http/server/templating/chloe/test/test1.xml
new file mode 100644 (file)
index 0000000..daccd57
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+       Hello world
+</t:chloe>
diff --git a/extra/http/server/templating/chloe/test/test2.xml b/extra/http/server/templating/chloe/test/test2.xml
new file mode 100644 (file)
index 0000000..05b9dde
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+       <t:title>Hello world</t:title>
+       Blah blah
+</t:chloe>
diff --git a/extra/http/server/templating/chloe/test/test3-aux.xml b/extra/http/server/templating/chloe/test/test3-aux.xml
new file mode 100644 (file)
index 0000000..99f61af
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+       <t:title>Hello world</t:title>
+</t:chloe>
diff --git a/extra/http/server/templating/chloe/test/test3.xml b/extra/http/server/templating/chloe/test/test3.xml
new file mode 100644 (file)
index 0000000..845dd35
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+       <html>
+               <head>
+                       <t:write-title />
+               </head>
+               <body>
+                       <t:call-next-template />
+               </body>
+       </html>
+</t:chloe>
diff --git a/extra/http/server/templating/chloe/test/test4.xml b/extra/http/server/templating/chloe/test/test4.xml
new file mode 100644 (file)
index 0000000..0381bcc
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <t:if code="http.server.templating.chloe.tests:test4-aux?">
+               True
+       </t:if>
+
+</t:chloe>
diff --git a/extra/http/server/templating/chloe/test/test5.xml b/extra/http/server/templating/chloe/test/test5.xml
new file mode 100644 (file)
index 0000000..d74a5e5
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <t:if code="http.server.templating.chloe.tests:test5-aux?">
+               True
+       </t:if>
+
+</t:chloe>
diff --git a/extra/http/server/templating/chloe/test/test6.xml b/extra/http/server/templating/chloe/test/test6.xml
new file mode 100644 (file)
index 0000000..5b6a71c
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <t:if var="http.server.templating.chloe.tests:test6-aux?">
+               True
+       </t:if>
+
+</t:chloe>
diff --git a/extra/http/server/templating/chloe/test/test7.xml b/extra/http/server/templating/chloe/test/test7.xml
new file mode 100644 (file)
index 0000000..4381b5c
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <t:if var="http.server.templating.chloe.tests:test7-aux?">
+               True
+       </t:if>
+
+</t:chloe>
index 9d8a6f4617e6c57a4edd5dcc1a21f8f75b19eb01..42bec435700cdfe28e7e33cd498deb9d456a898f 100755 (executable)
@@ -1,13 +1,13 @@
 USING: io io.files io.streams.string io.encodings.utf8
-http.server.templating.fhtml kernel tools.test sequences
-parser ;
+http.server.templating http.server.templating.fhtml kernel
+tools.test sequences parser ;
 IN: http.server.templating.fhtml.tests
 
 : test-template ( path -- ? )
     "resource:extra/http/server/templating/fhtml/test/"
     prepend
     [
-        ".fhtml" append [ run-template ] with-string-writer
+        ".fhtml" append <fhtml> [ call-template ] with-string-writer
     ] keep
     ".html" append utf8 file-contents = ;
 
index 4a3bf38e23e4d5b7fdcefbd923b287fd51bbbcc3..2cc053a0cabf76a121eb1d95f140da0bfe29caf7 100755 (executable)
@@ -1,12 +1,12 @@
 ! Copyright (C) 2005 Alex Chapman
 ! Copyright (C) 2006, 2008 Slava Pestov
 ! See http://factorcode.org/license.txt for BSD license.
-USING: continuations sequences kernel parser namespaces io
-io.files io.streams.string html html.elements source-files
-debugger combinators math quotations generic strings splitting
-accessors http.server.static http.server assocs
-io.encodings.utf8 fry accessors ;
-
+USING: continuations sequences kernel namespaces debugger
+combinators math quotations generic strings splitting
+accessors assocs fry
+parser io io.files io.streams.string io.encodings.utf8 source-files
+html html.elements
+http.server.static http.server http.server.templating ;
 IN: http.server.templating.fhtml
 
 : templating-vocab ( -- vocab-name ) "http.server.templating.fhtml" ;
@@ -72,9 +72,13 @@ DEFER: <% delimiter
 : html-error. ( error -- )
     <pre> error. </pre> ;
 
-: run-template ( filename -- )
+TUPLE: fhtml path ;
+
+C: <fhtml> fhtml
+
+M: fhtml call-template* ( filename -- )
     '[
-        , [
+        , path>> [
             "quiet" on
             parser-notes off
             templating-vocab use+
@@ -85,16 +89,10 @@ DEFER: <% delimiter
         ] with-file-vocabs
     ] assert-depth ;
 
-: template-convert ( infile outfile -- )
-    utf8 [ run-template ] with-file-writer ;
-
-! responder integration
-: serve-template ( name -- response )
-    "text/html" <content>
-    swap '[ , run-template ] >>body ;
-
 ! file responder integration
 : enable-fhtml ( responder -- responder )
-    [ serve-template ]
+    [ <fhtml> serve-template ]
     "application/x-factor-server-page"
     pick special>> set-at ;
+
+INSTANCE: fhtml template
diff --git a/extra/http/server/templating/templating.factor b/extra/http/server/templating/templating.factor
new file mode 100644 (file)
index 0000000..610ec78
--- /dev/null
@@ -0,0 +1,28 @@
+USING: accessors kernel fry io io.encodings.utf8 io.files
+http http.server debugger prettyprint continuations ;
+IN: http.server.templating
+
+MIXIN: template
+
+GENERIC: call-template* ( template -- )
+
+ERROR: template-error template error ;
+
+M: template-error error.
+    "Error while processing template " write
+    [ template>> pprint ":" print nl ]
+    [ error>> error. ]
+    bi ;
+
+: call-template ( template -- )
+    [ call-template* ] [ template-error ] recover ;
+
+M: template write-response-body* call-template ;
+
+: template-convert ( template output -- )
+    utf8 [ call-template ] with-file-writer ;
+
+! responder integration
+: serve-template ( template -- response )
+    "text/html" <content>
+    swap '[ , call-template ] >>body ;
index 82827ac450f74b97c774bfde6d68ca1988227acc..5e845705ab1bcb12a06fa854123c4c0919966c6d 100755 (executable)
@@ -21,3 +21,9 @@ accessors ;
 
 [ "slava@factorcodeorg" v-email ]
 [ "invalid e-mail" = ] must-fail-with
+
+[ "http://www.factorcode.org" ]
+[ "http://www.factorcode.org" v-url ] unit-test
+
+[ "http:/www.factorcode.org" v-url ]
+[ "invalid URL" = ] must-fail-with
index 5be064c5ce716fbc1b82ce4d3c4c308b40aa581b..7415787c7992352a2b92022c467a337b3f96c211 100755 (executable)
@@ -11,8 +11,7 @@ TUPLE: validation-error value reason ;
 C: <validation-error> validation-error
 
 : with-validator ( value quot -- result )
-    [ validation-failed? on <validation-error> ] recover ;
-    inline
+    [ validation-failed? on <validation-error> ] recover ; inline
 
 : v-default ( str def -- str )
     over empty? spin ? ;
@@ -20,6 +19,9 @@ C: <validation-error> validation-error
 : v-required ( str -- str )
     dup empty? [ "required" throw ] when ;
 
+: v-optional ( str quot -- str )
+    over empty? [ 2drop f ] [ call ] if ; inline
+
 : v-min-length ( str n -- str )
     over length over < [
         [ "must be at least " % # " characters" % ] "" make
@@ -63,7 +65,12 @@ C: <validation-error> validation-error
 : v-email ( str -- str )
     #! From http://www.regular-expressions.info/email.html
     "e-mail"
-    R/ [A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}/i
+    R' [A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}'i
+    v-regexp ;
+
+: v-url ( str -- str )
+    "URL"
+    R' (ftp|http|https)://(\w+:?\w*@)?(\S+)(:[0-9]+)?(/|/([\w#!:.?+=&%@!\-/]))?'
     v-regexp ;
 
 : v-captcha ( str -- str )
diff --git a/extra/io/encodings/utf16/.utf16.factor.swo b/extra/io/encodings/utf16/.utf16.factor.swo
deleted file mode 100644 (file)
index 01be8fd..0000000
Binary files a/extra/io/encodings/utf16/.utf16.factor.swo and /dev/null differ
diff --git a/extra/io/encodings/utf16/authors.txt b/extra/io/encodings/utf16/authors.txt
deleted file mode 100644 (file)
index f990dd0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Daniel Ehrenberg
diff --git a/extra/io/encodings/utf16/summary.txt b/extra/io/encodings/utf16/summary.txt
deleted file mode 100644 (file)
index b249067..0000000
+++ /dev/null
@@ -1 +0,0 @@
-UTF16 encoding/decoding
diff --git a/extra/io/encodings/utf16/tags.txt b/extra/io/encodings/utf16/tags.txt
deleted file mode 100644 (file)
index 8e27be7..0000000
+++ /dev/null
@@ -1 +0,0 @@
-text
diff --git a/extra/io/encodings/utf16/utf16-docs.factor b/extra/io/encodings/utf16/utf16-docs.factor
deleted file mode 100644 (file)
index 1666219..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-USING: help.markup help.syntax io.encodings strings ;
-IN: io.encodings.utf16
-
-ARTICLE: "io.encodings.utf16" "UTF-16"
-"The UTF-16 encoding is a variable-width encoding. Unicode code points are encoded as 2 or 4 byte sequences. There are three encoding descriptor classes for working with UTF-16, depending on endianness or the presence of a BOM:"
-{ $subsection utf16 }
-{ $subsection utf16le }
-{ $subsection utf16be }
-{ $subsection utf16n } ;
-
-ABOUT: "io.encodings.utf16"
-
-HELP: utf16le
-{ $class-description "The encoding descriptor for UTF-16LE, that is, UTF-16 in little endian, without a byte order mark. Streams can be made which read or write wth this encoding." }
-{ $see-also "encodings-introduction" } ;
-
-HELP: utf16be
-{ $class-description "The encoding descriptor for UTF-16BE, that is, UTF-16 in big endian, without a byte order mark. Streams can be made which read or write wth this encoding." }
-{ $see-also "encodings-introduction" } ;
-
-HELP: utf16
-{ $class-description "The encoding descriptor for UTF-16, that is, UTF-16 with a byte order mark. This is the most useful for general input and output in UTF-16. Streams can be made which read or write wth this encoding." }
-{ $see-also "encodings-introduction" } ;
-
-HELP: utf16n
-{ $class-description "The encoding descriptor for UTF-16 without a byte order mark in native endian order. This is useful mostly for FFI calls which take input of strings of the type wchar_t*" }
-{ $see-also "encodings-introduction" } ;
-
-{ utf16 utf16le utf16be utf16n } related-words
diff --git a/extra/io/encodings/utf16/utf16-tests.factor b/extra/io/encodings/utf16/utf16-tests.factor
deleted file mode 100755 (executable)
index 6985983..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-USING: kernel tools.test io.encodings.utf16 arrays sbufs
-io.streams.byte-array sequences io.encodings io unicode
-io.encodings.string alien.c-types accessors classes ;
-IN: io.encodings.utf16.tests
-
-[ { CHAR: x } ] [ { 0 CHAR: x } utf16be decode >array ] unit-test
-[ { HEX: 1D11E } ] [ { HEX: D8 HEX: 34 HEX: DD HEX: 1E } utf16be decode >array ] unit-test
-[ { CHAR: replacement-character } ] [ { BIN: 11011111 CHAR: q } utf16be decode >array ] unit-test
-[ { CHAR: replacement-character } ] [ { BIN: 11011011 CHAR: x BIN: 11011011 CHAR: x } utf16be decode >array ] unit-test
-
-[ { 0 120 216 52 221 30 } ] [ { CHAR: x HEX: 1d11e } utf16be encode >array ] unit-test
-
-[ { CHAR: x } ] [ { CHAR: x 0 } utf16le decode >array ] unit-test
-[ { 119070 } ] [ { HEX: 34 HEX: D8 HEX: 1E HEX: DD } utf16le decode >array ] unit-test
-[ { CHAR: replacement-character } ] [ { 0 BIN: 11011111 } utf16le decode >array ] unit-test
-[ { CHAR: replacement-character } ] [ { 0 BIN: 11011011 0 0 } utf16le decode >array ] unit-test
-[ { 119070 } ] [ { HEX: 34 HEX: D8 HEX: 1E HEX: DD } utf16le decode >array ] unit-test
-
-[ { 120 0 52 216 30 221 } ] [ { CHAR: x HEX: 1d11e } utf16le encode >array ] unit-test
-
-[ { CHAR: x } ] [ { HEX: ff HEX: fe CHAR: x 0 } utf16 decode >array ] unit-test
-[ { CHAR: x } ] [ { HEX: fe HEX: ff 0 CHAR: x } utf16 decode >array ] unit-test
-
-[ { HEX: ff HEX: fe 120 0 52 216 30 221 } ] [ { CHAR: x HEX: 1d11e } utf16 encode >array ] unit-test
-
-: correct-endian
-    code>> class little-endian? [ utf16le = ] [ utf16be = ] if ;
-
-[ t ] [ B{ } utf16n <byte-reader> correct-endian ] unit-test
-[ t ] [ utf16n <byte-writer> correct-endian ] unit-test
diff --git a/extra/io/encodings/utf16/utf16.factor b/extra/io/encodings/utf16/utf16.factor
deleted file mode 100755 (executable)
index fbc296e..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-! Copyright (C) 2006, 2008 Daniel Ehrenberg.
-! See http://factorcode.org/license.txt for BSD license.
-USING: math kernel sequences sbufs vectors namespaces io.binary
-io.encodings combinators splitting io byte-arrays inspector
-alien.c-types ;
-IN: io.encodings.utf16
-
-TUPLE: utf16be ;
-
-TUPLE: utf16le ;
-
-TUPLE: utf16 ;
-
-TUPLE: utf16n ;
-
-<PRIVATE
-
-! UTF-16BE decoding
-
-: append-nums ( byte ch -- ch )
-    over [ 8 shift bitor ] [ 2drop replacement-char ] if ;
-
-: double-be ( stream byte -- stream char )
-    over stream-read1 swap append-nums ;
-
-: quad-be ( stream byte -- stream char )
-    double-be over stream-read1 [
-        dup -2 shift BIN: 110111 number= [
-            >r 2 shift r> BIN: 11 bitand bitor
-            over stream-read1 swap append-nums HEX: 10000 +
-        ] [ 2drop dup stream-read1 drop replacement-char ] if
-    ] when* ;
-
-: ignore ( stream -- stream char )
-    dup stream-read1 drop replacement-char ;
-
-: begin-utf16be ( stream byte -- stream char )
-    dup -3 shift BIN: 11011 number= [
-        dup BIN: 00000100 bitand zero?
-        [ BIN: 11 bitand quad-be ]
-        [ drop ignore ] if
-    ] [ double-be ] if ;
-    
-M: utf16be decode-char
-    drop dup stream-read1 dup [ begin-utf16be ] when nip ;
-
-! UTF-16LE decoding
-
-: quad-le ( stream ch -- stream char )
-    over stream-read1 swap 10 shift bitor
-    over stream-read1 dup -2 shift BIN: 110111 = [
-        BIN: 11 bitand append-nums HEX: 10000 +
-    ] [ 2drop replacement-char ] if ;
-
-: double-le ( stream byte1 byte2 -- stream char )
-    dup -3 shift BIN: 11011 = [
-        dup BIN: 100 bitand 0 number=
-        [ BIN: 11 bitand 8 shift bitor quad-le ]
-        [ 2drop replacement-char ] if
-    ] [ append-nums ] if ;
-
-: begin-utf16le ( stream byte -- stream char )
-    over stream-read1 [ double-le ] [ drop replacement-char ] if* ;
-
-M: utf16le decode-char
-    drop dup stream-read1 dup [ begin-utf16le ] when nip ;
-
-! UTF-16LE/BE encoding
-
-: encode-first ( char -- byte1 byte2 )
-    -10 shift
-    dup -8 shift BIN: 11011000 bitor
-    swap HEX: FF bitand ;
-
-: encode-second ( char -- byte3 byte4 )
-    BIN: 1111111111 bitand
-    dup -8 shift BIN: 11011100 bitor
-    swap BIN: 11111111 bitand ;
-
-: stream-write2 ( stream char1 char2 -- )
-    rot [ stream-write1 ] curry bi@ ;
-
-: char>utf16be ( stream char -- )
-    dup HEX: FFFF > [
-        HEX: 10000 -
-        2dup encode-first stream-write2
-        encode-second stream-write2
-    ] [ h>b/b swap stream-write2 ] if ;
-
-M: utf16be encode-char ( char stream encoding -- )
-    drop swap char>utf16be ;
-
-: char>utf16le ( char stream -- )
-    dup HEX: FFFF > [
-        HEX: 10000 -
-        2dup encode-first swap stream-write2
-        encode-second swap stream-write2
-    ] [ h>b/b stream-write2 ] if ; 
-
-M: utf16le encode-char ( char stream encoding -- )
-    drop swap char>utf16le ;
-
-! UTF-16
-
-: bom-le B{ HEX: ff HEX: fe } ; inline
-
-: bom-be B{ HEX: fe HEX: ff } ; inline
-
-: start-utf16le? ( seq1 -- seq2 ? ) bom-le ?head ;
-
-: start-utf16be? ( seq1 -- seq2 ? ) bom-be ?head ;
-
-TUPLE: missing-bom ;
-M: missing-bom summary drop "The BOM for a UTF-16 stream was missing" ;
-
-: bom>le/be ( bom -- le/be )
-    dup bom-le sequence= [ drop utf16le ] [
-        bom-be sequence= [ utf16be ] [ missing-bom ] if
-    ] if ;
-
-M: utf16 <decoder> ( stream utf16 -- decoder )
-    drop 2 over stream-read bom>le/be <decoder> ;
-
-M: utf16 <encoder> ( stream utf16 -- encoder )
-    drop bom-le over stream-write utf16le <encoder> ;
-
-! Native-order UTF-16
-
-: native-utf16 ( -- descriptor )
-    little-endian? utf16le utf16be ? ;
-
-M: utf16n <decoder> drop native-utf16 <decoder> ;
-
-M: utf16n <encoder> drop native-utf16 <encoder> ;
-
-PRIVATE>
index 4446b82f208f2ffd91ebc0dacc7287b9234c71b2..dadb627fc073fcf2ce826438b61c858d7b3bf553 100755 (executable)
@@ -113,6 +113,8 @@ HELP: try-process
 { $values { "desc" "a launch descriptor" } }
 { $description "Launches a process and waits for it to complete. If it exits with a non-zero status code, throws a " { $link process-failed } " error." } ;
 
+{ run-process try-process run-detached } related-words
+
 HELP: kill-process
 { $values { "process" process } }
 { $description "Kills a running process. Does nothing if the process has already exited." } ;
@@ -171,6 +173,7 @@ ARTICLE: "io.launcher.launch" "Launching processes"
 "Launching processes:"
 { $subsection run-process }
 { $subsection try-process }
+{ $subsection run-detached }
 "Redirecting standard input and output to a pipe:"
 { $subsection <process-stream> }
 { $subsection with-process-stream } ;
index 9b480d0cc2974e1d4bc9987de6051c752d71ef7e..6ee866052866b8ef007215c15505806ca1b42471 100755 (executable)
@@ -127,10 +127,7 @@ HOOK: run-process* io-backend ( process -- handle )
     run-detached
     dup detached>> [ dup wait-for-process drop ] unless ;
 
-TUPLE: process-failed code ;
-
-: process-failed ( code -- * )
-    \ process-failed boa throw ;
+ERROR: process-failed code ;
 
 : try-process ( desc -- )
     run-process wait-for-process dup zero?
index 6407108a615bee903ebd960f3facda075b0c2fbd..77d539259e7755e8de40f854dde9b3ce689179b0 100644 (file)
@@ -33,7 +33,6 @@ os { winnt linux macosx } member? [
         [ ] [ "m" get dispose ] unit-test
     ] with-monitors
 
-    
     [
         [ "monitor-test" temp-file delete-tree ] ignore-errors
         
@@ -88,4 +87,7 @@ os { winnt linux macosx } member? [
 
         [ ] [ "m" get dispose ] unit-test
     ] with-monitors
+
+    ! Out-of-scope disposal should not fail
+    [ "" resource-path t <monitor> ] with-monitors dispose
 ] when
index 1b18015513f2c1e5a31e9d034131f9ffb3015b47..04d491edbe076c9da541f374ae7bb76a3d86ec37 100644 (file)
@@ -1,15 +1,16 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors sequences assocs arrays continuations combinators kernel
-threads concurrency.messaging concurrency.mailboxes
-concurrency.promises
-io.files io.monitors ;
+threads concurrency.messaging concurrency.mailboxes concurrency.promises
+io.files io.monitors debugger ;
 IN: io.monitors.recursive
 
 ! Simulate recursive monitors on platforms that don't have them
 
 TUPLE: recursive-monitor < monitor children thread ready ;
 
+: notify? ( -- ? ) monitor tget ready>> promise-fulfilled? ;
+
 DEFER: add-child-monitor
 
 : qualify-path ( path -- path' )
@@ -17,25 +18,22 @@ DEFER: add-child-monitor
 
 : add-child-monitors ( path -- )
     #! We yield since this directory scan might take a while.
-    [
-        directory* [ first add-child-monitor yield ] each
-    ] curry ignore-errors ;
+    directory* [ first add-child-monitor ] each yield ;
 
 : add-child-monitor ( path -- )
+    notify? [ dup { +add-file+ } monitor tget queue-change ] when
     qualify-path dup link-info type>> +directory+ eq? [
         [ add-child-monitors ]
         [
-            [ f my-mailbox (monitor) ] keep
-            monitor tget children>> set-at
+            [
+                [ f my-mailbox (monitor) ] keep
+                monitor tget children>> set-at
+            ] curry ignore-errors
         ] bi
     ] [ drop ] if ;
 
-USE: io
-USE: prettyprint
-
 : remove-child-monitor ( monitor -- )
-    monitor tget children>> delete-at*
-    [ dispose ] [ drop ] if ;
+    monitor tget children>> delete-at* [ dispose ] [ drop ] if ;
 
 M: recursive-monitor dispose
     dup queue>> closed>> [
index 498430fdbc84108db12459fed0c91b9be0182f17..2a376e18c2cc7cb25525d1984df53390dd6966c2 100755 (executable)
@@ -1,8 +1,9 @@
-! Copyright (C) 2007 Doug Coleman, Slava Pestov
+! Copyright (C) 2007, 2008 Doug Coleman, Slava Pestov
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays byte-arrays io.backend io.binary io.sockets
-kernel math math.parser sequences splitting system
-alien.c-types combinators namespaces alien parser ;
+io.encodings.ascii kernel math math.parser sequences splitting
+system alien.c-types alien.strings alien combinators namespaces
+parser ;
 IN: io.sockets.impl
 
 << {
@@ -130,4 +131,4 @@ M: object resolve-host ( host serv passive? -- seq )
 M: object host-name ( -- name )
     256 <byte-array> dup dup length gethostname
     zero? [ "gethostname failed" throw ] unless
-    alien>char-string ;
+    ascii alien>string ;
index 58c1f0110cd00d1ed57c67bf9438bee6871d2e64..cd17dfbbce76648b676956e86c25531f57e02049 100644 (file)
@@ -2,21 +2,24 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel io.backend io.monitors io.monitors.recursive
 io.files io.buffers io.monitors io.nonblocking io.timeouts
-io.unix.backend io.unix.select unix.linux.inotify assocs
-namespaces threads continuations init math math.bitfields sets
-alien.c-types alien vocabs.loader accessors system hashtables ;
+io.unix.backend io.unix.select io.encodings.utf8
+unix.linux.inotify assocs namespaces threads continuations init
+math math.bitfields sets alien alien.strings alien.c-types
+vocabs.loader accessors system hashtables ;
 IN: io.unix.linux.monitors
 
-TUPLE: linux-monitor < monitor wd ;
+SYMBOL: watches
+
+SYMBOL: inotify
+
+TUPLE: linux-monitor < monitor wd inotify watches ;
 
 : <linux-monitor> ( wd path mailbox -- monitor )
     linux-monitor new-monitor
+        inotify get >>inotify
+        watches get >>watches
         swap >>wd ;
 
-SYMBOL: watches
-
-SYMBOL: inotify
-
 : wd>monitor ( wd -- monitor ) watches get at ;
 
 : <inotify> ( -- port/f )
@@ -52,8 +55,13 @@ M: linux (monitor) ( path recursive? mailbox -- monitor )
     ] if ;
 
 M: linux-monitor dispose ( monitor -- )
-    [ wd>> watches get delete-at ]
-    [ wd>> inotify-fd swap inotify_rm_watch io-error ] bi ;
+    dup inotify>> closed>> [ drop ] [
+        [ [ wd>> ] [ watches>> ] bi delete-at ]
+        [
+            [ inotify>> handle>> ] [ wd>> ] bi
+            inotify_rm_watch io-error
+        ] bi
+    ] if ;
 
 : ignore-flags? ( mask -- ? )
     {
@@ -79,7 +87,7 @@ M: linux-monitor dispose ( monitor -- )
     dup inotify-event-mask ignore-flags? [
         drop f f
     ] [
-        [ inotify-event-name alien>char-string ]
+        [ inotify-event-name utf8 alien>string ]
         [ inotify-event-mask parse-action ] bi
     ] if ;
 
index cecc70fb0825a7d65b90f6214febcfff6958d609..b60cb5760e42a506c23c1be45b500d2cd959c36c 100755 (executable)
@@ -1,13 +1,15 @@
 ! Copyright (C) 2004, 2008 Slava Pestov, Ivan Tikhonov. 
 ! See http://factorcode.org/license.txt for BSD license.
+USING: alien alien.c-types alien.strings generic kernel math
+namespaces threads sequences byte-arrays io.nonblocking
+io.binary io.unix.backend io.streams.duplex io.sockets.impl
+io.backend io.files io.files.private io.encodings.utf8
+math.parser continuations libc combinators system accessors
+qualified unix ;
+
+EXCLUDE: io => read write close ;
+EXCLUDE: io.sockets => accept ;
 
-! We need to fiddle with the exact search order here, since
-! unix::accept shadows streams::accept.
-USING: alien alien.c-types generic io kernel math namespaces
-io.nonblocking parser threads unix sequences
-byte-arrays io.sockets io.binary io.unix.backend
-io.streams.duplex io.sockets.impl math.parser continuations libc
-combinators io.backend io.files io.files.private system accessors ;
 IN: io.unix.sockets
 
 : pending-init-error ( port -- )
@@ -36,7 +38,7 @@ TUPLE: connect-task < output-task ;
     connect-task <io-task> ;
 
 M: connect-task do-io-task
-    io-task-port dup port-handle f 0 write
+    port>> dup handle>> f 0 write
     0 < [ defer-error ] [ drop t ] if ;
 
 : wait-to-connect ( port -- )
@@ -56,8 +58,6 @@ M: unix ((client)) ( addrspec -- client-in client-out )
     ] if ;
 
 ! Server sockets - TCP and Unix domain
-USE: unix
-
 : init-server-socket ( fd -- )
     SOL_SOCKET SO_REUSEADDR sockopt ;
 
@@ -83,8 +83,6 @@ M: accept-task do-io-task
 : wait-to-accept ( server -- )
     [ <accept-task> add-io-task ] with-port-continuation drop ;
 
-USE: io.sockets
-
 : server-fd ( addrspec type -- fd )
     >r dup protocol-family r>  socket-fd
     dup init-server-socket
@@ -187,12 +185,12 @@ M: local protocol-family drop PF_UNIX ;
 M: local sockaddr-type drop "sockaddr-un" c-type ;
 
 M: local make-sockaddr
-    local-path cwd prepend-path
+    path>> (normalize-path)
     dup length 1 + max-un-path > [ "Path too long" throw ] when
     "sockaddr-un" <c-object>
     AF_UNIX over set-sockaddr-un-family
-    dup sockaddr-un-path rot string>char-alien dup length memcpy ;
+    dup sockaddr-un-path rot utf8 string>alien dup length memcpy ;
 
 M: local parse-sockaddr
     drop
-    sockaddr-un-path alien>char-string <local> ;
+    sockaddr-un-path utf8 alien>string <local> ;
index eec473e8403f32c7618e7bc5106446feb6433037..c9f17147d34c633c6483a7f10d8004996b9fc74d 100755 (executable)
@@ -1,15 +1,15 @@
 USING: continuations destructors io.buffers io.files io.backend
 io.timeouts io.nonblocking io.windows io.windows.nt.backend
 kernel libc math threads windows windows.kernel32 system
-alien.c-types alien.arrays sequences combinators combinators.lib
-sequences.lib ascii splitting alien strings assocs namespaces
-io.files.private accessors ;
+alien.c-types alien.arrays alien.strings sequences combinators
+combinators.lib sequences.lib ascii splitting alien strings
+assocs namespaces io.files.private accessors ;
 IN: io.windows.nt.files
 
 M: winnt cwd
     MAX_UNICODE_PATH dup "ushort" <c-array>
     [ GetCurrentDirectory win32-error=0/f ] keep
-    alien>u16-string ;
+    utf16n alien>string ;
 
 M: winnt cd
     SetCurrentDirectory win32-error=0/f ;
diff --git a/extra/locals/backend/backend-tests.factor b/extra/locals/backend/backend-tests.factor
new file mode 100644 (file)
index 0000000..41caa87
--- /dev/null
@@ -0,0 +1,38 @@
+IN: locals.backend.tests
+USING: tools.test locals.backend kernel arrays ;
+
+[ 3 ] [ 3 >r 1 get-local r> drop ] unit-test
+
+[ 4 ] [ 3 4 >r >r 2 get-local 2 drop-locals ] unit-test
+
+: get-local-test-1 3 >r 1 get-local r> drop ;
+
+{ 0 1 } [ get-local-test-1 ] must-infer-as
+
+[ 3 ] [ get-local-test-1 ] unit-test
+
+: get-local-test-2 3 4 >r >r 2 get-local 2 drop-locals ;
+
+{ 0 1 } [ get-local-test-2 ] must-infer-as
+
+[ 4 ] [ get-local-test-2 ] unit-test
+
+: get-local-test-3 3 4 >r >r 2 get-local r> r> 2array ;
+
+{ 0 2 } [ get-local-test-3 ] must-infer-as
+
+[ 4 { 3 4 } ] [ get-local-test-3 ] unit-test
+
+: get-local-test-4 3 4 >r >r r> r> dup swap >r swap >r r> r> 2array ;
+
+{ 0 2 } [ get-local-test-4 ] must-infer-as
+
+[ 4 { 3 4 } ] [ get-local-test-4 ] unit-test
+
+[ 1 2 ] [ 1 2 2 load-locals r> r> ] unit-test
+
+: load-locals-test-1 1 2 2 load-locals r> r> ;
+
+{ 0 2 } [ load-locals-test-1 ] must-infer-as
+
+[ 1 2 ] [ load-locals-test-1 ] unit-test
diff --git a/extra/locals/backend/backend.factor b/extra/locals/backend/backend.factor
new file mode 100644 (file)
index 0000000..10bed8b
--- /dev/null
@@ -0,0 +1,42 @@
+USING: math kernel slots.private inference.known-words
+inference.backend sequences effects words ;
+IN: locals.backend
+
+: load-locals ( n -- )
+    dup zero? [ drop ] [ swap >r 1- load-locals ] if ;
+
+: get-local ( n -- value )
+    dup zero? [ drop dup ] [ r> swap 1- get-local swap >r ] if ;
+
+: local-value 2 slot ; inline
+
+: set-local-value 2 set-slot ; inline
+
+: drop-locals ( n -- )
+    dup zero? [ drop ] [ r> drop 1- drop-locals ] if ;
+
+\ load-locals [
+    pop-literal nip
+    [ dup reverse <effect> infer-shuffle ]
+    [ infer->r ]
+    bi
+] "infer" set-word-prop
+
+\ get-local [
+    pop-literal nip
+    [ infer-r> ]
+    [ dup 0 prefix <effect> infer-shuffle ]
+    [ infer->r ]
+    tri
+] "infer" set-word-prop
+
+\ drop-locals [
+    pop-literal nip
+    [ infer-r> ]
+    [ { } <effect> infer-shuffle ] bi
+] "infer" set-word-prop
+
+<<
+{ load-locals get-local drop-locals }
+[ t "no-compile" set-word-prop ] each
+>>
index 4ee9b48bb73d1343ccc19b6273eb9e249fef3945..c13be40c8f73e3996942b71a2e8f9a4f478f5c56 100755 (executable)
@@ -82,6 +82,8 @@ IN: locals.tests
 
 0 write-test-1 "q" set
 
+{ 1 1 } "q" get must-infer-as
+
 [ 1 ] [ 1 "q" get call ] unit-test
 
 [ 2 ] [ 1 "q" get call ] unit-test
index 2b0c61cc8951d17f828fdb8162cc910ffcd87b53..be73f1db889f2f304e9a29c6811e7d1d111121fd 100755 (executable)
@@ -4,7 +4,8 @@ USING: kernel namespaces sequences sequences.private assocs math
 inference.transforms parser words quotations debugger macros
 arrays macros splitting combinators prettyprint.backend
 definitions prettyprint hashtables prettyprint.sections sets
-sequences.private effects generic compiler.units accessors ;
+sequences.private effects generic compiler.units accessors
+locals.backend ;
 IN: locals
 
 ! Inspired by
@@ -56,95 +57,80 @@ TUPLE: quote local ;
 
 C: <quote> quote
 
-! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-! read-local
-! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
 : local-index ( obj args -- n )
     [ dup quote? [ quote-local ] when eq? ] with find drop ;
 
-: read-local ( obj args -- quot )
-    local-index 1+
-    dup [ r> ] <repetition> concat [ dup ] append
-    swap [ swap >r ] <repetition> concat append ;
-
-! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-! localize
-! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+: read-local-quot ( obj args -- quot )
+    local-index 1+ [ get-local ] curry ;
 
 : localize-writer ( obj args -- quot )
-  >r "local-reader" word-prop r> read-local [ 0 swap set-array-nth ] append ;
+  >r "local-reader" word-prop r>
+  read-local-quot [ set-local-value ] append ;
 
 : localize ( obj args -- quot )
     {
-        { [ over local? ]        [ read-local ] }
-        { [ over quote? ]        [ >r quote-local r> read-local ] }
-        { [ over local-word? ]   [ read-local [ call ] append ] }
-        { [ over local-reader? ] [ read-local [ 0 swap array-nth ] append ] }
+        { [ over local? ]        [ read-local-quot ] }
+        { [ over quote? ]        [ >r quote-local r> read-local-quot ] }
+        { [ over local-word? ]   [ read-local-quot [ call ] append ] }
+        { [ over local-reader? ] [ read-local-quot [ local-value ] append ] }
         { [ over local-writer? ] [ localize-writer ] }
         { [ over \ lambda eq? ]  [ 2drop [ ] ] }
         { [ t ]                  [ drop 1quotation ] }
     } cond ;
 
-! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-! point-free
-! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
 UNION: special local quote local-word local-reader local-writer ;
 
-: load-local ( arg -- quot ) 
-    local-reader? [ 1array >r ] [ >r ] ? ;
-
-: load-locals ( quot args -- quot )
-    nip <reversed> [ load-local ] map concat ;
+: load-locals-quot ( args -- quot )
+    dup [ local-reader? ] contains? [
+        <reversed> [
+            local-reader? [ 1array >r ] [ >r ] ?
+        ] map concat
+    ] [
+        length [ load-locals ] curry >quotation
+    ] if ;
 
-: drop-locals ( args -- args quot )
-    dup length [ r> drop ] <repetition> concat ;
+: drop-locals-quot ( args -- quot )
+    length [ drop-locals ] curry ;
 
 : point-free-body ( quot args -- newquot )
     >r 1 head-slice* r> [ localize ] curry map concat ;
 
 : point-free-end ( quot args -- newquot )
     over peek special?
-    [ drop-locals >r >r peek r> localize r> append ]
-    [ drop-locals nip swap peek suffix ]
+    [ dup drop-locals-quot >r >r peek r> localize r> append ]
+    [ dup drop-locals-quot nip swap peek suffix ]
     if ;
 
 : (point-free) ( quot args -- newquot )
-    [ load-locals ] [ point-free-body ] [ point-free-end ]
+    [ nip load-locals-quot ]
+    [ point-free-body ]
+    [ point-free-end ]
     2tri 3append >quotation ;
 
 : point-free ( quot args -- newquot )
     over empty? [ drop ] [ (point-free) ] if ;
 
-! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-! free-vars
-! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
 UNION: lexical local local-reader local-writer local-word ;
 
-GENERIC: free-vars ( form -- vars )
+GENERIC: free-vars* ( form -- )
+
+: free-vars ( form -- vars )
+    [ free-vars* ] { } make prune ;
 
-: add-if-free ( vars object -- vars )
+: add-if-free ( object -- )
   {
-      { [ dup local-writer? ] [ "local-reader" word-prop suffix ] }
-      { [ dup lexical? ]      [ suffix ] }
-      { [ dup quote? ]        [ quote-local suffix ] }
-      { [ t ]                 [ free-vars append ] }
+      { [ dup local-writer? ] [ "local-reader" word-prop , ] }
+      { [ dup lexical? ]      [ , ] }
+      { [ dup quote? ]        [ local>> , ] }
+      { [ t ]                 [ free-vars* ] }
   } cond ;
 
-M: object free-vars drop { } ;
+M: object free-vars* drop ;
 
-M: quotation free-vars { } [ add-if-free ] reduce ;
+M: quotation free-vars* [ add-if-free ] each ;
 
-M: lambda free-vars
-    dup vars>> swap body>> free-vars diff ;
-
-! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-! lambda-rewrite
-! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+M: lambda free-vars*
+    [ vars>> ] [ body>> ] bi free-vars diff % ;
 
 GENERIC: lambda-rewrite* ( obj -- )
 
@@ -172,8 +158,8 @@ M: lambda block-vars vars>> ;
 M: lambda block-body body>> ;
 
 M: lambda local-rewrite*
-    dup vars>> swap body>>
-    [ local-rewrite* \ call , ] [ ] make <lambda> , ;
+    [ vars>> ] [ body>> ] bi
+    [ [ local-rewrite* ] each ] [ ] make <lambda> , ;
 
 M: block lambda-rewrite*
     #! Turn free variables into bound variables, curry them
@@ -188,8 +174,6 @@ M: object lambda-rewrite* , ;
 
 M: object local-rewrite* , ;
 
-! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
 : make-local ( name -- word )
     "!" ?tail [
         <local-reader>
index 625be534ce026242eb422311f8d8adc02d4388ec..4d4068158e2f8354256aa594abc10ccf1a88a47c 100644 (file)
@@ -1,7 +1,7 @@
 ! Fast Fourier Transform, copyright (C) 2007 Hans Schmid
 ! http://dressguardmeister.blogspot.com/2007/01/fft.html
 USING: arrays sequences math math.vectors math.constants
-math.functions kernel splitting ;
+math.functions kernel splitting columns ;
 IN: math.fft
 
 : n^v ( n v -- w ) [ ^ ] with map ;
index f0819fb03ec3a5adc172cd69080dd3792ae4f223..35471653dc75a73c9d3710875faf31b283887324 100755 (executable)
@@ -7,6 +7,9 @@ ARTICLE: "integer-functions" "Integer functions"
 { $subsection gcd }
 { $subsection log2 }
 { $subsection next-power-of-2 }
+"Modular exponentiation:"
+{ $subsection ^mod }
+{ $subsection mod-inv }
 "Tests:"
 { $subsection power-of-2? }
 { $subsection even? }
@@ -33,7 +36,9 @@ ARTICLE: "arithmetic-functions" "Arithmetic functions"
 { $subsection ceiling }
 { $subsection floor }
 { $subsection truncate }
-{ $subsection round } ;
+{ $subsection round }
+"Inexact comparison:"
+{ $subsection ~ } ;
 
 ARTICLE: "power-functions" "Powers and logarithms"
 "Squares:"
@@ -107,10 +112,6 @@ HELP: >rect
 { $values { "z" number } { "x" real } { "y" real } }
 { $description "Extracts the real and imaginary components of a complex number." } ;
 
-HELP: power-of-2?
-{ $values { "n" integer } { "?" "a boolean" } }
-{ $description "Tests if " { $snippet "n" } " is a power of 2." } ;
-
 HELP: align
 { $values { "m" integer } { "w" "a power of 2" } { "n" "an integer multiple of " { $snippet "w" } } }
 { $description "Outputs the least multiple of " { $snippet "w" } " greater than " { $snippet "m" } "." }
index 6773678dab4b60696bb294153176b344c25415ca..8c71eb545b6b2e3886c1add0e51dab4f97ac3d25 100755 (executable)
@@ -81,9 +81,6 @@ IN: math.functions.tests
 [ 1/8 ] [ 2 -3 ^ ] unit-test
 [ t ] [ 1 100 shift 2 100 ^ = ] unit-test
 
-[ t ] [ 256 power-of-2? ] unit-test
-[ f ] [ 123 power-of-2? ] unit-test
-
 [ 1 ] [ 7/8 ceiling ] unit-test
 [ 2 ] [ 3/2 ceiling ] unit-test
 [ 0 ] [ -7/8 ceiling ] unit-test
index b3cfba8650ff810b6863fd803a120897fbf0cc3a..632939ff71fa023099a10f7fc41ae934f9924852 100755 (executable)
@@ -102,9 +102,6 @@ M: real absq sq ;
         [ ~abs ]
     } cond ;
 
-: power-of-2? ( n -- ? )
-    dup 0 < [ drop f ] [ dup 1- bitand zero? ] if ; foldable
-
 : >rect ( z -- x y ) dup real-part swap imaginary-part ; inline
 
 : conjugate ( z -- z* ) >rect neg rect> ; inline
index 91d9fd8ece8a922d1a6cc7902bfa2a747a0ff15b..9254fd0ce7d09106fd3f5202078bc56db9ac4bec 100644 (file)
@@ -1,5 +1,5 @@
 ! Haar wavelet transform -- http://dmr.ath.cx/gfx/haar/
-USING: sequences math kernel splitting ;
+USING: sequences math kernel splitting columns ;
 IN: math.haar
 
 : averages ( seq -- seq )
index 81b7f634276fbaf8b89448884dfea37dfa03a8c4..cc7d0758e57f24e4c49fed9445670f49533efa82 100755 (executable)
@@ -1,4 +1,5 @@
-USING: kernel layouts math namespaces sequences sequences.private ;
+USING: kernel layouts math namespaces sequences
+sequences.private accessors ;
 IN: math.ranges
 
 TUPLE: range from length step ;
@@ -9,10 +10,10 @@ TUPLE: range from length step ;
     range boa ;
 
 M: range length ( seq -- n )
-    range-length ;
+    length>> ;
 
 M: range nth-unsafe ( n range -- obj )
-    [ range-step * ] keep range-from + ;
+    [ step>> * ] keep from>> + ;
 
 INSTANCE: range immutable-sequence
 
@@ -37,10 +38,10 @@ INSTANCE: range immutable-sequence
 : [0,b) ( b -- range ) 0 swap [a,b) ;
 
 : range-increasing? ( range -- ? )
-    range-step 0 > ;
+    step>> 0 > ;
 
 : range-decreasing? ( range -- ? )
-    range-step 0 < ;
+    step>> 0 < ;
 
 : first-or-peek ( seq head? -- elt )
     [ first ] [ peek ] if ;
@@ -52,7 +53,7 @@ INSTANCE: range immutable-sequence
     dup range-decreasing? first-or-peek ;
 
 : clamp-to-range ( n range -- n )
-    tuck range-min max swap range-max min ;
+    [ range-min max ] [ range-max min ] bi ;
 
 : sequence-index-range  ( seq -- range )
     length [0,b) ;
index 6a191f0e07ab35132f252c5f5672efcc083e839a..3e5f66eb6fa3032998294e3a1ab5f4cb9a0b3faa 100644 (file)
@@ -155,6 +155,23 @@ METHOD: as-mutate { object object assoc }       set-at ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
+: prefix-on ( elt seq -- seq ) swap prefix ;
+: suffix-on ( elt seq -- seq ) swap suffix ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: 1st 0 at ;
+: 2nd 1 at ;
+: 3rd 2 at ;
+: 4th 3 at ;
+: 5th 4 at ;
+: 6th 5 at ;
+: 7th 6 at ;
+: 8th 7 at ;
+: 9th 8 at ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
 ! A note about the 'mutate' qualifier. Other words also technically mutate
 ! their primary object. However, the 'mutate' qualifier is supposed to
 ! indicate that this is the main objective of the word, as a side effect.
\ No newline at end of file
index 59f5095aad5fe1e13c3cdee328db5e6bc9904a44..0bcd639bc1b96e476fe5d106d2d80ccf0ae6b31a 100644 (file)
@@ -1,10 +1,11 @@
 ! Copyright (C) 2007 Chris Double.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel alien alien.syntax combinators alien.c-types
-       strings sequences namespaces words math threads ;
+USING: kernel alien alien.strings alien.syntax combinators
+alien.c-types strings sequences namespaces words math threads
+io.encodings.ascii ;
 IN: odbc
 
-"odbc" "odbc32.dll" "stdcall" add-library
+<< "odbc" "odbc32.dll" "stdcall" add-library >>
 
 LIBRARY: odbc
 
@@ -150,7 +151,7 @@ FUNCTION: SQLRETURN SQLGetData ( SQLHSTMT statementHandle, SQLUSMALLINT columnNu
   SQL-HANDLE-STMT swap alloc-handle ;
 
 : temp-string ( length -- byte-array length )
-  [ CHAR: \space  <string> string>char-alien ] keep ;
+  [ CHAR: \space  <string> ascii string>alien ] keep ;
 
 : odbc-init ( -- env )
   alloc-env-handle
@@ -192,7 +193,7 @@ C: <column> column
 
 : odbc-describe-column ( statement n -- column )
   dup >r
-  1024 CHAR: \space <string> string>char-alien dup >r
+  1024 CHAR: \space <string> ascii string>alien dup >r
   1024
   0 <short>
   0 <short> dup >r
@@ -204,7 +205,7 @@ C: <column> column
     r> *short
     r> *uint
     r> *short convert-sql-type
-    r> alien>char-string
+    r> ascii alien>string
     r> <column>
   ] [
     r> drop r> drop r> drop r> drop r> drop r> drop
@@ -213,12 +214,12 @@ C: <column> column
 
 : dereference-type-pointer ( byte-array column -- object )
   column-type {
-    { SQL-CHAR [ alien>char-string ] }
-    { SQL-VARCHAR [ alien>char-string ] }
-    { SQL-LONGVARCHAR [ alien>char-string ] }
-    { SQL-WCHAR [ alien>char-string ] }
-    { SQL-WCHARVAR [ alien>char-string ] }
-    { SQL-WLONGCHARVAR [ alien>char-string ] }
+    { SQL-CHAR [ ascii alien>string ] }
+    { SQL-VARCHAR [ ascii alien>string ] }
+    { SQL-LONGVARCHAR [ ascii alien>string ] }
+    { SQL-WCHAR [ ascii alien>string ] }
+    { SQL-WCHARVAR [ ascii alien>string ] }
+    { SQL-WLONGCHARVAR [ ascii alien>string ] }
     { SQL-SMALLINT [ *short ] }
     { SQL-INTEGER [ *long ] }
     { SQL-REAL [ *float ] }
@@ -236,7 +237,7 @@ C: <field> field
 : odbc-get-field ( statement column -- field )
   dup column? [ dupd odbc-describe-column ] unless dup >r column-number
   SQL-C-DEFAULT
-  8192 CHAR: \space <string> string>char-alien dup >r
+  8192 CHAR: \space <string> ascii string>alien dup >r
   8192
   f SQLGetData succeeded? [
     r> r> [ dereference-type-pointer ] keep <field>
index e352eabc10717bb5217b9d86dc7324b3b2c998a1..c05e180c115e889746aa1776a51fa4ccdd22fb17 100755 (executable)
@@ -1,14 +1,12 @@
 ! Copyright (C) 2008 Joe Groff.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel opengl.gl alien.c-types continuations namespaces
-assocs alien libc opengl math sequences combinators
-combinators.lib macros arrays ;
+assocs alien alien.strings libc opengl math sequences combinators
+combinators.lib macros arrays io.encodings.ascii ;
 IN: opengl.shaders
 
 : with-gl-shader-source-ptr ( string quot -- )
-    swap string>char-alien malloc-byte-array [
-        <void*> swap call
-    ] keep free ; inline
+    swap ascii malloc-string [ <void*> swap call ] keep free ; inline
 
 : <gl-shader> ( source kind -- shader )
     glCreateShader dup rot
@@ -47,7 +45,7 @@ IN: opengl.shaders
 : gl-shader-info-log ( shader -- log )
     dup gl-shader-info-log-length dup [
         [ 0 <int> swap glGetShaderInfoLog ] keep
-        alien>char-string
+        ascii alien>string
     ] with-malloc ;
 
 : check-gl-shader ( shader -- shader )
@@ -82,7 +80,7 @@ PREDICATE: fragment-shader < gl-shader (fragment-shader?) ;
 : gl-program-info-log ( program -- log )
     dup gl-program-info-log-length dup [
         [ 0 <int> swap glGetProgramInfoLog ] keep
-        alien>char-string
+        ascii alien>string
     ] with-malloc ;
 
 : check-gl-program ( program -- program )
index c85c0ee21839ca2509fc3dfea73f971fe8442f51..5825ca7270b38d4b8de74074553307a405ad8ffb 100755 (executable)
@@ -1,6 +1,7 @@
-USING: alien alien.c-types assocs bit-arrays hashtables io io.files
-io.sockets kernel mirrors openssl.libcrypto openssl.libssl
-namespaces math math.parser openssl prettyprint sequences tools.test ;
+USING: alien alien.c-types alien.strings assocs bit-arrays
+hashtables io io.files io.encodings.ascii io.sockets kernel
+mirrors openssl.libcrypto openssl.libssl namespaces math
+math.parser openssl prettyprint sequences tools.test ;
 
 ! =========================================================
 ! Some crypto functions (still to be turned into words)
@@ -31,7 +32,7 @@ namespaces math math.parser openssl prettyprint sequences tools.test ;
 ! TODO: debug 'Memory protection fault at address 6c'
 ! get-ctx 1024 "char" malloc-array 1024 0 f password-cb set-default-passwd
 
-[ ] [ get-ctx "password" string>char-alien set-default-passwd-userdata ] unit-test
+[ ] [ get-ctx "password" ascii string>alien set-default-passwd-userdata ] unit-test
 
 ! Enter PEM pass phrase: password
 [ ] [ get-ctx "extra/openssl/test/server.pem" resource-path
index bfa7f3259489f9bfdf1eaf38d9ae523f152e62be..9b237745982451030fea710146fb833282ea1933 100755 (executable)
@@ -3,8 +3,9 @@
 !
 ! Tested with OpenSSL 0.9.8a_0 on Mac OS X 10.4.9 PowerPC
 
-USING: alien alien.c-types assocs kernel libc namespaces
-openssl.libcrypto openssl.libssl sequences ;
+USING: alien alien.c-types alien.strings assocs kernel libc
+namespaces openssl.libcrypto openssl.libssl sequences
+io.encodings.ascii ;
 
 IN: openssl
 
@@ -21,7 +22,7 @@ SYMBOL: rsa
 
 : password-cb ( -- alien )
     "int" { "char*" "int" "int" "void*" } "cdecl"
-    [ 3drop "password" string>char-alien 1023 memcpy
+    [ 3drop "password" ascii string>alien 1023 memcpy
     "password" length ] alien-callback ;
 
 ! =========================================================
index 44b746f8ce792f78c86e7f5dd5bded43e0d3194c..8ef169810af1ca5e35122d8a8f084b1ee27f6ccb 100644 (file)
@@ -4,8 +4,9 @@
 ! Adapted from oci.h and ociap.h
 ! Tested with Oracle version - 10.1.0.3 Instant Client
 
-USING: alien alien.c-types combinators kernel math namespaces oracle.liboci
-prettyprint sequences ;
+USING: alien alien.c-types alien.strings combinators kernel math
+namespaces oracle.liboci prettyprint sequences
+io.encodings.ascii ;
 
 IN: oracle
 
@@ -31,7 +32,7 @@ C: <connection> connection
 : get-oci-error ( object -- * )
     1 f "uint*" <c-object> dup >r 512 "uchar" <c-array> dup >r
     512 OCI_HTYPE_ERROR OCIErrorGet r> r> *uint drop
-    alien>char-string throw ;
+    ascii alien>string throw ;
 
 : check-result ( result -- )
     {
@@ -101,9 +102,9 @@ C: <connection> connection
 
 : oci-log-on ( -- )
     env get err get svc get 
-    con get connection-username dup length swap malloc-char-string swap 
-    con get connection-password dup length swap malloc-char-string swap
-    con get connection-db dup length swap malloc-char-string swap
+    con get connection-username dup length swap ascii malloc-string swap 
+    con get connection-password dup length swap ascii malloc-string swap
+    con get connection-db dup length swap ascii malloc-string swap
     OCILogon check-result ;
 
 ! =========================================================
@@ -118,11 +119,11 @@ C: <connection> connection
     svc get OCI_HTYPE_SVCCTX srv get 0 OCI_ATTR_SERVER err get OCIAttrSet check-result ;
 
 : set-username-attribute ( -- )
-    ses get OCI_HTYPE_SESSION con get connection-username dup length swap malloc-char-string swap 
+    ses get OCI_HTYPE_SESSION con get connection-username dup length swap ascii malloc-string swap 
     OCI_ATTR_USERNAME err get OCIAttrSet check-result ;
 
 : set-password-attribute ( -- )
-    ses get OCI_HTYPE_SESSION con get connection-password dup length swap malloc-char-string swap 
+    ses get OCI_HTYPE_SESSION con get connection-password dup length swap ascii malloc-string swap 
     OCI_ATTR_PASSWORD err get OCIAttrSet check-result ;
 
 : set-attributes ( -- )
@@ -150,7 +151,7 @@ C: <connection> connection
     check-result *void* stm set ;
 
 : prepare-statement ( statement -- )
-    >r stm get err get r> dup length swap malloc-char-string swap
+    >r stm get err get r> dup length swap ascii malloc-string swap
     OCI_NTV_SYNTAX OCI_DEFAULT OCIStmtPrepare check-result ;
 
 : calculate-size ( type -- size )
@@ -222,7 +223,7 @@ C: <connection> connection
 
 : server-version ( -- )
     srv get err get 512 "uchar" malloc-array dup >r 512 OCI_HTYPE_SERVER
-    OCIServerVersion check-result r> alien>char-string . ;
+    OCIServerVersion check-result r> ascii alien>string . ;
 
 ! =========================================================
 ! Public routines
@@ -236,13 +237,13 @@ C: <connection> connection
 
 : fetch-each ( object -- object )
     fetch-statement [
-        buf get alien>char-string res get swap suffix res set
+        buf get ascii alien>string res get swap suffix res set
         fetch-each
     ] [ ] if ;
 
 : run-query ( object -- object )
     execute-statement [
-        buf get alien>char-string res get swap suffix res set
+        buf get ascii alien>string res get swap suffix res set
         fetch-each
     ] [ ] if ;
 
diff --git a/extra/project-euler/076/076.factor b/extra/project-euler/076/076.factor
new file mode 100644 (file)
index 0000000..b09a274
--- /dev/null
@@ -0,0 +1,53 @@
+! Copyright (c) 2008 Eric Mertens
+! See http://factorcode.org/license.txt for BSD license.
+USING: arrays assocs combinators kernel math sequences math.ranges locals ;
+IN: project-euler.076
+
+! http://projecteuler.net/index.php?section=problems&id=76
+
+! DESCRIPTION
+! -----------
+
+! How many different ways can one hundred be written as a
+! sum of at least two positive integers?
+
+! SOLUTION
+! --------
+
+! This solution uses dynamic programming and the following
+! recurence relation:
+
+! ways(0,_) = 1
+! ways(_,0) = 0
+! ways(n,i) = ways(n-i,i) + ways(n,i-1)
+
+<PRIVATE
+
+: init ( n -- table )
+    [1,b] [ 0 2array 0 ] H{ } map>assoc
+    1 { 0 0 } pick set-at ;
+
+: use ( n i -- n i )
+    [ - dup ] keep min ; inline
+
+: ways ( n i table -- )
+    over zero? [
+        3drop
+    ] [
+        [ [ 1-  2array ] dip at     ]
+        [ [ use 2array ] dip at +   ]
+        [ [     2array ] dip set-at ] 3tri
+    ] if ;
+
+:: each-subproblem ( n quot -- )
+    n [1,b] [ dup [1,b] quot with each ] each ; inline
+
+PRIVATE>
+
+: (euler076) ( n -- m )
+    dup init
+    [ [ ways ] curry each-subproblem ]
+    [ [ dup 2array ] dip at 1- ] 2bi ;
+
+: euler076 ( -- m )
+    100 (euler076) ;
diff --git a/extra/project-euler/116/116.factor b/extra/project-euler/116/116.factor
new file mode 100644 (file)
index 0000000..d48cdf1
--- /dev/null
@@ -0,0 +1,55 @@
+! Copyright (c) 2008 Eric Mertens
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel math math.ranges sequences sequences.lib ;
+
+IN: project-euler.116
+
+! http://projecteuler.net/index.php?section=problems&id=116
+
+! DESCRIPTION
+! -----------
+
+! A row of five black square tiles is to have a number of its tiles replaced
+! with coloured oblong tiles chosen from red (length two), green (length
+! three), or blue (length four).
+
+! If red tiles are chosen there are exactly seven ways this can be done.
+! If green tiles are chosen there are three ways.
+! And if blue tiles are chosen there are two ways.
+
+! Assuming that colours cannot be mixed there are 7 + 3 + 2 = 12 ways of
+! replacing the black tiles in a row measuring five units in length.
+
+! How many different ways can the black tiles in a row measuring fifty units in
+! length be replaced if colours cannot be mixed and at least one coloured tile
+! must be used?
+
+! SOLUTION
+! --------
+
+! This solution uses a simple dynamic programming approach using the
+! following recurence relation
+
+! ways(n,_) = 0   | n < 0
+! ways(0,_) = 1
+! ways(n,i) = ways(n-i,i) + ways(n-1,i)
+! solution(n) = ways(n,1) - 1 + ways(n,2) - 1 + ways(n,3) - 1
+
+<PRIVATE
+
+: nth* ( n seq -- elt/0 )
+    [ length swap - 1- ] keep ?nth 0 or ;
+
+: next ( colortile seq -- )
+     [ nth* ] [ peek + ] [ push ] tri ;
+
+: ways ( length colortile -- permutations )
+    V{ 1 } clone [ [ next ] 2curry times ] keep peek 1- ;
+
+PRIVATE>
+
+: (euler116) ( length -- permutations )
+    3 [1,b] [ ways ] with sigma ;
+
+: euler116 ( -- permutations )
+    50 (euler116) ;
diff --git a/extra/project-euler/117/117.factor b/extra/project-euler/117/117.factor
new file mode 100644 (file)
index 0000000..5056560
--- /dev/null
@@ -0,0 +1,42 @@
+! Copyright (c) 2008 Eric Mertens
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel math splitting sequences ;
+
+IN: project-euler.117
+
+! http://projecteuler.net/index.php?section=problems&id=117
+
+! DESCRIPTION
+! -----------
+
+! Using a combination of black square tiles and oblong tiles chosen
+! from: red tiles measuring two units, green tiles measuring three
+! units, and blue tiles measuring four units, it is possible to tile a
+! row measuring five units in length in exactly fifteen different ways.
+
+!  How many ways can a row measuring fifty units in length be tiled?
+
+! SOLUTION
+! --------
+
+! This solution uses a simple dynamic programming approach using the
+! following recurence relation
+
+! ways(i) = 1 | i <= 0
+! ways(i) = ways(i-4) + ways(i-3) + ways(i-2) + ways(i-1)
+
+<PRIVATE
+
+: short ( seq n -- seq n )
+    over length min ;
+
+: next ( seq -- )
+    [ 4 short tail* sum ] keep push ;
+
+PRIVATE>
+
+: (euler117) ( n -- m )
+    V{ 1 } clone tuck [ next ] curry times peek ;
+
+: euler117 ( -- m )
+    50 (euler117) ;
diff --git a/extra/project-euler/148/148.factor b/extra/project-euler/148/148.factor
new file mode 100644 (file)
index 0000000..daad89a
--- /dev/null
@@ -0,0 +1,24 @@
+! Copyright (c) 2008 Eric Mertens
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel math math.functions sequences sequences.lib ;
+
+IN: project-euler.148
+
+<PRIVATE
+
+: sum-1toN ( n -- sum )
+    dup 1+ * 2/ ; inline
+
+: >base7 ( x -- y )
+    [ dup 0 > ] [ 7 /mod ] [ ] unfold nip ;
+
+: (use-digit) ( prev x index -- next )
+    [ [ 1+ * ] [ sum-1toN 7 sum-1toN ] bi ] dip ^ * + ;
+
+PRIVATE>
+
+: (euler148) ( x -- y )
+    >base7 0 [ (use-digit) ] reduce-index ;
+
+: euler148 ( -- y )
+    10 9 ^ (euler148) ;
diff --git a/extra/project-euler/150/150.factor b/extra/project-euler/150/150.factor
new file mode 100644 (file)
index 0000000..c96c1eb
--- /dev/null
@@ -0,0 +1,52 @@
+! Copyright (c) 2008 Eric Mertens
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel math sequences sequences.private locals hints ;
+IN: project-euler.150
+
+<PRIVATE
+
+! sequence helper functions
+
+: partial-sums ( seq -- sums )
+    0 [ + ] accumulate swap suffix ; inline
+
+: (partial-sum-infimum) ( inf sum elt -- inf sum )
+    + [ min ] keep ; inline
+
+: partial-sum-infimum ( seq -- seq )
+    0 0 rot [ (partial-sum-infimum) ] each drop ; inline
+
+: generate ( n quot -- seq )
+    [ drop ] swap compose map ; inline
+
+: map-infimum ( seq quot -- min )
+    [ min ] compose 0 swap reduce ; inline
+
+
+! triangle generator functions
+
+: next ( t -- new-t s )
+    615949 * 797807 + 20 2^ rem dup 19 2^ - ; inline
+
+: sums-triangle ( -- seq )
+    0 1000 [ 1+ [ next ] generate partial-sums ] map nip ; 
+
+PRIVATE>
+
+:: (euler150) ( m -- n )
+    [let | table [ sums-triangle ] |
+        m [| x |
+            x 1+ [| y |
+                m x - [| z |
+                    x z + table nth-unsafe
+                    [ y z + 1+ swap nth-unsafe ]
+                    [ y        swap nth-unsafe ] bi -
+                ] map partial-sum-infimum
+            ] map-infimum
+        ] map-infimum
+    ] ;
+
+HINTS: (euler150) fixnum ;
+
+: euler150 ( -- n )
+    1000 (euler150) ;
diff --git a/extra/project-euler/164/164.factor b/extra/project-euler/164/164.factor
new file mode 100644 (file)
index 0000000..bf1f5dc
--- /dev/null
@@ -0,0 +1,33 @@
+! Copyright (c) 2008 Eric Mertens
+! See http://factorcode.org/license.txt for BSD license.
+USING: arrays assocs kernel math math.ranges sequences ;
+
+IN: project-euler.164
+
+! http://projecteuler.net/index.php?section=problems&id=164
+
+! DESCRIPTION
+! -----------
+
+! How many 20 digit numbers n (without any leading zero) exist such
+! that no three consecutive digits of n have a sum greater than 9?
+
+! SOLUTION
+! --------
+
+<PRIVATE
+
+: next-keys ( key -- keys )
+    [ peek ] [ 10 swap sum - ] bi [ 2array ] with map ;
+
+: next-table ( assoc -- assoc )
+    H{ } clone swap
+    [ swap next-keys [ pick at+ ] with each ] assoc-each ;
+
+: init-table ( -- assoc )
+    9 [1,b] [ 1array 1 ] H{ } map>assoc ;
+
+PRIVATE>
+
+: euler164 ( -- n )
+    init-table 19 [ next-table ] times values sum ;
diff --git a/extra/project-euler/190/190.factor b/extra/project-euler/190/190.factor
new file mode 100644 (file)
index 0000000..6fc15c9
--- /dev/null
@@ -0,0 +1,48 @@
+! Copyright (c) 2008 Eric Mertens
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel sequences sequences.lib math math.functions math.ranges locals ;
+IN: project-euler.190
+
+! PROBLEM
+! -------
+
+! http://projecteuler.net/index.php?section=problems&id=190
+
+! Let Sm = (x1, x2, ... , xm) be the m-tuple of positive real numbers
+! with x1 + x2 + ... + xm = m for which Pm = x1 * x22 * ... * xmm is
+! maximised.
+
+! For example, it can be verified that [P10] = 4112 ([ ] is the integer
+! part function).
+
+! Find Î£[Pm] for 2 â‰¤ m â‰¤ 15.
+
+! SOLUTION
+! --------
+
+! Pm = x1 * x2^2 * x3^3 * ... * xm^m
+! fm = x1 + x2 + x3 + ... + xm - m = 0
+! Gm === Pm - L * fm
+! dG/dx_i = 0 = i * Pm / xi - L
+! xi = i * Pm / L
+
+! Sum(i=1 to m) xi = m
+! Sum(i=1 to m) i * Pm / L = m
+! Pm / L * Sum(i=1 to m) i = m
+! Pm / L * m*(m+1)/2 = m
+! Pm / L = 2 / (m+1)
+
+! xi = i * (2 / (m+1)) = 2*i/(m+1)
+
+<PRIVATE
+
+: PI ( seq quot -- n )
+    [ * ] compose 1 swap reduce ; inline
+
+PRIVATE>
+
+:: P_m ( m -- P_m )
+    m [1,b] [| i | 2 i * m 1+ / i ^ ] PI ;
+
+: euler190 ( -- n )
+    2 15 [a,b] [ P_m truncate ] sigma ;
index a92f256eeb853c47200a7947c7d4f9f87b35c551..c882dd2b4d8f989577557e3517ad5a1bd8ce60e5 100644 (file)
@@ -1,27 +1,29 @@
 USING: kernel math tools.test namespaces random
-random.blum-blum-shub ;
+random.blum-blum-shub alien.c-types sequences splitting ;
 IN: blum-blum-shub.tests
 
 [ 887708070 ] [
-    T{ blum-blum-shub f 590695557939 811977232793 } random-32*
+    T{ blum-blum-shub f 590695557939 811977232793 } clone random-32*
 ] unit-test
 
 
 [ 887708070 ] [
-    T{ blum-blum-shub f 590695557939 811977232793 } [
+    T{ blum-blum-shub f 590695557939 811977232793 } clone [
         32 random-bits
+        little-endian? [ <uint> reverse *uint ] unless
     ] with-random
 ] unit-test
 
 [ 5726770047455156646 ] [
-    T{ blum-blum-shub f 590695557939 811977232793 } [
+    T{ blum-blum-shub f 590695557939 811977232793 } clone [
         64 random-bits
+        little-endian? [ <ulonglong> 4 group [ reverse ] map concat *ulonglong ] unless
     ] with-random
 ] unit-test
 
 [ 3716213681 ]
 [
-    100 T{ blum-blum-shub f 200352954495 846054538649 } tuck [
+    100 T{ blum-blum-shub f 200352954495 846054538649 } clone tuck [
         random-32* drop
     ] curry times
     random-32*
index db8fe540e590f6354a747d422d0864412f62c74d..e60990075c0a27c24ed413c33b80970118bef062 100755 (executable)
@@ -12,17 +12,16 @@ TUPLE: blum-blum-shub x n ;
 : generate-bbs-primes ( numbits -- p q )
     [ [ random-prime ] curry [ 4 mod 3 = ] generate ] dup bi ;
 
+: next-bbs-bit ( bbs -- bit )
+    [ [ x>> 2 ] [ n>> ] bi ^mod dup ] keep (>>x) 1 bitand ;
+
+PRIVATE>
+
 : <blum-blum-shub> ( numbits -- blum-blum-shub )
     generate-bbs-primes *
     [ find-relative-prime ] keep
     blum-blum-shub boa ;
 
-: next-bbs-bit ( bbs -- bit )
-    [ [ x>> 2 ] [ n>> ] bi ^mod ] keep
-    over >>x drop 1 bitand ;
-
-PRIVATE>
-
 M: blum-blum-shub random-32* ( bbs -- r )
     0 32 rot
     [ next-bbs-bit swap 1 shift bitor ] curry times ;
index 5a6b0bdface8c9257cfb156e7858583b3dfb0f8f..e9433c6c64069e9ec4c583f0d9951d191b43b444 100755 (executable)
@@ -226,3 +226,10 @@ IN: regexp-tests
 [ t ] [ "s@f" "[a-z.-]@[a-z]" f <regexp> matches? ] unit-test
 [ f ] [ "a" "[a-z.-]@[a-z]" f <regexp> matches? ] unit-test
 [ t ] [ ".o" "\\.[a-z]" f <regexp> matches? ] unit-test
+
+! Bug in parsing word
+[ t ] [
+    "a"
+    R' a'
+    matches?
+] unit-test
index 6b344ad140450802d30744f394a87162378a532a..d517db09fe245b17cd0325b5b7649e97d8c5c4a2 100755 (executable)
@@ -290,10 +290,11 @@ TUPLE: regexp source parser ignore-case? ;
     } case ;
 
 : parse-regexp ( accum end -- accum )
-    lexer get dup skip-blank [
-        [ index* dup 1+ swap ] 2keep swapd subseq swap
-    ] change-lexer-column
-    lexer get (parse-token) parse-options <regexp> parsed ;
+    lexer get dup skip-blank
+    [ [ index* dup 1+ swap ] 2keep swapd subseq swap ] change-lexer-column
+    lexer get dup still-parsing-line?
+    [ (parse-token) parse-options ] [ drop f ] if
+    <regexp> parsed ;
 
 : R! CHAR: ! parse-regexp ; parsing
 : R" CHAR: " parse-regexp ; parsing
index 77364d73e779f0aeefd9fdf1b5b2e8a049a6eb33..252defe99bb59e3dcc19f99250e3e1446cb2927c 100755 (executable)
@@ -1,10 +1,11 @@
-USING: rss io kernel io.files tools.test io.encodings.utf8 ;
+USING: rss io kernel io.files tools.test io.encodings.utf8
+calendar ;
 IN: rss.tests
 
 : load-news-file ( filename -- feed )
     #! Load an news syndication file and process it, returning
     #! it as an feed tuple.
-    utf8 <file-reader> read-feed ;
+    utf8 file-contents read-feed ;
 
 [ T{
     feed
@@ -35,7 +36,7 @@ IN: rss.tests
             "http://example.org/2005/04/02/atom"
             "\n         <div xmlns=\"http://www.w3.org/1999/xhtml\">\n           <p><i>[Update: The Atom draft is finished.]</i></p>\n         </div>\n       "
 
-            "2003-12-13T08:29:29-04:00"
+            T{ timestamp f 2003 12 13 8 29 29 T{ duration f 0 0 0 -4 0 0 } }
         }
     }
 } ] [ "extra/rss/atom.xml" resource-path load-news-file ] unit-test
index 99360e5509dd3098f9943bc6c1866cff964b9023..5fc688967a8f1b3328cff2a81821636cb427ede2 100644 (file)
@@ -4,10 +4,8 @@ IN: rss
 USING: xml.utilities kernel assocs xml.generator
     strings sequences xml.data xml.writer
     io.streams.string combinators xml xml.entities io.files io
-    http.client namespaces xml.generator hashtables ;
-
-: ?children>string ( tag/f -- string/f )
-    [ children>string ] [ f ] if* ;
+    http.client namespaces xml.generator hashtables
+    calendar.format accessors continuations ;
 
 : any-tag-named ( tag names -- tag-inside )
     f -rot [ tag-named nip dup ] with find 2drop ;
@@ -25,7 +23,7 @@ C: <entry> entry
     [ "link" tag-named children>string ] keep
     [ "description" tag-named children>string ] keep
     f "date" "http://purl.org/dc/elements/1.1/" <name>
-    tag-named ?children>string
+    tag-named dup [ children>string rfc822>timestamp ] when
     <entry> ;
 
 : rss1.0 ( xml -- feed )
@@ -41,7 +39,7 @@ C: <entry> entry
     [ "link" tag-named ] keep
     [ "guid" tag-named dupd ? children>string ] keep
     [ "description" tag-named children>string ] keep
-    "pubDate" tag-named children>string <entry> ;
+    "pubDate" tag-named children>string rfc822>timestamp <entry> ;
 
 : rss2.0 ( xml -- feed )
     "channel" tag-named 
@@ -59,7 +57,7 @@ C: <entry> entry
         [ children>string ] if
     ] keep
     { "published" "updated" "issued" "modified" } any-tag-named
-    children>string <entry> ;
+    children>string rfc3339>timestamp <entry> ;
 
 : atom1.0 ( xml -- feed )
     [ "title" tag-named children>string ] keep
@@ -73,16 +71,12 @@ C: <entry> entry
         { "feed" [ atom1.0 ] }
     } case ;
 
-: read-feed ( stream -- feed )
-    [ read-xml ] with-html-entities xml>feed ;
+: read-feed ( string -- feed )
+    [ string>xml xml>feed ] with-html-entities ;
 
 : download-feed ( url -- feed )
     #! Retrieve an news syndication file, return as a feed tuple.
-    http-get-stream rot success? [
-        nip read-feed
-    ] [
-        2drop "Error retrieving newsfeed file" throw
-    ] if ;
+    http-get read-feed ;
 
 ! Atom generation
 : simple-tag, ( content name -- )
@@ -95,7 +89,7 @@ C: <entry> entry
     "entry" [
         dup entry-title "title" { { "type" "html" } } simple-tag*,
         "link" over entry-link "href" associate contained*,
-        dup entry-pub-date "published" simple-tag,
+        dup entry-pub-date timestamp>rfc3339 "published" simple-tag,
         entry-description [ "content" { { "type" "html" } } simple-tag*, ] when*
     ] tag, ;
 
index dad1dd39194567e1095b91575d81e0fc3afc7828..51bd94d61cef2d8ce2bf7bd114a90d9fa924c900 100755 (executable)
@@ -96,8 +96,6 @@ arc "arc"
     node create-table arc create-table
     create-bootstrap-nodes create-bootstrap-arcs ;
 
-: param ( value key type -- param ) swapd 3array ;
-
 ! db utilities
 : results ( bindings sql -- array )
     f f <simple-statement> [ do-bound-query ] with-disposal ;
@@ -111,6 +109,9 @@ arc "arc"
 : node-results ( results -- nodes )
     [ node-result ] map ;
 
+: param ( value key type -- param )
+    swapd <sqlite-low-level-binding> ;
+
 : subjects-with-cor ( content object relation -- sql-results )
     [ id>> ] bi@
     [
index 15983329d6d5fcec9cf73045e0c830396dc2c42a..b186ee7777c44a86349302b516cc65a88ed723ee 100755 (executable)
@@ -35,6 +35,10 @@ MACRO: firstn ( n -- )
     #! quot: ( elt index -- obj )
     prepare-index 2map ; inline
 
+: reduce-index ( seq identity quot -- )
+    #! quot: ( prev elt index -- next )
+    swapd each-index ; inline
+
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
 : each-percent ( seq quot -- )
@@ -48,7 +52,7 @@ MACRO: firstn ( n -- )
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
 : sigma ( seq quot -- n )
-    [ rot slip + ] curry 0 swap reduce ; inline
+    [ + ] compose 0 swap reduce ; inline
 
 : count ( seq quot -- n )
     [ 1 0 ? ] compose sigma ; inline
@@ -197,9 +201,6 @@ USE: continuations
     >r >r 0 max r> r>
     [ length tuck min >r min r> ] keep subseq ;
 
-: ?head* ( seq n -- seq/f ) (head) ?subseq ;
-: ?tail* ( seq n -- seq/f ) (tail) ?subseq ;
-
 : accumulator ( quot -- quot vec )
     V{ } clone [ [ push ] curry compose ] keep ; inline
 
diff --git a/extra/shell/parser/parser.factor b/extra/shell/parser/parser.factor
new file mode 100644 (file)
index 0000000..46548bb
--- /dev/null
@@ -0,0 +1,94 @@
+
+USING: kernel arrays strings sequences sequences.deep accessors peg peg.ebnf
+       newfx ;
+
+IN: shell.parser
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+TUPLE: basic-expr         command  stdin stdout background ;
+TUPLE: pipeline-expr      commands stdin stdout background ;
+TUPLE: single-quoted-expr expr ;
+TUPLE: double-quoted-expr expr ;
+TUPLE: back-quoted-expr   expr ;
+TUPLE: glob-expr          expr ;
+TUPLE: variable-expr      expr ;
+TUPLE: factor-expr        expr ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: ast>basic-expr ( ast -- obj ) first4 basic-expr boa ;
+
+: ast>pipeline-expr ( ast -- obj )
+  pipeline-expr new
+    over [ 1st ] [ 4th [ 1st ] map ] [ 5th ] tri suffix prefix-on >>commands
+    over 2nd >>stdin
+    over 5th   >>stdout
+    swap 6th   >>background ;
+
+: ast>single-quoted-expr ( ast -- obj )
+  2nd >string single-quoted-expr boa ;
+
+: ast>double-quoted-expr ( ast -- obj )
+  2nd >string double-quoted-expr boa ;
+
+: ast>back-quoted-expr ( ast -- obj )
+  2nd >string back-quoted-expr boa ;
+
+: ast>glob-expr ( ast -- obj ) flatten concat glob-expr boa ;
+
+: ast>variable-expr ( ast -- obj ) 2nd variable-expr boa ;
+
+: ast>factor-expr ( ast -- obj ) 2nd >string factor-expr boa ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+EBNF: expr
+
+space = " "
+
+tab   = "\t"
+
+white = (space | tab)
+
+_ = (white)* => [[ drop ignore ]]
+
+sq = "'"
+dq = '"'
+bq = "`"
+
+single-quoted = sq (!(sq) .)* sq => [[ ast>single-quoted-expr ]]
+double-quoted = dq (!(dq) .)* dq => [[ ast>double-quoted-expr ]]
+back-quoted   = bq (!(bq) .)* bq => [[ ast>back-quoted-expr   ]]
+
+factor = "$(" (!(")") .)* ")" => [[ ast>factor-expr ]]
+
+variable = "$" other => [[ ast>variable-expr ]]
+
+glob-char = ("*" | "?")
+
+non-glob-char = !(glob-char | white) .
+
+glob-beginning-string = (non-glob-char)* => [[ >string ]]
+
+glob-rest-string = (non-glob-char)+ => [[ >string ]]
+
+glob = glob-beginning-string glob-char (glob-rest-string | glob-char)* => [[ ast>glob-expr ]]
+
+other = (!(white | "&" | ">" | ">>" | "<" | "|") .)+ => [[ >string ]]
+
+element = (single-quoted | double-quoted | back-quoted | factor | variable | glob | other)
+
+command = (element _)+
+
+to-file = ">"  _ other => [[ second ]]
+in-file = "<"  _ other => [[ second ]]
+ap-file = ">>" _ other => [[ second ]]
+
+basic = _ command _ (in-file)? _ (to-file | ap-file)? _ ("&")? => [[ ast>basic-expr ]]
+
+pipeline = _ command _ (in-file)? _ "|" _ (command _ "|" _)* command _ (to-file | ap-file)? _ ("&")? => [[ ast>pipeline-expr ]]
+
+submission = (pipeline | basic)
+
+;EBNF
\ No newline at end of file
diff --git a/extra/shell/shell.factor b/extra/shell/shell.factor
new file mode 100644 (file)
index 0000000..7f30104
--- /dev/null
@@ -0,0 +1,143 @@
+
+USING: kernel parser words continuations namespaces debugger
+       sequences combinators splitting prettyprint
+       system io io.files io.launcher io.encodings.utf8 sequences.deep
+       accessors multi-methods newfx shell.parser ;
+
+IN: shell
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: cd ( args -- )
+  dup empty?
+    [ drop home set-current-directory ]
+    [ first     set-current-directory ]
+  if ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: pwd ( args -- )
+  drop
+  current-directory get
+  print ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: swords ( -- seq ) { "cd" "pwd" } ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+GENERIC: expand ( expr -- expr )
+
+METHOD: expand { single-quoted-expr } expr>> ;
+
+METHOD: expand { double-quoted-expr } expr>> ;
+
+METHOD: expand { variable-expr } expr>> os-env ;
+
+METHOD: expand { glob-expr }
+  expr>>
+  dup "*" =
+    [ drop current-directory get directory [ first ] map ]
+    [ ]
+  if ;
+
+METHOD: expand { factor-expr } expr>> eval unparse ;
+
+DEFER: expansion
+
+METHOD: expand { back-quoted-expr }
+  expr>>
+  expr
+  ast>>
+  command>>
+  expansion
+  utf8 <process-stream>
+  contents
+  " \n" split
+  "" remove ;
+
+METHOD: expand { object } ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: expansion ( command -- command ) [ expand ] map flatten ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: run-sword ( basic-expr -- )
+  command>> expansion unclip "shell" lookup execute ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: run-foreground ( process -- )
+  [ try-process ] [ print-error drop ] recover ;
+
+: run-background ( process -- ) run-detached drop ;
+
+: run-basic-expr ( basic-expr -- )
+  <process>
+    over command>> expansion >>command
+    over stdin>>             >>stdin
+    over stdout>>            >>stdout
+  swap background>>
+    [ run-background ]
+    [ run-foreground ]
+  if ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: basic-chant ( basic-expr -- )
+  dup command>> first swords member-of?
+    [ run-sword ]
+    [ run-basic-expr ]
+  if ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: pipeline-chant ( pipeline-chant -- )
+  drop "ix: pipelines not supported" print ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: chant ( obj -- )
+  dup basic-expr?
+    [ basic-chant    ]
+    [ pipeline-chant ]
+  if ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: prompt ( -- )
+  current-directory get write
+  " $ " write
+  flush ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+DEFER: shell
+
+: handle ( input -- )
+  {
+    { [ dup f = ]      [ drop ] }
+    { [ dup "exit" = ] [ drop ] }
+    { [ dup "" = ]     [ drop shell ] }
+    { [ dup expr ]     [ expr ast>> chant shell ] }
+    { [ t ]            [ drop "ix: ignoring input" print shell ] }
+  }
+    cond ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: shell ( -- )
+  prompt
+  readln
+  handle ;
+  
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: ix ( -- ) shell ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+MAIN: ix
\ No newline at end of file
index b0ba85c97f55dea438a78ea3d4445947e298a720..1cb82253b1d5ef884be8b856be4d4e2debf0918b 100644 (file)
@@ -1,6 +1,6 @@
 ! Based on http://www.ffconsultancy.com/ocaml/sudoku/index.html
 USING: sequences namespaces kernel math math.parser io
-io.styles combinators ;
+io.styles combinators columns ;
 IN: sudoku
 
 SYMBOL: solutions
index b8386542488b6f459e253410de9c999faa85c226..d4fbf1de7872df6e5776ae19a95448b4fd37075c 100755 (executable)
@@ -8,6 +8,15 @@ debugger io.streams.c io.streams.duplex io.files io.backend
 quotations io.launcher words.private tools.deploy.config
 bootstrap.image io.encodings.utf8 accessors ;
 IN: tools.deploy.backend
+    
+: copy-vm ( executable bundle-name extension -- vm )
+  [ prepend-path ] dip append vm over copy-file ;
+  
+: copy-fonts ( name dir -- )  
+  append-path "fonts/" resource-path swap copy-tree-into ;
+  
+: image-name ( vocab bundle-name -- str )  
+  prepend-path ".image" append ;
 
 : (copy-lines) ( stream -- )
     dup stream-readln dup
index b22523624917b10c789b078144feb4a94dc39bc0..eccb3982c7c3342399b7797c6a179b89a67294da 100755 (executable)
@@ -7,7 +7,12 @@ ARTICLE: "tools.deploy" "Application deployment"
 $nl
 "For example, we can deploy the " { $vocab-link "hello-world" } " demo which comes with Factor:"
 { $code "\"hello-ui\" deploy" }
-"On Mac OS X, this yields a program named " { $snippet "Hello world.app" } ". On Windows, it yields a directory named " { $snippet "Hello world" } " containing a program named " { $snippet "hello-ui.exe" } ". In both cases, running the program displays a window with a message."
+{ $list
+   { "On Mac OS X, this yields a program named " { $snippet "Hello world.app" } "." }
+   { "On Windows, it yields a directory named " { $snippet "Hello world" } " containing a program named " { $snippet "hello-ui.exe" } "." }
+   { "On Unix-like systems (Linux, BSD, Solaris, etc), it yields a directory named " { $snippet "Hello world" } " containing a program named " { $snippet "hello-ui" } "." }
+}
+"In all cases, running the program displays a window with a message."
 $nl
 "The deployment tool works by bootstrapping a fresh image, loading the vocabulary into this image, then applying various heuristics to strip the image down to minimal size."
 $nl
index 893b43844a1ec0fa1e9cd6191b8c8e1a750bedcc..e57cc1f04b1322dfe083d5de7745b4d31f71364b 100755 (executable)
@@ -1,9 +1,13 @@
 ! Copyright (C) 2007, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: tools.deploy.backend system vocabs.loader kernel ;
+USING: tools.deploy.backend system vocabs.loader kernel
+combinators ;
 IN: tools.deploy
 
 : deploy ( vocab -- ) deploy* ;
 
-os macosx? [ "tools.deploy.macosx" require ] when
-os winnt? [ "tools.deploy.windows" require ] when
+{
+    { [ os macosx? ] [ "tools.deploy.macosx" ] }
+    { [ os winnt? ] [ "tools.deploy.windows" ] }
+    { [ os unix? ] [ "tools.deploy.unix" ] }
+} cond require
\ No newline at end of file
index 3121866d94f3d6d5bc231712e7636c4a0c2f3905..d38b40db4b96c5d216d623238f6e59654ef6591e 100755 (executable)
@@ -14,13 +14,6 @@ IN: tools.deploy.macosx
     bundle-dir over append-path -rot
     "Contents" prepend-path append-path copy-tree ;
 
-: copy-vm ( executable bundle-name -- vm )
-    "Contents/MacOS/" append-path prepend-path vm over copy-file ;
-
-: copy-fonts ( name -- )
-    "fonts/" resource-path
-    swap "Contents/Resources/" append-path copy-tree-into ;
-
 : app-plist ( executable bundle-name -- assoc )
     [
         "6.0" "CFBundleInfoDictionaryVersion" set
@@ -38,10 +31,14 @@ IN: tools.deploy.macosx
     write-plist ;
 
 : create-app-dir ( vocab bundle-name -- vm )
-    dup "Frameworks" copy-bundle-dir
-    dup "Resources/English.lproj/MiniFactor.nib" copy-bundle-dir
-    dup copy-fonts
-    2dup create-app-plist copy-vm ;
+    [
+        nip
+        [ "Frameworks" copy-bundle-dir ]
+        [ "Resources/English.lproj/MiniFactor.nib" copy-bundle-dir ]
+        [ "Contents/Resources/" copy-fonts ] tri
+    ]
+    [ create-app-plist ]
+    [ "Contents/MacOS/" append-path "" copy-vm ] 2tri ;
 
 : deploy.app-image ( vocab bundle-name -- str )
     [ % "/Contents/Resources/" % % ".image" % ] "" make ;
@@ -50,9 +47,8 @@ IN: tools.deploy.macosx
     deploy-name get ".app" append ;
 
 : show-in-finder ( path -- )
-    NSWorkspace
-    -> sharedWorkspace
-    over <NSString> rot parent-directory <NSString>
+    [ NSWorkspace -> sharedWorkspace ]
+    [ normalize-path [ <NSString> ] [ parent-directory <NSString> ] bi ] bi*
     -> selectFile:inFileViewerRootedAtPath: drop ;
 
 M: macosx deploy* ( vocab -- )
@@ -63,6 +59,6 @@ M: macosx deploy* ( vocab -- )
             [ bundle-name create-app-dir ] keep
             [ bundle-name deploy.app-image ] keep
             namespace make-deploy-image
-            bundle-name normalize-path show-in-finder
+            bundle-name show-in-finder
         ] bind
     ] with-directory ;
diff --git a/extra/tools/deploy/unix/authors.txt b/extra/tools/deploy/unix/authors.txt
new file mode 100644 (file)
index 0000000..4b7af4a
--- /dev/null
@@ -0,0 +1 @@
+James Cash
diff --git a/extra/tools/deploy/unix/summary.txt b/extra/tools/deploy/unix/summary.txt
new file mode 100644 (file)
index 0000000..7cd80c5
--- /dev/null
@@ -0,0 +1 @@
+Deploying minimal stand-alone binaries on *nix-like systems
diff --git a/extra/tools/deploy/unix/tags.txt b/extra/tools/deploy/unix/tags.txt
new file mode 100644 (file)
index 0000000..ef1aab0
--- /dev/null
@@ -0,0 +1 @@
+tools
diff --git a/extra/tools/deploy/unix/unix.factor b/extra/tools/deploy/unix/unix.factor
new file mode 100644 (file)
index 0000000..6f5a030
--- /dev/null
@@ -0,0 +1,23 @@
+! Copyright (C) 2008 James Cash
+! See http://factorcode.org/license.txt for BSD license.
+USING: io io.files io.backend kernel namespaces sequences
+system tools.deploy.backend tools.deploy.config assocs
+hashtables prettyprint ;
+IN: tools.deploy.unix
+
+: create-app-dir ( vocab bundle-name -- vm )
+    dup "" copy-fonts
+    "" copy-vm ;
+
+: bundle-name ( -- str )
+    deploy-name get ;
+
+M: unix deploy* ( vocab -- )
+    "." resource-path [
+        dup deploy-config [
+            [ bundle-name create-app-dir ] keep
+            [ bundle-name image-name ] keep
+            namespace make-deploy-image
+            bundle-name normalize-path [ "Binary deployed to " % % "." % ] "" make print
+        ] bind
+    ] with-directory ;
\ No newline at end of file
index 68b106663c1fca4957a11f9d55e5b2863d2b606e..5af3062e39dafaa7255ec61301422da8877c074d 100755 (executable)
@@ -5,25 +5,14 @@ tools.deploy.backend tools.deploy.config assocs hashtables
 prettyprint windows.shell32 windows.user32 ;
 IN: tools.deploy.windows
 
-: copy-vm ( executable bundle-name -- vm )
-    prepend-path ".exe" append
-    vm over copy-file ;
-
-: copy-fonts ( bundle-name -- )
-    "fonts/" resource-path swap copy-tree-into ;
-
 : copy-dlls ( bundle-name -- )
-    { "freetype6.dll" "zlib1.dll" "factor.dll" }
-    [ resource-path ] map
+    { "resource:freetype6.dll" "resource:zlib1.dll" "resource:factor.dll" }
     swap copy-files-into ;
 
 : create-exe-dir ( vocab bundle-name -- vm )
     dup copy-dlls
-    dup copy-fonts
-    copy-vm ;
-
-: image-name ( vocab bundle-name -- str )
-    prepend-path ".image" append ;
+    dup "" copy-fonts
+    ".exe" copy-vm ;
 
 M: winnt deploy*
     "." resource-path [
@@ -31,6 +20,6 @@ M: winnt deploy*
             [ deploy-name get create-exe-dir ] keep
             [ deploy-name get image-name ] keep
             [ namespace make-deploy-image ] keep
-            (normalize-path) open-in-explorer
+            open-in-explorer
         ] bind
     ] with-directory ;
index 8a5ab42767d3df122eeed021c52992fa4920821e..6bf3c5376811df5a693caa612141d22b8c6533f4 100755 (executable)
@@ -138,7 +138,6 @@ SYMBOL: +stopped+
     >n ndrop >c c>
     continue continue-with
     stop yield suspend sleep (spawn)
-    suspend
 } [
     dup [ execute break ] curry
     "step-into" set-word-prop
index ab0c3015251ad5cc1ff602da257031e79efdbdb1..83890788e3675b4dfea8a6a3636252debf799640 100755 (executable)
@@ -126,6 +126,13 @@ CLASS: {
     { +name+ "FactorView" }
     { +protocols+ { "NSTextInput" } }
 }
+
+! Rendering
+! Rendering
+{ "drawRect:" "void" { "id" "SEL" "id" "NSRect" }
+    [ 3drop window relayout-1 ]
+}
+
 ! Events
 { "acceptsFirstMouse:" "bool" { "id" "SEL" "id" }
     [ 3drop 1 ]
index 90eb6254cd57bce74153f77935716a0dfd12a8dc..c7db687dc3f53c061b4037c43e3b0e5ab16d7878 100755 (executable)
@@ -66,7 +66,7 @@ M: word command-description ( word -- str )
     H{ { +nullary+ f } { +listener+ f } { +description+ f } } ;
 
 : define-command ( word hash -- )
-    default-flags swap assoc-union >r word-props r> update ;
+    [ word-props ] [ default-flags swap assoc-union ] bi* update ;
 
 : command-quot ( target command -- quot )
     dup 1quotation swap +nullary+ word-prop
index 342c360c8311ba047c1ac0b47e715508f5760606..99512562495faf382cdbb1af5a0df45ee9dd5fa8 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2006 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays kernel math namespaces sequences words io
-io.streams.string math.vectors ui.gadgets ;
+io.streams.string math.vectors ui.gadgets columns ;
 IN: ui.gadgets.grids
 
 TUPLE: grid children gap fill? ;
index 396a494ef3a4dd6bde55a94c4884497412c9e81e..ce2bf40db8ee2d0f3766a3a76f03a3eb428f80d9 100755 (executable)
@@ -1,10 +1,9 @@
-! Copyright (C) 2005, 2007 Slava Pestov.
+! Copyright (C) 2005, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: arrays ui.gadgets
-ui.gadgets.viewports ui.gadgets.frames ui.gadgets.grids
-ui.gadgets.theme ui.gadgets.sliders ui.gestures kernel math
-namespaces sequences models combinators math.vectors
-classes.tuple ;
+USING: accessors arrays ui.gadgets ui.gadgets.viewports
+ui.gadgets.frames ui.gadgets.grids ui.gadgets.theme
+ui.gadgets.sliders ui.gestures kernel math namespaces sequences
+models combinators math.vectors classes.tuple ;
 IN: ui.gadgets.scrollers
 
 TUPLE: scroller viewport x y follows ;
@@ -133,3 +132,13 @@ M: scroller focusable-child*
 
 M: scroller model-changed
     nip f swap set-scroller-follows ;
+
+TUPLE: limited-scroller dim ;
+
+: <limited-scroller> ( gadget -- scroller )
+    <scroller>
+    limited-scroller new
+    [ set-gadget-delegate ] keep ;
+
+M: limited-scroller pref-dim*
+    dim>> ;
index 8ee64b58be3f5d7f9bbfcee23d92d47257c75c9e..b63e7f9d2e5fdbca7707ded01f3c481dd73b49b5 100755 (executable)
@@ -48,9 +48,6 @@ M: world request-focus-on ( child gadget -- )
 
 M: world hashcode* drop world hashcode* ;
 
-M: world pref-dim*
-    delegate pref-dim* [ >fixnum ] map { 1024 768 } vmin ;
-
 M: world layout*
     dup delegate layout*
     dup world-glass [
index f68a70c2bd5c312d0efde2d9fe31b83a575accb8..ed0f38b7430b19d0e71c22b2a8e26f8ae0f2c48a 100755 (executable)
@@ -3,7 +3,7 @@
 USING: arrays assocs kernel math models namespaces
 sequences words strings system hashtables math.parser
 math.vectors classes.tuple classes ui.gadgets boxes
-calendar alarms symbols combinators sets ;
+calendar alarms symbols combinators sets columns ;
 IN: ui.gestures
 
 : set-gestures ( class hash -- ) "gestures" set-word-prop ;
index 6c2a5e317d67dc19425a4804baaeb7563dffa08f..d96270075f165c6f8be82f6bef1e37f3d85654f7 100755 (executable)
@@ -24,19 +24,10 @@ TUPLE: listener-gadget input output stack ;
 : <listener-input> ( listener -- gadget )
     listener-gadget-output <pane-stream> <interactor> ;
 
-TUPLE: input-scroller ;
-
-: <input-scroller> ( interactor -- scroller )
-    <scroller>
-    input-scroller new
-    [ set-gadget-delegate ] keep ;
-
-M: input-scroller pref-dim*
-    drop { 0 100 } ;
-
 : listener-input, ( -- )
     g <listener-input> g-> set-listener-gadget-input
-    <input-scroller> "Input" <labelled-gadget> f track, ;
+    <limited-scroller> { 0 100 } >>dim
+    "Input" <labelled-gadget> f track, ;
 
 : welcome. ( -- )
    "If this is your first time with Factor, please read the " print
@@ -111,7 +102,7 @@ M: method-body word-completion-string
 
 USE: generic.standard.engines.tuple
 
-M: tuple-dispatch-engine-word word-completion-string
+M: engine-word word-completion-string
     "engine-generic" word-prop word-completion-string ;
 
 : use-if-necessary ( word seq -- )
index 54caf8be1225faef67e3bd927e1e80275b24d7bd..fb0ce0adf24e1c2cd8ad53b388b97dd233300b8d 100755 (executable)
@@ -1,10 +1,41 @@
 IN: ui.tools.walker\r
 USING: help.markup help.syntax ui.commands ui.operations\r
-tools.walker ;\r
+ui.render tools.walker sequences ;\r
+\r
+ARTICLE: "ui-walker-step" "Stepping through code"\r
+"If the current position points to a word, the various stepping commands behave as follows:"\r
+{ $list\r
+    { { $link com-step } " executes the word and moves the current position one word further." }\r
+    { { $link com-into } " enters the word's definition, unless it is a primitive, in which case it behaves like " { $link com-step } "." }\r
+    { { $link com-out } " executes until the end of the current quotation." }\r
+}\r
+"If the current position points to a literal, the various stepping commands behave as follows:"\r
+{ $list\r
+    { { $link com-step } " pushes the literal on the data stack." }\r
+    { { $link com-into } " pushes the literal. If it is a quotation, a breakpoint is inserted at the beginning of the quotation, and if it is an array of quotations, a breakpoint is inserted at the beginning of each quotation element." }\r
+    { { $link com-out } " executes until the end of the current quotation." }\r
+}\r
+"The behavior of the " { $link com-into } " command is useful when debugging code using combinators. Instead of stepping into the definition of a combinator, which may be quite complex, you can set a breakpoint on the quotation and continue. For example, suppose the following quotation is being walked:"\r
+{ $code "{ 10 20 30 } [ 3 + . ] each" }\r
+"If the current position is on the quotation and " { $link com-into } " is invoked, the following quotation is pushed on the stack:"\r
+{ $code "[ break 3 + . ]" }\r
+"Invoking " { $link com-continue } " will continue execution until the breakpoint is hit, which in this case happens immediately. The stack can then be inspected to verify that the first element of the array, 10, was pushed. Invoking " { $link com-continue } " proceeds until the breakpoint is hit on the second iteration, at which time the top of the stack will contain the value 20. Invoking " { $link com-continue } " a third time will proceed on to the final iteration where 30 is at the top of the stack. Invoking " { $link com-continue } " again will end the walk of this code snippet, since no more iterations remain the quotation will never be called again and the breakpoint will not be hit."\r
+$nl\r
+"The " { $link com-back } " command travels backwards through time, and restore stacks. This does not undo side effects (modifying array entries, writing to files, formatting the hard drive, etc) and therefore can only be used reliably on referentially transparent code." ;\r
+\r
+ARTICLE: "breakpoints" "Setting breakpoints"\r
+"In addition to invoking the walker explicitly through the UI, it is possible to set breakpoints on words. See " { $link "tools.annotations" } "."\r
+$nl\r
+"Breakpoints can be inserted directly into code:"\r
+{ $subsection break }\r
+"Note that because the walker calls various core library and UI words while rendering its own user interface, setting a breakpoint on a word such as " { $link append } " or " { $link draw-gadget } " will hang the UI." ;\r
 \r
 ARTICLE: "ui-walker" "UI walker"\r
 "The walker single-steps through quotations. To use the walker, enter a piece of code in the listener's input area and press " { $operation walk } "."\r
 $nl\r
-"The walker can travel backwards through time, and restore stacks. This does not undo side effects and therefore can only be used reliably on referentially transparent code."\r
-{ $command-map walker-gadget "toolbar" }\r
-"Walkers are instances of " { $link walker-gadget } "." ;\r
+"Walkers are instances of " { $link walker-gadget } "."\r
+{ $subsection "ui-walker-step" }\r
+{ $subsection "breakpoints" }\r
+{ $command-map walker-gadget "toolbar" } ;\r
+\r
+ABOUT: "ui-walker"\r
index d79fa92f5434b93b933cb6e8c07508eddcf13db1..5a334ab56b62efe604b16573eb9088dfe0e65d3a 100755 (executable)
@@ -5,7 +5,7 @@ sequences ui ui.backend ui.tools.debugger ui.gadgets
 ui.gadgets.books ui.gadgets.buttons ui.gadgets.labelled
 ui.gadgets.panes ui.gadgets.scrollers ui.gadgets.tracks
 ui.gadgets.worlds ui.gadgets.presentations ui.gadgets.status-bar
-ui.commands ui.gestures assocs arrays namespaces ;
+ui.commands ui.gestures assocs arrays namespaces accessors ;
 IN: ui.tools.workspace
 
 TUPLE: workspace book listener popup ;
@@ -49,7 +49,10 @@ M: gadget tool-scroller drop f ;
     get-workspace find-tool nip ;
 
 : help-window ( topic -- )
-    [ <pane> [ [ help ] with-pane ] keep <scroller> ] keep
+    [
+        <pane> [ [ help ] with-pane ] keep
+        <limited-scroller> { 550 700 } >>dim
+    ] keep
     article-title open-window ;
 
 : hide-popup ( workspace -- )
index 6229fc9a6555973b07c8f002c9b4590d41ceb938..e3e1fc51249291df65d9de02cd64fcb05241f2a5 100755 (executable)
@@ -1,13 +1,14 @@
 ! Copyright (C) 2005, 2006 Doug Coleman.
+! Portions copyright (C) 2007, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien alien.c-types arrays assocs ui ui.gadgets
-ui.backend ui.clipboards ui.gadgets.worlds ui.gestures io kernel
-math math.vectors namespaces prettyprint sequences strings
-vectors words windows.kernel32 windows.gdi32 windows.user32
-windows.opengl32 windows.messages windows.types windows.nt
-windows threads libc combinators continuations command-line
-shuffle opengl ui.render unicode.case ascii math.bitfields
-locals symbols accessors ;
+USING: alien alien.c-types alien.strings arrays assocs ui
+ui.gadgets ui.backend ui.clipboards ui.gadgets.worlds
+ui.gestures io kernel math math.vectors namespaces prettyprint
+sequences strings vectors words windows.kernel32 windows.gdi32
+windows.user32 windows.opengl32 windows.messages windows.types
+windows.nt windows threads libc combinators continuations
+command-line shuffle opengl ui.render unicode.case ascii
+math.bitfields locals symbols accessors ;
 IN: ui.windows
 
 SINGLETON: windows-ui-backend
@@ -36,14 +37,14 @@ SINGLETON: windows-ui-backend
             CF_UNICODETEXT GetClipboardData dup win32-error=0/f
             dup GlobalLock dup win32-error=0/f
             GlobalUnlock win32-error=0/f
-            alien>u16-string
+            utf16n alien>string
         ] if
     ] with-clipboard
     crlf>lf ;
 
 : copy ( str -- )
     lf>crlf [
-        string>u16-alien
+        utf16n string>alien
         EmptyClipboard win32-error=0/f
         GMEM_MOVEABLE over length 1+ GlobalAlloc
             dup win32-error=0/f
@@ -409,7 +410,7 @@ SYMBOL: trace-messages?
         0 over set-WNDCLASSEX-cbClsExtra
         0 over set-WNDCLASSEX-cbWndExtra
         f GetModuleHandle over set-WNDCLASSEX-hInstance
-        f GetModuleHandle "fraptor" string>u16-alien LoadIcon
+        f GetModuleHandle "fraptor" utf16n string>alien LoadIcon
         over set-WNDCLASSEX-hIcon
         f IDC_ARROW LoadCursor over set-WNDCLASSEX-hCursor
 
@@ -447,7 +448,7 @@ SYMBOL: trace-messages?
 : init-win32-ui ( -- )
     V{ } clone nc-buttons set-global
     "MSG" malloc-object msg-obj set-global
-    "Factor-window" malloc-u16-string class-name-ptr set-global
+    "Factor-window" utf16n malloc-string class-name-ptr set-global
     register-wndclassex drop
     GetDoubleClickTime double-click-timeout set-global ;
 
@@ -492,7 +493,7 @@ M: windows-ui-backend raise-window* ( world -- )
 M: windows-ui-backend set-title ( string world -- )
     world-handle
     dup win-title [ free ] when*
-    >r malloc-u16-string r>
+    >r utf16n malloc-string r>
     2dup set-win-title
     win-hWnd WM_SETTEXT 0 roll alien-address SendMessage drop ;
 
index c04427185390bed4441730d029297eb76f9f1afa..606a45eba5db65b92f9c7087250cbeb4b0c076c1 100755 (executable)
@@ -1,11 +1,12 @@
 ! Copyright (C) 2005, 2007 Eduardo Cavazos and Slava Pestov
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien alien.c-types arrays ui ui.gadgets ui.gestures
-ui.backend ui.clipboards ui.gadgets.worlds assocs kernel math
-namespaces opengl sequences strings x11.xlib x11.events x11.xim
-x11.glx x11.clipboard x11.constants x11.windows io.encodings.string
+ui.backend ui.clipboards ui.gadgets.worlds ui.render assocs
+kernel math namespaces opengl sequences strings x11.xlib
+x11.events x11.xim x11.glx x11.clipboard x11.constants
+x11.windows io.encodings.string io.encodings.ascii
 io.encodings.utf8 combinators debugger command-line qualified
-ui.render math.vectors classes.tuple opengl.gl threads ;
+math.vectors classes.tuple opengl.gl threads ;
 QUALIFIED: system
 IN: ui.x11
 
@@ -137,8 +138,8 @@ M: world selection-notify-event
     } cond ;
 
 : encode-clipboard ( string type -- bytes )
-    XSelectionRequestEvent-target XA_UTF8_STRING =
-    [ utf8 encode ] [ string>char-alien ] if ;
+    XSelectionRequestEvent-target
+    XA_UTF8_STRING = utf8 ascii ? encode ;
 
 : set-selection-prop ( evt -- )
     dpy get swap
index 31adc5c23767f46069b4da6ef02bc7ab98284313..d688153bd05df886cbe53db1069d07959135fb63 100755 (executable)
@@ -10,7 +10,7 @@ IN: unix.linux.ifreq
 
 : set-if-addr ( name addr -- )
   "struct-ifreq" <c-object>
-  rot  string>char-alien        over set-struct-ifreq-ifr-ifrn
+  rot  ascii string>alien       over set-struct-ifreq-ifr-ifrn
   swap 0 <inet4> make-sockaddr  over set-struct-ifreq-ifr-ifru
 
   AF_INET SOCK_DGRAM 0 socket SIOCSIFADDR rot ioctl drop ;
@@ -19,7 +19,7 @@ IN: unix.linux.ifreq
 
 : set-if-flags ( name flags -- )
   "struct-ifreq" <c-object>
-  rot  string>char-alien over set-struct-ifreq-ifr-ifrn
+  rot  ascii string>alien over set-struct-ifreq-ifr-ifrn
   swap <short>          over set-struct-ifreq-ifr-ifru
 
   AF_INET SOCK_DGRAM 0 socket SIOCSIFFLAGS rot ioctl drop ;
@@ -28,7 +28,7 @@ IN: unix.linux.ifreq
 
 : set-if-dst-addr ( name addr -- )
   "struct-ifreq" <c-object>
-  rot  string>char-alien        over set-struct-ifreq-ifr-ifrn
+  rot  ascii string>alien       over set-struct-ifreq-ifr-ifrn
   swap 0 <inet4> make-sockaddr  over set-struct-ifreq-ifr-ifru
 
   AF_INET SOCK_DGRAM 0 socket SIOCSIFDSTADDR rot ioctl drop ;
@@ -37,7 +37,7 @@ IN: unix.linux.ifreq
 
 : set-if-brd-addr ( name addr -- )
   "struct-ifreq" <c-object>
-  rot  string>char-alien        over set-struct-ifreq-ifr-ifrn
+  rot  ascii string>alien       over set-struct-ifreq-ifr-ifrn
   swap 0 <inet4> make-sockaddr  over set-struct-ifreq-ifr-ifru
 
   AF_INET SOCK_DGRAM 0 socket SIOCSIFBRDADDR rot ioctl drop ;
@@ -46,7 +46,7 @@ IN: unix.linux.ifreq
 
 : set-if-netmask ( name addr -- )
   "struct-ifreq" <c-object>
-  rot  string>char-alien        over set-struct-ifreq-ifr-ifrn
+  rot  ascii string>alien       over set-struct-ifreq-ifr-ifrn
   swap 0 <inet4> make-sockaddr  over set-struct-ifreq-ifr-ifru
 
   AF_INET SOCK_DGRAM 0 socket SIOCSIFNETMASK rot ioctl drop ;
@@ -55,7 +55,7 @@ IN: unix.linux.ifreq
 
 : set-if-metric ( name metric -- )
   "struct-ifreq" <c-object>
-  rot string>char-alien over set-struct-ifreq-ifr-ifrn
+  rot ascii string>alien over set-struct-ifreq-ifr-ifrn
   swap <int>           over set-struct-ifreq-ifr-ifru
 
   AF_INET SOCK_DGRAM 0 socket SIOCSIFMETRIC rot ioctl drop ;
\ No newline at end of file
index ba02f15c7a29e0ca12e645d9967c6773d2bcc6bd..0abefe14f1f8c05169b0f39e9c74f202ddabe080 100755 (executable)
@@ -1,7 +1,6 @@
-USING: kernel alien.c-types sequences math unix
-vectors kernel namespaces continuations
-threads assocs vectors io.unix.backend ;
-
+USING: kernel alien.c-types alien.strings sequences math unix
+vectors kernel namespaces continuations threads assocs vectors
+io.unix.backend io.encodings.utf8 ;
 IN: unix.process
 
 ! Low-level Unix process launching utilities. These are used
@@ -9,16 +8,16 @@ IN: unix.process
 ! io.launcher instead.
 
 : >argv ( seq -- alien )
-    [ malloc-char-string ] map f suffix >c-void*-array ;
+    [ utf8 malloc-string ] map f suffix >c-void*-array ;
 
 : exec ( pathname argv -- int )
-    [ malloc-char-string ] [ >argv ] bi* execv ;
+    [ utf8 malloc-string ] [ >argv ] bi* execv ;
 
 : exec-with-path ( filename argv -- int )
-    [ malloc-char-string ] [ >argv ] bi* execvp ;
+    [ utf8 malloc-string ] [ >argv ] bi* execvp ;
 
 : exec-with-env ( filename argv envp -- int )
-    [ malloc-char-string ] [ >argv ] [ >argv ] tri* execve ;
+    [ utf8 malloc-string ] [ >argv ] [ >argv ] tri* execve ;
 
 : exec-args ( seq -- int )
     [ first ] [ ] bi exec ;
diff --git a/extra/update/update.factor b/extra/update/update.factor
new file mode 100644 (file)
index 0000000..9b10ea7
--- /dev/null
@@ -0,0 +1,63 @@
+
+USING: kernel system sequences io.files io.launcher bootstrap.image
+       http.client
+       builder.util builder.release.branch ;
+
+IN: update
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: run-command ( cmd -- ) to-strings try-process ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: git-pull-clean ( -- )
+  image parent-directory
+    [
+      { "git" "pull" "git://factorcode.org/git/factor.git" branch-name }
+      run-command
+    ]
+  with-directory ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: remote-clean-image ( -- url )
+  "http://factorcode.org/images/clean/" my-boot-image-name append ;
+
+: download-clean-image ( -- ) remote-clean-image download ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: make-clean ( -- ) { gnu-make "clean" } run-command ;
+: make       ( -- ) { gnu-make         } run-command ;
+: boot       ( -- ) { "./factor" { "-i=" my-boot-image-name } } run-command ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: rebuild ( -- )
+  image parent-directory
+    [
+      download-clean-image
+      make-clean
+      make
+      boot
+    ]
+  with-directory ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+: update ( -- )
+  image parent-directory
+    [
+      git-id
+      git-pull-clean
+      git-id
+      = not
+        [ rebuild ]
+      when
+    ]
+  with-directory ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+MAIN: update
\ No newline at end of file
diff --git a/extra/webapps/factor-website/factor-website.factor b/extra/webapps/factor-website/factor-website.factor
new file mode 100644 (file)
index 0000000..3483d43
--- /dev/null
@@ -0,0 +1,38 @@
+! Copyright (c) 2008 Slava Pestov
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors kernel sequences io.files io.sockets
+db.sqlite smtp namespaces db
+http.server.db
+http.server.sessions
+http.server.auth.login
+http.server.auth.providers.db
+http.server.sessions.storage.db
+http.server.boilerplate
+http.server.templating.chloe ;
+IN: webapps.factor-website
+
+: factor-template ( path -- template )
+    "resource:extra/webapps/factor-website/" swap ".xml" 3append <chloe> ;
+
+: test-db "todo.db" resource-path sqlite-db ;
+
+: <factor-boilerplate> ( responder -- responder' )
+    <login>
+        users-in-db >>users
+        allow-registration
+        allow-password-recovery
+        allow-edit-profile
+    <boilerplate>
+        "page" factor-template >>template
+    <url-sessions>
+        sessions-in-db >>sessions
+    test-db <db-persistence> ;
+
+: init-factor-website ( -- )
+    "factorcode.org" 25 <inet> smtp-server set-global
+    "todo@factorcode.org" lost-password-from set-global
+
+    test-db [
+        init-sessions-table
+        init-users-table
+    ] with-db ;
diff --git a/extra/webapps/factor-website/page.xml b/extra/webapps/factor-website/page.xml
new file mode 100644 (file)
index 0000000..d929042
--- /dev/null
@@ -0,0 +1,61 @@
+<?xml version='1.0' ?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+       <t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+               <head>
+                       <t:write-title />
+
+                       <t:style>
+                               body, button {
+                                       font:9pt "Lucida Grande", "Lucida Sans Unicode", verdana, geneva, sans-serif;
+                                       color:#444;
+                               }
+
+                               .link-button {
+                                       padding: 0px;
+                                       background: none;
+                                       border: none;
+                               }
+
+                               a, .link {
+                                       color: #222;
+                                       border-bottom:1px dotted #666;
+                                       text-decoration:none;
+                               }
+
+                               a:hover, .link:hover {
+                                       border-bottom:1px solid #66a;
+                               }
+
+                               .error { color: #a00; }
+
+                               .field-label {
+                                       text-align: right;
+                               }
+
+                               .inline {
+                                       display: inline;
+                               }
+                               
+                               .navbar {
+                                       background-color: #eee;
+                                       padding: 5px;
+                                       border: 1px solid #ccc;
+                               }
+                       </t:style>
+
+                       <t:write-style />
+               </head>
+
+               <body>
+                       <t:call-next-template />
+               </body>
+
+       </t:chloe>
+
+</html>
diff --git a/extra/webapps/planet/admin.xml b/extra/webapps/planet/admin.xml
new file mode 100644 (file)
index 0000000..1a18cad
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <t:title>Planet Factor Administration</t:title>
+
+       <t:summary component="blogroll" />
+
+       <p>
+               <t:a href="edit-blog">Add Blog</t:a> | <t:a href="update">Update</t:a>
+       </p>
+
+</t:chloe>
diff --git a/extra/webapps/planet/authors.txt b/extra/webapps/planet/authors.txt
new file mode 100755 (executable)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/extra/webapps/planet/blog-admin-link.xml b/extra/webapps/planet/blog-admin-link.xml
new file mode 100644 (file)
index 0000000..712db4b
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <t:a href="view-blog" query="id"><t:view component="name" /></t:a>
+
+</t:chloe>
diff --git a/extra/webapps/planet/edit-blog.xml b/extra/webapps/planet/edit-blog.xml
new file mode 100644 (file)
index 0000000..890b23d
--- /dev/null
@@ -0,0 +1,40 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <t:title>Edit Blog</t:title>
+
+       <t:form action="edit-blog">
+
+               <t:edit component="id" />
+
+               <table>
+
+                       <tr>
+                               <th class="field-label">Blog name:</th>
+                               <td><t:edit component="name" /></td>
+                       </tr>
+
+                       <tr>
+                               <th class="field-label">Home page:</th>
+                               <td><t:edit component="www-url" /></td>
+                       </tr>
+
+                       <tr>
+                               <th class="field-label">Atom feed:</th>
+                               <td><t:edit component="atom-url" /></td>
+                       </tr>
+
+               </table>
+
+               <input type="SUBMIT" value="Done" />
+
+       </t:form>
+
+       <t:a href="view" query="id">View</t:a>
+       |
+       <t:form action="delete-blog" class="inline">
+               <t:edit component="id" />
+               <button type="submit" class="link-button link">Delete</button>
+       </t:form>
+</t:chloe>
diff --git a/extra/webapps/planet/entry-summary.xml b/extra/webapps/planet/entry-summary.xml
new file mode 100644 (file)
index 0000000..a877032
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <p class="news">
+               <strong><t:view component="title" /></strong> <br/>
+               <t:a value="link" class="more">Read More...</t:a>
+       </p>
+
+</t:chloe>
diff --git a/extra/webapps/planet/entry.xml b/extra/webapps/planet/entry.xml
new file mode 100644 (file)
index 0000000..bc89af3
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <h2 class="posting-title">
+               <t:a value="link"><t:view component="title" /></t:a>
+       </h2>
+
+       <p class="posting-body">
+               <t:view component="description" />
+       </p>
+
+       <p class="posting-date">
+               <t:a value="link"><t:view component="pub-date" /></t:a>
+       </p>
+
+</t:chloe>
diff --git a/extra/webapps/planet/planet.css b/extra/webapps/planet/planet.css
new file mode 100644 (file)
index 0000000..ea7b7d8
--- /dev/null
@@ -0,0 +1,30 @@
+h1.planet-title {
+       font-size:300%;
+}
+
+.posting-title {
+       background-color:#f5f5f5;
+}
+
+pre, code {
+       color:#000000;
+       font-size:120%;
+}
+
+.infobox {
+       border-left: 1px solid #C1DAD7;
+}
+
+.posting-date {
+       text-align: right;
+       font-size:90%;
+}
+
+a.more {
+       display:block;
+       padding:0 0 5px 0;
+       color:#333;
+       text-decoration:none;
+       text-align:right;
+       border:none;
+}
diff --git a/extra/webapps/planet/planet.factor b/extra/webapps/planet/planet.factor
new file mode 100755 (executable)
index 0000000..464e2bb
--- /dev/null
@@ -0,0 +1,188 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel accessors sequences sorting locals math
+calendar alarms logging concurrency.combinators namespaces
+db.types db.tuples db
+rss xml.writer
+http.server
+http.server.crud
+http.server.forms
+http.server.actions
+http.server.boilerplate
+http.server.templating.chloe
+http.server.components
+http.server.auth.login
+webapps.factor-website ;
+IN: webapps.planet
+
+TUPLE: planet-factor < dispatcher postings ;
+
+: planet-template ( name -- template )
+    "resource:extra/webapps/planet/" swap ".xml" 3append <chloe> ;
+
+TUPLE: blog id name www-url atom-url ;
+
+M: blog link-title name>> ;
+
+M: blog link-href www-url>> ;
+
+blog "BLOGS"
+{
+    { "id" "ID" INTEGER +native-id+ }
+    { "name" "NAME" { VARCHAR 256 } +not-null+ }
+    { "www-url" "WWWURL" { VARCHAR 256 } +not-null+ }
+    { "atom-url" "ATOMURL" { VARCHAR 256 } +not-null+ }
+} define-persistent
+
+: init-blog-table blog ensure-table ;
+
+: <blog> ( id -- todo )
+    blog new
+        swap >>id ;
+
+: blogroll ( -- seq )
+    f <blog> select-tuples [ [ name>> ] compare ] sort ;
+
+: <entry-form> ( -- form )
+    "entry" <form>
+        "entry" planet-template >>view-template
+        "entry-summary" planet-template >>summary-template
+        "title" <string> add-field
+        "description" <html-text> add-field
+        "pub-date" <date> add-field ;
+
+: <blog-form> ( -- form )
+    "blog" <form>
+        "edit-blog" planet-template >>edit-template
+        "view-blog" planet-template >>view-template
+        "blog-admin-link" planet-template >>summary-template
+        "id" <integer>
+            hidden >>renderer
+            add-field
+        "name" <string>
+            t >>required
+            add-field
+        "www-url" <url>
+            t >>required
+            add-field
+        "atom-url" <url>
+            t >>required
+            add-field ;
+
+: <planet-factor-form> ( -- form )
+    "planet-factor" <form>
+        "postings" planet-template >>view-template
+        "postings-summary" planet-template >>summary-template
+        "postings" <entry-form> +plain+ <list> add-field
+        "blogroll" "blog" <link> +unordered+ <list> add-field ;
+
+: <admin-form> ( -- form )
+    "admin" <form>
+        "admin" planet-template >>view-template
+        "blogroll" <blog-form> +unordered+ <list> add-field ;
+
+:: <edit-blogroll-action> ( planet -- action )
+    [let | form [ <admin-form> ] |
+        <action>
+            [
+                blank-values
+
+                blogroll "blogroll" set-value
+
+                form view-form
+            ] >>display
+    ] ;
+
+:: <planet-action> ( planet -- action )
+    [let | form [ <planet-factor-form> ] |
+        <action>
+            [
+                blank-values
+
+                planet postings>> "postings" set-value
+                blogroll "blogroll" set-value
+
+                form view-form
+            ] >>display
+    ] ;
+
+: safe-head ( seq n -- seq' )
+    over length min head ;
+
+:: planet-feed ( planet -- feed )
+    feed new
+        "[ planet-factor ]" >>title
+        "http://planet.factorcode.org" >>link
+        planet postings>> 16 safe-head >>entries ;
+
+:: <feed-action> ( planet -- action )
+    <action>
+        [
+            "text/xml" <content>
+            [ planet planet-feed feed>xml write-xml ] >>body
+        ] >>display ;
+
+: <posting> ( name entry -- entry' )
+    clone [ ": " swap 3append ] change-title ;
+
+: fetch-feed ( url -- feed )
+    download-feed entries>> ;
+
+\ fetch-feed DEBUG add-error-logging
+
+: fetch-blogroll ( blogroll -- entries )
+    dup
+    [ atom-url>> fetch-feed ] parallel-map
+    [ >r name>> r> [ <posting> ] with map ] 2map concat ;
+
+: sort-entries ( entries -- entries' )
+    [ [ pub-date>> ] compare ] sort <reversed> ;
+
+: update-cached-postings ( planet -- )
+    "webapps.planet" [
+        blogroll fetch-blogroll sort-entries 8 safe-head
+        >>postings drop
+    ] with-logging ;
+
+:: <update-action> ( planet -- action )
+    <action>
+        [
+            planet update-cached-postings
+            "" f <temporary-redirect>
+        ] >>display ;
+
+:: <planet-factor-admin> ( planet-factor -- responder )
+    [let | blog-form [ <blog-form> ]
+           blog-ctor [ [ <blog> ] ] |
+        <dispatcher>
+            planet-factor <edit-blogroll-action> >>default
+
+            ! Administrative CRUD
+                      blog-ctor ""          <delete-action> "delete-blog" add-responder
+            blog-form blog-ctor             <view-action>   "view-blog"   add-responder
+            blog-form blog-ctor "view-blog" <edit-action>   "edit-blog"   add-responder
+    ] ;
+
+: <planet-factor> ( -- responder )
+    planet-factor new-dispatcher
+        dup <planet-action> >>default
+        dup <feed-action> "feed.xml" add-responder
+        dup <update-action> "update" add-responder
+        dup <planet-factor-admin> <protected> "admin" add-responder
+    <boilerplate>
+        "planet" planet-template >>template ;
+: <planet-app> ( -- responder )
+    <planet-factor> <factor-boilerplate> ;
+
+: start-update-task ( planet -- )
+    [ update-cached-postings ] curry 10 minutes every drop ;
+
+: init-planet ( -- )
+    test-db [
+        init-blog-table
+    ] with-db
+
+    <dispatcher>
+        <planet-app> "planet" add-responder
+    main-responder set-global ;
diff --git a/extra/webapps/planet/planet.xml b/extra/webapps/planet/planet.xml
new file mode 100644 (file)
index 0000000..772f819
--- /dev/null
@@ -0,0 +1,31 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+<t:comment>
+       <t:atom title="Planet Factor - Atom" href="feed.xml" />
+</t:comment>
+       <t:style include="resource:extra/webapps/planet/planet.css" />
+
+       <div class="navbar">
+                 <t:a href="list">Front Page</t:a>
+               | <t:a href="feed.xml">Atom Feed</t:a>
+
+               | <t:a href="admin">Admin</t:a>
+
+               <t:comment>
+               <t:if code="http.server.auth.login:allow-edit-profile?">
+                       | <t:a href="edit-profile">Edit Profile</t:a>
+               </t:if>
+
+               <t:form action="logout" class="inline">
+                       | <button type="submit" class="link-button link">Logout</button>
+               </t:form>
+               </t:comment>
+       </div>
+
+       <h1><t:write-title /></h1>
+
+        <t:call-next-template />
+
+</t:chloe>
diff --git a/extra/webapps/planet/postings-summary.xml b/extra/webapps/planet/postings-summary.xml
new file mode 100644 (file)
index 0000000..950191e
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <t:summary component="postings" />
+
+</t:chloe>
diff --git a/extra/webapps/planet/postings.xml b/extra/webapps/planet/postings.xml
new file mode 100644 (file)
index 0000000..f59a4f6
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <t:title>Planet Factor</t:title>
+
+       <table width="100%" cellpadding="10">
+                <tr>
+                        <td> <t:view component="postings" /> </td>
+  
+                        <td valign="top" width="25%" class="infobox">
+                                <h2>Blogroll</h2>
+  
+                                <t:summary component="blogroll" />
+                        </td>
+                </tr>
+        </table>
+
+</t:chloe>
diff --git a/extra/webapps/planet/view-blog.xml b/extra/webapps/planet/view-blog.xml
new file mode 100644 (file)
index 0000000..fbc03af
--- /dev/null
@@ -0,0 +1,41 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <t:title>View Blog</t:title>
+
+       <table>
+
+               <tr>
+                       <th class="field-label">Blog name:</th>
+                       <td><t:view component="name" /></td>
+               </tr>
+
+               <tr>
+                       <th class="field-label">Home page:</th>
+                       <td>
+                               <t:a value="www-url">
+                                       <t:view component="www-url" />
+                               </t:a>
+                       </td>
+               </tr>
+
+               <tr>
+                       <th class="field-label">Atom feed:</th>
+                       <td>
+                               <t:a value="atom-url">
+                                       <t:view component="atom-url" />
+                               </t:a>
+                       </td>
+               </tr>
+
+       </table>
+
+       <t:a href="edit-blog" query="id">Edit</t:a>
+       |
+       <t:form action="delete-blog" class="inline">
+               <t:edit component="id" />
+               <button type="submit" class="link-button link">Delete</button>
+       </t:form>
+
+</t:chloe>
diff --git a/extra/webapps/todo/edit-todo.xml b/extra/webapps/todo/edit-todo.xml
new file mode 100644 (file)
index 0000000..71d6900
--- /dev/null
@@ -0,0 +1,26 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <t:title>Edit Item</t:title>
+
+       <t:form action="edit">
+               <t:edit component="id" />
+
+               <table>
+                       <tr><th class="field-label">Summary:    </th><td><t:edit component="summary"     /></td></tr>
+                       <tr><th class="field-label">Priority:   </th><td><t:edit component="priority"    /></td></tr>
+                       <tr><th class="field-label big-field-label">Description:</th><td><t:edit component="description" /></td></tr>
+               </table>
+
+               <input type="SUBMIT" value="Done" />
+       </t:form>
+
+       <t:a href="view" query="id">View</t:a>
+       |
+       <t:form action="delete" class="inline">
+               <t:edit component="id" />
+               <button type="submit" class="link-button link">Delete</button>
+       </t:form>
+
+</t:chloe>
diff --git a/extra/webapps/todo/todo-list.xml b/extra/webapps/todo/todo-list.xml
new file mode 100644 (file)
index 0000000..1887fcc
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <t:title>My Todo List</t:title>
+
+       <table class="todo-list">
+               <tr><th>Summary</th><th>Priority</th><th>View</th><th>Edit</th></tr>
+               <t:summary component="list" />
+       </table>
+
+</t:chloe>
diff --git a/extra/webapps/todo/todo-summary.xml b/extra/webapps/todo/todo-summary.xml
new file mode 100644 (file)
index 0000000..9e03b7f
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <tr>
+               <td>
+                       <t:view component="summary" />
+               </td>
+               <td>
+                       <t:view component="priority" />
+               </td>
+               <td>
+                       <t:a href="view" query="id">View</t:a>
+               </td>
+               <td>
+                       <t:a href="edit" query="id">Edit</t:a>
+               </td>
+       </tr>
+
+</t:chloe>
diff --git a/extra/webapps/todo/todo.css b/extra/webapps/todo/todo.css
new file mode 100644 (file)
index 0000000..2520a56
--- /dev/null
@@ -0,0 +1,25 @@
+.big-field-label {
+       vertical-align: top;
+}
+
+.description {
+       border: 1px dashed #ccc;
+       background-color: #f5f5f5;
+       padding: 5px;
+       font-size: 150%;
+       color: #000000;
+}
+
+pre {
+       font-size: 75%;
+}
+
+.todo-list {
+       border-style: none;
+}
+
+.todo-list td, .todo-list th {
+       border-width: 1px;
+       padding: 2px;
+       border-style: solid;
+}
diff --git a/extra/webapps/todo/todo.factor b/extra/webapps/todo/todo.factor
new file mode 100755 (executable)
index 0000000..97af356
--- /dev/null
@@ -0,0 +1,86 @@
+! Copyright (c) 2008 Slava Pestov
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors kernel locals sequences namespaces
+db db.types db.tuples
+http.server.components http.server.components.farkup
+http.server.forms http.server.templating.chloe
+http.server.boilerplate http.server.crud http.server.auth
+http.server.actions http.server.db
+http.server.auth.login
+http.server
+webapps.factor-website ;
+IN: webapps.todo
+
+TUPLE: todo uid id priority summary description ;
+
+todo "TODO"
+{
+    { "uid" "UID" { VARCHAR 256 } +not-null+ }
+    { "id" "ID" +native-id+ }
+    { "priority" "PRIORITY" INTEGER +not-null+ }
+    { "summary" "SUMMARY" { VARCHAR 256 } +not-null+ }
+    { "description" "DESCRIPTION" { VARCHAR 256 } }
+} define-persistent
+
+: init-todo-table todo ensure-table ;
+
+: <todo> ( id -- todo )
+    todo new
+        swap >>id
+        uid >>uid ;
+
+: todo-template ( name -- template )
+    "resource:extra/webapps/todo/" swap ".xml" 3append <chloe> ;
+
+: <todo-form> ( -- form )
+    "todo" <form>
+        "view-todo" todo-template >>view-template
+        "edit-todo" todo-template >>edit-template
+        "todo-summary" todo-template >>summary-template
+        "id" <integer>
+            hidden >>renderer
+            add-field
+        "summary" <string>
+            t >>required
+            add-field
+        "priority" <integer>
+            t >>required
+            0 >>default
+            0 >>min-value
+            10 >>max-value
+            add-field
+        "description" <farkup>
+            add-field ;
+
+: <todo-list-form> ( -- form )
+    "todo-list" <form>
+        "todo-list" todo-template >>view-template
+        "list" <todo-form> +plain+ <list>
+        add-field ;
+
+TUPLE: todo-responder < dispatcher ;
+
+:: <todo-responder> ( -- responder )
+    [let | todo-form [ <todo-form> ]
+           list-form [ <todo-list-form> ]
+           ctor [ [ <todo> ] ] |
+        todo-responder new-dispatcher
+            list-form ctor        <list-action>   "list"   add-main-responder
+            todo-form ctor        <view-action>   "view"   add-responder
+            todo-form ctor "view" <edit-action>   "edit"   add-responder
+                      ctor "list" <delete-action> "delete" add-responder
+        <boilerplate>
+            "todo" todo-template >>template
+    ] ;
+
+: <todo-app> ( -- responder )
+    <todo-responder> <protected> <factor-boilerplate> ;
+
+: init-todo ( -- )
+    test-db [
+        init-todo-table
+    ] with-db
+
+    <dispatcher>
+        <todo-app> "todo" add-responder
+    main-responder set-global ;
diff --git a/extra/webapps/todo/todo.xml b/extra/webapps/todo/todo.xml
new file mode 100644 (file)
index 0000000..81a5d3a
--- /dev/null
@@ -0,0 +1,26 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <t:style include="resource:extra/webapps/todo/todo.css" />
+
+       <t:style include="resource:extra/xmode/code2html/stylesheet.css" />
+
+       <div class="navbar">
+                 <t:a href="list">List Items</t:a>
+               | <t:a href="edit">Add Item</t:a>
+
+               <t:if code="http.server.auth.login:allow-edit-profile?">
+                       | <t:a href="edit-profile">Edit Profile</t:a>
+               </t:if>
+
+               <t:form action="logout" class="inline">
+                       | <button type="submit" class="link-button link">Logout</button>
+               </t:form>
+       </div>
+
+       <h1><t:write-title /></h1>
+
+       <t:call-next-template />
+
+</t:chloe>
diff --git a/extra/webapps/todo/view-todo.xml b/extra/webapps/todo/view-todo.xml
new file mode 100644 (file)
index 0000000..fea77c1
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version='1.0' ?>
+
+<t:chloe xmlns:t="http://factorcode.org/chloe/1.0">
+
+       <t:title>View Item</t:title>
+
+       <table>
+               <tr><th class="field-label">Summary:    </th><td><t:view component="summary"     /></td></tr>
+               <tr><th class="field-label">Priority:   </th><td><t:view component="priority"    /></td></tr>
+       </table>
+
+       <div class="description">
+               <t:view component="description" />
+       </div>
+
+       <t:a href="edit" query="id">Edit</t:a>
+       |
+       <t:form action="delete" class="inline">
+               <t:edit component="id" />
+               <button class="link-button link">Delete</button>
+       </t:form>
+
+</t:chloe>
index 44ea853af0c15f0e27229fbc3e2419fca11a0748..6e06830130151574a21abd830e25e97e68d0f553 100644 (file)
@@ -1,5 +1,5 @@
-USING: alien alien.syntax alien.c-types math kernel sequences\r
-windows windows.types combinators.lib ;\r
+USING: alien alien.syntax alien.c-types alien.strings math\r
+kernel sequences windows windows.types combinators.lib ;\r
 IN: windows.ole32\r
 \r
 LIBRARY: ole32\r
@@ -12,8 +12,8 @@ C-STRUCT: GUID
 \r
 TYPEDEF: void* REFGUID\r
 TYPEDEF: void* LPUNKNOWN\r
-TYPEDEF: ushort* LPOLESTR\r
-TYPEDEF: ushort* LPCOLESTR\r
+TYPEDEF: wchar_t* LPOLESTR\r
+TYPEDEF: wchar_t* LPCOLESTR\r
 \r
 TYPEDEF: REFGUID REFIID\r
 TYPEDEF: REFGUID REFCLSID\r
@@ -52,8 +52,8 @@ FUNCTION: HRESULT CLSIDFromString ( LPOLESTR lpsz, REFGUID out_rguid ) ;
     "{01234567-89ab-cdef-0123-456789abcdef}" length ; inline\r
 \r
 : string>guid ( string -- guid )\r
-    string>u16-alien "GUID" <c-object> [ CLSIDFromString ole32-error ] keep ;\r
+    utf16n string>alien "GUID" <c-object> [ CLSIDFromString ole32-error ] keep ;\r
 : guid>string ( guid -- string )\r
     GUID-STRING-LENGTH 1+ [ "ushort" <c-array> ] keep\r
-    [ StringFromGUID2 drop ] { 2 } multikeep alien>u16-string ;\r
+    [ StringFromGUID2 drop ] { 2 } multikeep utf16n alien>string ;\r
 \r
index d64fb68cb31fddee5ea2194c3ddde48ab383a9e0..a9035eeeafb0a895c5a65e3af6e76d896b6f1a4a 100644 (file)
@@ -1,6 +1,6 @@
-USING: alien alien.c-types alien.syntax combinators
+USING: alien alien.c-types alien.strings alien.syntax combinators
 kernel windows windows.user32 windows.ole32
-windows.com windows.com.syntax ;
+windows.com windows.com.syntax io.files ;
 IN: windows.shell32
 
 : CSIDL_DESKTOP HEX: 00 ; inline
@@ -83,7 +83,7 @@ FUNCTION: HINSTANCE ShellExecuteW ( HWND hwnd, LPCTSTR lpOperation, LPCTSTR lpFi
 : ShellExecute ShellExecuteW ; inline
 
 : open-in-explorer ( dir -- )
-    f "open" rot f f SW_SHOWNORMAL ShellExecute drop ;
+    f "open" rot (normalize-path) f f SW_SHOWNORMAL ShellExecute drop ;
 
 : shell32-error ( n -- )
     ole32-error ; inline
@@ -91,7 +91,7 @@ FUNCTION: HINSTANCE ShellExecuteW ( HWND hwnd, LPCTSTR lpOperation, LPCTSTR lpFi
 : shell32-directory ( n -- str )
     f swap f SHGFP_TYPE_DEFAULT
     MAX_UNICODE_PATH "ushort" <c-array>
-    [ SHGetFolderPath shell32-error ] keep alien>u16-string ;
+    [ SHGetFolderPath shell32-error ] keep utf16n alien>string ;
 
 : desktop ( -- str )
     CSIDL_DESKTOPDIRECTORY shell32-directory ;
index 61b409e8e14af32fc3cf671f99e82b4282ed5e3c..8b4b2d98d29ef300d048a1243001f35743d0473d 100644 (file)
@@ -66,9 +66,8 @@ TYPEDEF: LARGE_INTEGER* PLARGE_INTEGER
 
 TYPEDEF: WCHAR       TCHAR
 TYPEDEF: TCHAR       TBYTE
-! TYPEDEF: uchar*  LPCSTR
-TYPEDEF: ushort*  LPCSTR
-TYPEDEF: ushort*  LPWSTR
+TYPEDEF: wchar_t*  LPCSTR
+TYPEDEF: wchar_t*  LPWSTR
 
 
 
@@ -126,10 +125,10 @@ TYPEDEF: WCHAR*              LPCWSTR
 ! TYPEDEF: WCHAR*              LPWSTR
 
 TYPEDEF: WCHAR*               LPSTR
-TYPEDEF: ushort* LPCTSTR
-TYPEDEF: ushort* LPWTSTR
+TYPEDEF: wchar_t* LPCTSTR
+TYPEDEF: wchar_t* LPWTSTR
 
-TYPEDEF: ushort*       LPTSTR
+TYPEDEF: wchar_t*       LPTSTR
 TYPEDEF: LPCSTR      PCTSTR
 TYPEDEF: LPSTR       PTSTR
 
index 600c0a4039c4a3cb10109f223a78538ea9e97ad0..3e7520d4063a33a23b3399813ad071328d32dd64 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2005, 2006 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien alien.syntax alien.c-types arrays combinators
-kernel math namespaces parser prettyprint sequences
+USING: alien alien.syntax alien.c-types alien.strings arrays
+combinators kernel math namespaces parser prettyprint sequences
 windows.errors windows.types windows.kernel32 words ;
 IN: windows
 
@@ -14,7 +14,7 @@ FUNCTION: void* error_message ( DWORD id ) ;
 
 : (win32-error-string) ( n -- string )
     error_message
-    dup alien>u16-string
+    dup utf16n alien>string
     swap LocalFree drop ;
 
 : win32-error-string ( -- str )
@@ -30,10 +30,10 @@ FUNCTION: void* error_message ( DWORD id ) ;
 : win32-error ( -- )
     GetLastError (win32-error) ;
 
-: win32-error=0/f { 0 f } member? [ win32-error ] when ;
-: win32-error>0 0 > [ win32-error ] when ;
-: win32-error<0 0 < [ win32-error ] when ;
-: win32-error<>0 zero? [ win32-error ] unless ;
+: 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 = [
index cc19cdc2a3a401c083cd6f8e07b7be0d6c080ec9..39d11b562b2df28d6e0cd0f8162952d0e84b9f47 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2006 Mackenzie Straight, Doug Coleman.
 
-USING: alien alien.c-types alien.syntax arrays byte-arrays
-kernel math sequences windows.types windows.kernel32
+USING: alien alien.c-types alien.strings alien.syntax arrays
+byte-arrays kernel math sequences windows.types windows.kernel32
 windows.errors structs windows math.bitfields ;
 IN: windows.winsock
 
@@ -397,7 +397,7 @@ FUNCTION: void GetAcceptExSockaddrs ( void* a, int b, int c, int d, void* e, voi
 : (winsock-error-string) ( n -- str )
     ! #! WSAStartup returns the error code 'n' directly
     dup winsock-expected-error?
-    [ drop f ] [ error_message alien>u16-string ] if ;
+    [ drop f ] [ error_message utf16n alien>string ] if ;
 
 : winsock-error-string ( -- string/f )
     WSAGetLastError (winsock-error-string) ;
index 63d90f58dbca6e36f73112bd52776c8fcb49a14c..aeb6af3ee623cf8ed3ca0eb6e6c12a4ee70828cd 100644 (file)
@@ -1,7 +1,8 @@
 
-USING: kernel io alien alien.c-types namespaces threads
+USING: kernel io alien alien.c-types alien.strings namespaces threads
        arrays sequences assocs math vars combinators.lib
-       x11.constants x11.events x11.xlib mortar slot-accessors geom.rect ;
+       x11.constants x11.events x11.xlib mortar slot-accessors geom.rect
+       io.encodings.ascii ;
 
 IN: x
 
@@ -29,7 +30,7 @@ define-independent-class
 
 <display> "create" !( name <display> -- display ) [
   new-empty swap >>name
-  dup $name dup [ string>char-alien ] [ ] if XOpenDisplay
+  dup $name dup [ ascii string>alien ] [ ] if XOpenDisplay
   dup [ >>ptr ] [ "XOpenDisplay error" throw ] if
   dup $ptr XDefaultScreen >>default-screen
   dup $ptr XDefaultRootWindow dupd <window> new >>default-root
@@ -433,7 +434,7 @@ add-method
 
 <window> "fetch-name" !( window -- name-or-f )
   [ <- raw f <void*> dup >r   XFetchName drop   r>
-    dup *void* alien-address 0 = [ drop f ] [ *char* ] if ]
+    dup *void* [ drop f ] [ *void* ascii alien>string ] if ]
 add-method
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
index a63a3903a11b41afe24cf084174a1df666ced5b6..9e1e0ef92021c149d717b7fab8793e0f74812ead 100755 (executable)
@@ -1,8 +1,8 @@
 ! Copyright (C) 2006, 2007 Slava Pestov
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien alien.c-types alien.syntax arrays kernel math
-namespaces sequences io.encodings.string io.encodings.utf8 x11.xlib
-x11.constants ;
+USING: alien alien.c-types alien.strings alien.syntax arrays
+kernel math namespaces sequences io.encodings.string
+io.encodings.utf8 io.encodings.ascii x11.xlib x11.constants ;
 IN: x11.clipboard
 
 ! This code was based on by McCLIM's Backends/CLX/port.lisp
@@ -25,7 +25,7 @@ TUPLE: x-clipboard atom contents ;
     CurrentTime XConvertSelection drop ;
 
 : snarf-property ( prop-return -- string )
-    dup *void* [ *char* ] [ drop f ] if ;
+    dup *void* [ *void* ascii alien>string ] [ drop f ] if ;
 
 : window-property ( win prop delete? -- string )
     >r dpy get -rot 0 -1 r> AnyPropertyType
index 752c6c442eb98a754a5e540d31b85d674d28ea9c..154bf4d6ffe196dfb8d67017f1db2cb4b37a8d62 100755 (executable)
@@ -11,8 +11,9 @@
 ! modify, just find the function or data structure in the manual
 ! and note the section.
 
-USING: kernel arrays alien alien.c-types alien.syntax
-math math.bitfields words sequences namespaces continuations ;
+USING: kernel arrays alien alien.c-types alien.strings
+alien.syntax math math.bitfields words sequences namespaces
+continuations io.encodings.ascii ;
 IN: x11.xlib
 
 LIBRARY: xlib
@@ -1372,7 +1373,7 @@ SYMBOL: root
 
 : initialize-x ( display-string -- )
     init-locale
-    dup [ string>char-alien ] when
+    dup [ ascii string>alien ] when
     XOpenDisplay check-display dpy set-global
     dpy get XDefaultScreen scr set-global
     dpy get scr get XRootWindow root set-global ;
index 27880da07f533b7c6d8c512d78f4ff1586735c65..44c92006a068de2b4681ac3ae34642662bbcc6cb 100644 (file)
@@ -1,8 +1,8 @@
 ! Copyright (C) 2005, 2006 Daniel Ehrenberg\r
 ! See http://factorcode.org/license.txt for BSD license.\r
 USING: hashtables kernel math namespaces sequences strings\r
-io io.streams.string xml.data assocs wrap xml.entities\r
-unicode.categories ;\r
+assocs combinators io io.streams.string\r
+xml.data wrap xml.entities unicode.categories ;\r
 IN: xml.writer\r
 \r
 SYMBOL: xml-pprint?\r
@@ -61,6 +61,9 @@ M: string write-item
     ?indent CHAR: < write1\r
     dup print-name tag-attrs print-attrs ;\r
 \r
+: write-start-tag ( tag -- )\r
+    write-tag ">" write ;\r
+\r
 M: contained-tag write-item\r
     write-tag "/>" write ;\r
 \r
@@ -72,11 +75,14 @@ M: contained-tag write-item
     ?indent "</" write print-name CHAR: > write1 ;\r
 \r
 M: open-tag write-item\r
-    xml-pprint? [ [\r
-        over sensitive? not and xml-pprint? set\r
-        dup write-tag CHAR: > write1\r
-        dup write-children write-end-tag\r
-    ] keep ] change ;\r
+    xml-pprint? get >r\r
+    {\r
+        [ sensitive? not xml-pprint? get and xml-pprint? set ]\r
+        [ write-start-tag ]\r
+        [ write-children ]\r
+        [ write-end-tag ]\r
+    } cleave\r
+    r> xml-pprint? set ;\r
 \r
 M: comment write-item\r
     "<!--" write comment-text write "-->" write ;\r
@@ -97,10 +103,12 @@ M: instruction write-item
     [ write-item ] each ;\r
 \r
 : write-xml ( xml -- )\r
-    dup xml-prolog write-prolog\r
-    dup xml-before write-chunk\r
-    dup write-item\r
-    xml-after write-chunk ;\r
+    {\r
+        [ xml-prolog write-prolog ]\r
+        [ xml-before write-chunk ]\r
+        [ write-item ]\r
+        [ xml-after write-chunk ]\r
+    } cleave ;\r
 \r
 : print-xml ( xml -- )\r
     write-xml nl ;\r
index 62f0f6ede32104942a572f6a3144f64402d07628..22d3217ee69c89b3e94514ee2a88a8bdb9a65682 100755 (executable)
@@ -36,9 +36,13 @@ TAGS>
     f \ modes set-global ;
 
 MEMO: (load-mode) ( name -- rule-sets )
-    modes at mode-file
-    "extra/xmode/modes/" prepend
-    resource-path utf8 <file-reader> parse-mode ;
+    modes at [
+        mode-file
+        "extra/xmode/modes/" prepend
+        resource-path utf8 <file-reader> parse-mode
+    ] [
+        "text" (load-mode)
+    ] if* ;
 
 SYMBOL: rule-sets
 
index 86552d64019f9b6a93baf6f04a495818f1931e5e..5aa47c8c6cb5cd2d1516f7cc51876d071c1395a1 100755 (executable)
@@ -122,7 +122,7 @@ void clear_cards(CELL from, CELL to)
 void set_data_heap(F_DATA_HEAP *data_heap_)
 {
        data_heap = data_heap_;
-       nursery = &data_heap->generations[NURSERY];
+       nursery = data_heap->generations[NURSERY];
        init_cards_offset();
        clear_cards(NURSERY,TENURED);
 }
@@ -231,7 +231,7 @@ DEFINE_PRIMITIVE(data_room)
 
        for(gen = 0; gen < data_heap->gen_count; gen++)
        {
-               F_ZONE *z = &data_heap->generations[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));
        }
@@ -583,7 +583,7 @@ CELL collect_next(CELL scan)
 
 INLINE void reset_generation(CELL i)
 {
-       F_ZONE *z = &data_heap->generations[i];
+       F_ZONE *z = (i == NURSERY ? &nursery : &data_heap->generations[i]);
        z->here = z->start;
        if(secure_gc)
                memset((void*)z->start,69,z->size);
@@ -608,7 +608,7 @@ void begin_gc(CELL requested_bytes)
 
                old_data_heap = data_heap;
                set_data_heap(grow_data_heap(old_data_heap,requested_bytes));
-               newspace = &data_heap->generations[collecting_gen];
+               newspace = &data_heap->generations[TENURED];
        }
        else if(collecting_accumulation_gen_p())
        {
@@ -783,6 +783,11 @@ void gc(void)
        garbage_collection(TENURED,false,0);
 }
 
+void minor_gc(void)
+{
+       garbage_collection(NURSERY,false,0);
+}
+
 DEFINE_PRIMITIVE(gc)
 {
        gc();
@@ -794,12 +799,6 @@ DEFINE_PRIMITIVE(gc_time)
        box_unsigned_8(gc_time);
 }
 
-void simple_gc(void)
-{
-       if(nursery->here + ALLOT_BUFFER_ZONE > nursery->end)
-               garbage_collection(NURSERY,false,0);
-}
-
 DEFINE_PRIMITIVE(become)
 {
        F_ARRAY *new_objects = untag_array(dpop());
index 2490ed88057f8c9b342984197cb37638e3e68ee8..be9ed159b791fb00c09deef59deb33136b3fefda 100755 (executable)
@@ -20,6 +20,7 @@ DECLARE_PRIMITIVE(next_object);
 DECLARE_PRIMITIVE(end_scan);
 
 void gc(void);
+DLLEXPORT void minor_gc(void);
 
 /* generational copying GC divides memory into zones */
 typedef struct {
@@ -125,7 +126,7 @@ void collect_cards(void);
 F_ZONE *newspace;
 
 /* new objects are allocated here */
-DLLEXPORT F_ZONE *nursery;
+DLLEXPORT F_ZONE nursery;
 
 INLINE bool in_zone(F_ZONE *z, CELL pointer)
 {
@@ -200,7 +201,7 @@ INLINE bool should_copy(CELL untagged)
        else if(HAVE_AGING_P && collecting_gen == AGING)
                return !in_zone(&data_heap->generations[TENURED],untagged);
        else if(HAVE_NURSERY_P && collecting_gen == NURSERY)
-               return in_zone(&data_heap->generations[NURSERY],untagged);
+               return in_zone(&nursery,untagged);
        else
        {
                critical_error("Bug in should_copy",untagged);
@@ -315,13 +316,15 @@ INLINE void* allot_object(CELL type, CELL a)
 {
        CELL *object;
 
-       if(HAVE_NURSERY_P && nursery->size - ALLOT_BUFFER_ZONE > a)
+       if(HAVE_NURSERY_P && nursery.size - ALLOT_BUFFER_ZONE > a)
        {
                /* If there is insufficient room, collect the nursery */
-               if(nursery->here + ALLOT_BUFFER_ZONE + a > nursery->end)
+               if(nursery.here + ALLOT_BUFFER_ZONE + a > nursery.end)
                        garbage_collection(NURSERY,false,0);
 
-               object = allot_zone(nursery,a);
+               CELL h = nursery.here;
+               nursery.here = h + align8(a);
+               object = (void*)h;
        }
        /* If the object is bigger than the nursery, allocate it in
        tenured space */
@@ -360,8 +363,6 @@ INLINE void* allot_object(CELL type, CELL a)
 
 CELL collect_next(CELL scan);
 
-DLLEXPORT void simple_gc(void);
-
 DECLARE_PRIMITIVE(gc);
 DECLARE_PRIMITIVE(gc_time);
 DECLARE_PRIMITIVE(become);
index 840d252769a27befee8d48596f27e9b0707f62f6..b86ec808bc5ce1560326a2fd29a9637cf781f095 100755 (executable)
@@ -227,7 +227,11 @@ void dump_zone(F_ZONE *z)
 void dump_generations(void)
 {
        int i;
-       for(i = 0; i < data_heap->gen_count; i++)
+
+       printf("Nursery: ");
+       dump_zone(&nursery);
+       
+       for(i = 1; i < data_heap->gen_count; i++)
        {
                printf("Generation %d: ",i);
                dump_zone(&data_heap->generations[i]);
index 6d99d347660d4a882477e42061968441733ee851..57dc8b66a1287a344fc8d3a739097c30baf517c7 100755 (executable)
@@ -96,7 +96,7 @@ void memory_protection_error(CELL addr, F_STACK_FRAME *native_stack)
                general_error(ERROR_RS_UNDERFLOW,F,F,native_stack);
        else if(in_page(addr, rs_bot, rs_size, 0))
                general_error(ERROR_RS_OVERFLOW,F,F,native_stack);
-       else if(in_page(addr, nursery->end, 0, 0))
+       else if(in_page(addr, nursery.end, 0, 0))
                critical_error("allot_object() missed GC check",0);
        else if(in_page(addr, gc_locals_region->start, 0, -1))
                critical_error("gc locals underflow",0);
index 9cec5ccbadcaebd61c3b39b19c7196ac9d8f4547..b2cbf9b6b522814da7873e8d429143d20c15778e 100755 (executable)
@@ -250,3 +250,28 @@ double ffi_test_36(struct test_struct_12 x)
 {
        return x.x;
 }
+
+static int global_var;
+
+void ffi_test_36_point_5(void)
+{
+       printf("int_ffi_test_36_point_5\n");
+       global_var = 0;
+}
+
+int ffi_test_37(int (*f)(int, int, int))
+{
+       printf("ffi_test_37\n");
+       printf("global_var is %d\n",global_var);
+       global_var = f(global_var,global_var * 2,global_var * 3);
+       printf("global_var is %d\n",global_var);
+       fflush(stdout);
+       return global_var;
+}
+
+unsigned long long ffi_test_38(unsigned long long x, unsigned long long y)
+{
+       return x * y;
+}
+
+
index aac5d32f93eb77f4faa728b2e07c5d75f439c038..d455d999b10bae14871c8852103dd436affb2b73 100755 (executable)
@@ -61,3 +61,9 @@ DLLEXPORT double ffi_test_35(struct test_struct_11 x, int y);
 struct test_struct_12 { int a; double x; };
 
 DLLEXPORT double ffi_test_36(struct test_struct_12 x);
+
+DLLEXPORT void int_ffi_test_36_point_5(void);
+
+DLLEXPORT int ffi_test_37(int (*f)(int, int, int));
+
+DLLEXPORT unsigned long long ffi_test_38(unsigned long long x, unsigned long long y);
index 640aeb796d4dde9363700fe0778f8c383af65d44..13213acbbc06c05502cdf801438d3cde5a747fe9 100644 (file)
@@ -8,6 +8,8 @@ Used under BSD license with permission from Paolo Bonzini and Bruno Haible,
 http://sourceforge.net/mailarchive/message.php?msg_name=200503102200.32002.bruno%40clisp.org
 
 Modified for Factor by Slava Pestov */
+#include <ucontext.h>
+
 #define FRAME_RETURN_ADDRESS(frame) *((XT *)(frame_successor(frame) + 1) + 2)
 
 #define MACH_EXC_STATE_TYPE ppc_exception_state_t
index d5e5827a5c164a46521cdef8baec402a90947ee1..7c830c775d0e1df3223e6d5f061ec3b2796593e9 100644 (file)
@@ -8,6 +8,8 @@ Used under BSD license with permission from Paolo Bonzini and Bruno Haible,
 http://sourceforge.net/mailarchive/message.php?msg_name=200503102200.32002.bruno%40clisp.org
 
 Modified for Factor by Slava Pestov */
+#include <ucontext.h>
+
 #define MACH_EXC_STATE_TYPE i386_exception_state_t
 #define MACH_EXC_STATE_FLAVOR i386_EXCEPTION_STATE
 #define MACH_EXC_STATE_COUNT i386_EXCEPTION_STATE_COUNT
index d2bb48c3fef7b4da77ac06dcd726ebf2d2ee6ccd..b11aa80ce8f4a3161aacf0eee47ead540121bd4f 100644 (file)
@@ -8,6 +8,8 @@ Used under BSD license with permission from Paolo Bonzini and Bruno Haible,
 http://sourceforge.net/mailarchive/message.php?msg_name=200503102200.32002.bruno%40clisp.org
 
 Modified for Factor by Slava Pestov and Daniel Ehrenberg */
+#include <ucontext.h>
+
 #define MACH_EXC_STATE_TYPE x86_exception_state64_t
 #define MACH_EXC_STATE_FLAVOR x86_EXCEPTION_STATE64
 #define MACH_EXC_STATE_COUNT x86_EXCEPTION_STATE64_COUNT
index 2906a154a25704214a629601566121f89734eb9f..da04870ecd06564ec55ce7bc0db81034c529da95 100755 (executable)
@@ -139,10 +139,6 @@ void *primitives[] = {
        primitive_set_alien_double,
        primitive_alien_cell,
        primitive_set_alien_cell,
-       primitive_alien_to_char_string,
-       primitive_string_to_char_alien,
-       primitive_alien_to_u16_string,
-       primitive_string_to_u16_alien,
        primitive_throw,
        primitive_alien_address,
        primitive_slot,
index d9fd152c970802c5af2c4aa1b618bdb62e8d5a24..b4e5269f4e36e6d1661269168c141a29afcfec4c 100755 (executable)
@@ -608,10 +608,6 @@ DEFINE_PRIMITIVE(resize_string)
        void box_##type##_string(const type *str) \
        { \
                dpush(str ? tag_object(from_##type##_string(str)) : F); \
-       } \
-       DEFINE_PRIMITIVE(alien_to_##type##_string) \
-       { \
-               drepl(tag_object(from_##type##_string(alien_offset(dpeek())))); \
        }
 
 MEMORY_TO_STRING(char,u8)
@@ -671,14 +667,6 @@ F_BYTE_ARRAY *allot_c_string(CELL capacity, CELL size)
        type *unbox_##type##_string(void) \
        { \
                return to_##type##_string(untag_string(dpop()),true); \
-       } \
-       DEFINE_PRIMITIVE(string_to_##type##_alien) \
-       { \
-               CELL string, t; \
-               string = dpeek(); \
-               t = type_of(string); \
-               if(t != ALIEN_TYPE && t != BYTE_ARRAY_TYPE && t != F_TYPE) \
-                       drepl(tag_object(string_to_##type##_alien(untag_string(string),true))); \
        }
 
 STRING_TO_MEMORY(char);
index 03ac84d5a5c8c8d1e751f4ff82df308f9b69fbfc..3ce1838b8b20b02ea11e40aca5ac31f9c3b20777 100755 (executable)
@@ -160,24 +160,20 @@ DECLARE_PRIMITIVE(resize_string);
 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);
-DECLARE_PRIMITIVE(alien_to_char_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);
-DECLARE_PRIMITIVE(alien_to_u16_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);
-DECLARE_PRIMITIVE(string_to_char_alien);
 
 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);
-DECLARE_PRIMITIVE(string_to_u16_alien);
 
 /* String getters and setters */
 CELL string_nth(F_STRING* string, CELL index);