]> gitweb.factorcode.org Git - factor.git/commitdiff
Merge branch 'cleanup'
authorJohn Benediktsson <mrjbq7@gmail.com>
Sat, 27 Aug 2011 01:49:25 +0000 (18:49 -0700)
committerJohn Benediktsson <mrjbq7@gmail.com>
Sat, 27 Aug 2011 01:49:25 +0000 (18:49 -0700)
119 files changed:
basis/bootstrap/finish-bootstrap.factor
basis/checksums/fnv1/fnv1-docs.factor
basis/classes/struct/authors.txt
basis/classes/struct/prettyprint/prettyprint.factor
basis/classes/struct/struct-docs.factor
basis/classes/struct/struct-tests.factor
basis/classes/struct/struct.factor
basis/cocoa/cocoa-docs.factor
basis/command-line/command-line-docs.factor
basis/command-line/command-line.factor
basis/concurrency/count-downs/count-downs-docs.factor
basis/cpu/ppc/32/linux/tags.txt [new file with mode: 0644]
basis/cpu/ppc/32/tags.txt [new file with mode: 0644]
basis/cpu/ppc/64/linux/tags.txt [new file with mode: 0644]
basis/cpu/ppc/64/tags.txt [new file with mode: 0644]
basis/cpu/ppc/tags.txt [new file with mode: 0644]
basis/db/tuples/tuples-docs.factor
basis/delegate/delegate-docs.factor
basis/delegate/delegate-tests.factor
basis/farkup/farkup-docs.factor
basis/furnace/recaptcha/recaptcha.factor
basis/http/client/client-docs.factor
basis/io/mmap/mmap-docs.factor
basis/io/pipes/pipes-tests.factor
basis/io/sockets/secure/secure-docs.factor
basis/io/sockets/sockets-tests.factor
basis/io/sockets/sockets.factor
basis/io/thread/thread.factor
basis/math/primes/primes-docs.factor
basis/math/vectors/simd/simd-docs.factor
basis/peg/ebnf/ebnf-docs.factor
basis/tools/annotations/annotations.factor
basis/tools/code-coverage/authors.txt [new file with mode: 0644]
basis/tools/code-coverage/code-coverage.factor [new file with mode: 0644]
basis/tools/code-coverage/summary.txt [new file with mode: 0644]
basis/unix/linux/epoll/epoll.factor
basis/urls/urls-docs.factor
basis/xml/syntax/syntax-docs.factor
basis/xml/writer/writer-docs.factor
core/classes/tuple/tuple-docs.factor
core/combinators/combinators-docs.factor
core/continuations/continuations-docs.factor
core/generic/standard/standard-tests.factor
core/hashtables/hashtables-docs.factor
core/kernel/kernel-docs.factor
core/sequences/sequences.factor
core/sets/sets-tests.factor
core/sets/sets.factor
core/source-files/source-files.factor
core/strings/strings-tests.factor
core/syntax/syntax-docs.factor
core/syntax/syntax.factor
extra/anagrams/anagrams.factor [new file with mode: 0644]
extra/anagrams/authors.txt [new file with mode: 0644]
extra/anagrams/platforms.txt [new file with mode: 0644]
extra/benchmark/echo/echo.factor [new file with mode: 0644]
extra/brainfuck/brainfuck.factor
extra/fjsc/resources/bootstrap.js
extra/fuel/remote/remote.factor
extra/gestalt/authors.txt [new file with mode: 0644]
extra/gestalt/gestalt.factor [new file with mode: 0644]
extra/gestalt/platforms.txt [new file with mode: 0644]
extra/google-tech-talk/google-tech-talk.factor
extra/google/charts/authors.txt [new file with mode: 0644]
extra/google/charts/charts.factor [new file with mode: 0644]
extra/google/charts/summary.txt [new file with mode: 0644]
extra/google/translate/authors.txt [new file with mode: 0644]
extra/google/translate/translate.factor [new file with mode: 0644]
extra/hamurabi/authors.txt [new file with mode: 0644]
extra/hamurabi/hamurabi.factor [new file with mode: 0644]
extra/hamurabi/summary.txt [new file with mode: 0644]
extra/images/viewer/viewer-docs.factor
extra/ini-file/authors.txt [new file with mode: 0644]
extra/ini-file/ini-file-docs.factor [new file with mode: 0644]
extra/ini-file/ini-file-tests.factor [new file with mode: 0644]
extra/ini-file/ini-file.factor [new file with mode: 0644]
extra/ini-file/summary.txt [new file with mode: 0644]
extra/io/files/trash/authors.txt [new file with mode: 0644]
extra/io/files/trash/macosx/macosx.factor [new file with mode: 0644]
extra/io/files/trash/macosx/platforms.txt [new file with mode: 0644]
extra/io/files/trash/summary.txt [new file with mode: 0644]
extra/io/files/trash/trash-docs.factor [new file with mode: 0644]
extra/io/files/trash/trash.factor [new file with mode: 0644]
extra/io/files/trash/unix/platforms.txt [new file with mode: 0644]
extra/io/files/trash/unix/unix.factor [new file with mode: 0644]
extra/io/files/trash/windows/platforms.txt [new file with mode: 0644]
extra/io/files/trash/windows/windows.factor [new file with mode: 0644]
extra/lunar-rescue/lunar-rescue-docs.factor
extra/mason/config/config.factor
extra/mason/platform/platform-tests.factor [new file with mode: 0644]
extra/math/approx/approx-docs.factor [new file with mode: 0644]
extra/math/approx/approx-tests.factor [new file with mode: 0644]
extra/math/approx/approx.factor [new file with mode: 0644]
extra/math/approx/authors.txt [new file with mode: 0644]
extra/math/approx/summary.txt [new file with mode: 0644]
extra/memcached/authors.txt [new file with mode: 0644]
extra/memcached/memcached-docs.factor [new file with mode: 0644]
extra/memcached/memcached-tests.factor [new file with mode: 0644]
extra/memcached/memcached.factor [new file with mode: 0644]
extra/memcached/summary.txt [new file with mode: 0644]
extra/ntp/authors.txt [new file with mode: 0644]
extra/ntp/ntp-docs.factor [new file with mode: 0644]
extra/ntp/ntp.factor [new file with mode: 0644]
extra/ntp/summary.txt [new file with mode: 0644]
extra/otug-talk/otug-talk.factor
extra/readline/readline-docs.factor
extra/tnetstrings/authors.txt [new file with mode: 0644]
extra/tnetstrings/summary.txt [new file with mode: 0644]
extra/tnetstrings/tnetstrings-tests.factor [new file with mode: 0644]
extra/tnetstrings/tnetstrings.factor [new file with mode: 0644]
extra/tty-server/tty-server.factor
extra/vpri-talk/vpri-talk.factor
extra/webapps/benchmark/benchmark.factor [new file with mode: 0644]
extra/webapps/fjsc/www/repl.js
extra/webapps/mason/version/files/files.factor
extra/websites/factorcode/index.fhtml
extra/wolfram-alpha/authors.txt [new file with mode: 0644]
extra/wolfram-alpha/summary.txt [new file with mode: 0644]
extra/wolfram-alpha/wolfram-alpha.factor [new file with mode: 0644]

index 387903d1e9d60968f2822e63fb6fbfc6d7041327..b64de97622ea720a5a77a3135a84ca2c85f5c44b 100644 (file)
@@ -4,19 +4,5 @@ namespaces eval kernel vocabs.loader io ;
 [
     boot
     do-startup-hooks
-    [
-        (command-line) parse-command-line
-        load-vocab-roots
-        run-user-init
-
-        "e" get script get or [
-            "e" get [ eval( -- ) ] when*
-            script get [ run-script ] when*
-        ] [
-            "run" get run
-        ] if
-
-        output-stream get [ stream-flush ] when*
-        0 exit
-    ] [ print-error 1 exit ] recover
+    [ command-line-startup ] [ print-error 1 exit ] recover
 ] set-startup-quot
index 1c242a6591208ecc82d49b6d63d22ecea71962e5..4fd109807e8042ac110bc2ae90f090d5e02325fb 100644 (file)
@@ -43,7 +43,7 @@ HELP: fnv1a-1024
 { $class-description "Fowler-Noll-Vo checksum algorithm, v1a, 1024-bit." } ;
 
 ARTICLE: "checksums.fnv1" "Fowler-Noll-Vo checksum"
-  "The Fowler-Noll-Vo checksum algorithm is another simple and fast checksum. It comes in 32, 64, 128, 256, 512 and 1024-bit versions, each in 1 and 1a variants. The 1a variants tend to produce a slightly better result. See http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash for more details."
+  "The Fowler-Noll-Vo checksum algorithm is another simple and fast checksum. It comes in 32, 64, 128, 256, 512 and 1024-bit versions, each in 1 and 1a variants. The 1a variants tend to produce a slightly better result. See " { $url "http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash" } " for more details."
 { $subsections
     fnv1-32
     fnv1a-32
index f13c9c1e77f7b880a3377fd0ad6283a5d9c7b616..b1b0eae4456fbc5fff67d387b1f8fb554ffd81fa 100644 (file)
@@ -1 +1,4 @@
 Joe Groff
+Daniel Ehrenberg
+John Benediktsson
+Slava Pestov
index b7b51432ddb2fb89ddc41f3eec669cfaa28c681f..57b6b4fca54dcbb8648644cdd83e604cf128a106 100644 (file)
@@ -1,17 +1,22 @@
 ! (c)Joe Groff bsd license
-USING: accessors alien alien.c-types alien.data alien.prettyprint arrays
-assocs classes classes.struct combinators combinators.short-circuit
-continuations fry kernel libc make math math.parser mirrors
-prettyprint.backend prettyprint.custom prettyprint.sections
-see.private sequences slots strings summary words ;
+USING: accessors alien alien.c-types alien.data
+alien.prettyprint arrays assocs classes classes.struct
+combinators combinators.short-circuit continuations fry kernel
+libc make math math.parser mirrors prettyprint.backend
+prettyprint.custom prettyprint.sections see.private sequences
+slots strings summary words ;
 IN: classes.struct.prettyprint
 
 <PRIVATE
 
 : struct-definer-word ( class -- word )
-    struct-slots dup length 2 >=
-    [ second offset>> 0 = \ UNION-STRUCT: \ STRUCT: ? ]
-    [ drop \ STRUCT: ] if ;
+    struct-slots
+    {
+        { [ dup length 1 <= ] [ drop \ STRUCT: ] }
+        { [ dup [ offset>> 0 = ] all? ] [ drop \ UNION-STRUCT: ] }
+        { [ dup [ packed?>> ] all? ] [ drop \ PACKED-STRUCT: ] }
+        [ drop \ STRUCT: ]
+    } cond ;
 
 : struct>assoc ( struct -- assoc )
     [ class struct-slots ] [ struct-slot-values ] bi zip ;
index 68a4876f926cb9fd84449d15c8aef8595b966794..13ac16a7bbbbecbe4640430f88499e18b4bec2c3 100644 (file)
@@ -55,12 +55,23 @@ HELP: UNION-STRUCT:
 { $values { "class" "a new " { $link struct } " class to define" } { "slots" "a list of slot specifiers" } }
 { $description "Defines a new " { $link struct } " type where all of the slots share the same storage. See " { $link POSTPONE: STRUCT: } " for details on the syntax." } ;
 
+HELP: PACKED-STRUCT:
+{ $syntax "PACKED-STRUCT: class { slot type } { slot type } ... ;" }
+{ $values { "class" "a new " { $link struct } " class to define" } { "slots" "a list of slot specifiers" } }
+{ $description "Defines a new " { $link struct } " type with no alignment padding between slots or at the end. In all other respects, behaves like " { $link POSTPONE: STRUCT: } "." } ;
+
 HELP: define-struct-class
 { $values
     { "class" class } { "slots" "a sequence of " { $link struct-slot-spec } "s" }
 }
 { $description "Defines a new " { $link struct } " class. This is the runtime equivalent of the " { $link POSTPONE: STRUCT: } " syntax." } ;
 
+HELP: define-packed-struct-class
+{ $values
+    { "class" class } { "slots" "a sequence of " { $link struct-slot-spec } "s" }
+}
+{ $description "Defines a new " { $link struct } " class. This is the runtime equivalent of the " { $link POSTPONE: PACKED-STRUCT: } " syntax." } ;
+
 HELP: define-union-struct-class
 { $values
     { "class" class } { "slots" "a sequence of " { $link struct-slot-spec } "s" }
@@ -121,7 +132,7 @@ ARTICLE: "classes.struct.examples" "Struct class examples"
 
 ARTICLE: "classes.struct.define" "Defining struct classes"
 "Struct classes are defined using a syntax similar to the " { $link POSTPONE: TUPLE: } " syntax for defining tuple classes:"
-{ $subsections POSTPONE: STRUCT: }
+{ $subsections POSTPONE: STRUCT: POSTPONE: PACKED-STRUCT: }
 "Union structs are also supported, which behave like structs but share the same memory for all the slots."
 { $subsections POSTPONE: UNION-STRUCT: } ;
 
index 4bc567ce8b741b2fe000012083a04c363d7ad359..46970c86f711d796f0ed78097b50235315a1f1fd 100644 (file)
@@ -1,11 +1,13 @@
 ! (c)Joe Groff bsd license
-USING: accessors alien alien.c-types alien.data alien.syntax ascii
-assocs byte-arrays classes.struct classes.tuple.parser
-classes.tuple.private classes.tuple combinators compiler.tree.debugger
-compiler.units delegate destructors io.encodings.utf8 io.pathnames
-io.streams.string kernel libc literals math mirrors namespaces
-prettyprint prettyprint.config see sequences specialized-arrays
-system tools.test parser lexer eval layouts generic.single classes
+USING: accessors alien alien.c-types alien.data alien.syntax
+ascii assocs byte-arrays classes.struct
+classes.struct.prettyprint classes.struct.prettyprint.private
+classes.tuple.parser classes.tuple.private classes.tuple
+combinators compiler.tree.debugger compiler.units delegate
+destructors io.encodings.utf8 io.pathnames io.streams.string
+kernel libc literals math mirrors namespaces prettyprint
+prettyprint.config see sequences specialized-arrays system
+tools.test parser lexer eval layouts generic.single classes
 vocabs ;
 FROM: math => float ;
 FROM: specialized-arrays.private => specialized-array-vocab ;
@@ -131,6 +133,9 @@ STRUCT: struct-test-bar
     [ make-mirror clear-assoc ] keep
 ] unit-test
 
+[ POSTPONE: STRUCT: ]
+[ struct-test-foo struct-definer-word ] unit-test
+
 UNION-STRUCT: struct-test-float-and-bits
     { f c:float }
     { bits uint } ;
@@ -140,6 +145,9 @@ UNION-STRUCT: struct-test-float-and-bits
 
 [ 123 ] [ [ struct-test-foo malloc-struct &free y>> ] with-destructors ] unit-test
 
+[ POSTPONE: UNION-STRUCT: ]
+[ struct-test-float-and-bits struct-definer-word ] unit-test
+
 STRUCT: struct-test-string-ptr
     { x c-string } ;
 
@@ -487,3 +495,22 @@ SPECIALIZED-ARRAY: void*
 STRUCT: silly-array-field-test { x int*[3] } ;
 
 [ t ] [ silly-array-field-test <struct> x>> void*-array? ] unit-test
+
+! Packed structs
+PACKED-STRUCT: packed-struct-test
+    { d c:int }
+    { e c:short }
+    { f c:int }
+    { g c:char }
+    { h c:int } ;
+
+[ 15 ] [ packed-struct-test heap-size ] unit-test
+
+[ 0 ] [ "d" packed-struct-test offset-of ] unit-test
+[ 4 ] [ "e" packed-struct-test offset-of ] unit-test
+[ 6 ] [ "f" packed-struct-test offset-of ] unit-test
+[ 10 ] [ "g" packed-struct-test offset-of ] unit-test
+[ 11 ] [ "h" packed-struct-test offset-of ] unit-test
+
+[ POSTPONE: PACKED-STRUCT: ]
+[ packed-struct-test struct-definer-word ] unit-test
index 15a7b72c6c2aaabf9dbe49def8313e9d1d473571..c00746865b1d41f41f8bc8a27c85ece6cfc830c8 100644 (file)
@@ -1,4 +1,6 @@
-! (c)Joe Groff, Daniel Ehrenberg bsd license
+! Copyright (C) 2010, 2011 Joe Groff, Daniel Ehrenberg,
+! John Benediktsson, Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license
 USING: accessors alien alien.c-types alien.data alien.parser
 arrays byte-arrays classes classes.private classes.parser
 classes.tuple classes.tuple.parser classes.tuple.private
@@ -24,8 +26,11 @@ M: struct-must-have-slots summary
 TUPLE: struct
     { (underlying) c-ptr read-only } ;
 
+! We hijack the core slots vocab's slot-spec type for struct
+! fields. Note that 'offset' is in bits, not bytes, to support
+! bitfields.
 TUPLE: struct-slot-spec < slot-spec
-    type ;
+    type packed? ;
 
 ! For a struct-bit-slot-spec, offset is in bits, not bytes
 TUPLE: struct-bit-slot-spec < struct-slot-spec
@@ -213,11 +218,14 @@ M: struct-c-type base-type ;
 
 GENERIC: compute-slot-offset ( offset class -- offset' )
 
-: c-type-align-at ( class offset -- n )
-    0 = [ c-type-align-first ] [ c-type-align ] if ;
+: c-type-align-at ( slot-spec offset -- n )
+    over packed?>> [ 2drop 1 ] [
+        [ type>> ] dip
+        0 = [ c-type-align-first ] [ c-type-align ] if
+    ] if ;
 
 M: struct-slot-spec compute-slot-offset
-    [ type>> over c-type-align-at 8 * align ] keep
+    [ over c-type-align-at 8 * align ] keep
     [ [ 8 /i ] dip offset<< ] [ type>> heap-size 8 * + ] 2bi ;
 
 M: struct-bit-slot-spec compute-slot-offset
@@ -231,7 +239,7 @@ M: struct-bit-slot-spec compute-slot-offset
 
 : struct-alignment ( slots -- align )
     [ struct-bit-slot-spec? not ] filter
-    1 [ [ type>> ] [ offset>> ] bi c-type-align-at max ] reduce ;
+    1 [ dup offset>> c-type-align-at max ] reduce ;
 
 PRIVATE>
 
@@ -267,28 +275,41 @@ M: struct binary-zero? binary-object <direct-uchar-array> [ 0 = ] all? ; inline
 : redefine-struct-tuple-class ( class -- )
     [ struct f define-tuple-class ] [ make-final ] bi ;
 
-:: (define-struct-class) ( class slots offsets-quot -- )
-    slots empty? [ struct-must-have-slots ] when
+:: (define-struct-class) ( class slot-specs offsets-quot alignment-quot -- )
+    slot-specs check-struct-slots
+    slot-specs empty? [ struct-must-have-slots ] when
     class redefine-struct-tuple-class
-    slots make-slots dup check-struct-slots :> slot-specs
     slot-specs offsets-quot call :> unaligned-size
-    slot-specs struct-alignment :> alignment
+    slot-specs alignment-quot call :> alignment
     unaligned-size alignment align :> size
 
-    class  slot-specs  size  alignment  c-type-for-class :> c-type
+    class slot-specs size alignment c-type-for-class :> c-type
 
     c-type class typedef
     class slot-specs define-accessors
     class size "struct-size" set-word-prop
     class dup make-struct-prototype "prototype" set-word-prop
     class (struct-methods) ; inline
+
+: make-packed-slots ( slots -- slot-specs )
+    make-slots [ t >>packed? ] map! ;
+
 PRIVATE>
 
 : define-struct-class ( class slots -- )
-    [ compute-struct-offsets ] (define-struct-class) ;
+    make-slots
+    [ compute-struct-offsets ] [ struct-alignment ]
+    (define-struct-class) ;
+
+: define-packed-struct-class ( class slots -- )
+    make-packed-slots
+    [ compute-struct-offsets ] [ drop 1 ]
+    (define-struct-class) ;
 
 : define-union-struct-class ( class slots -- )
-    [ compute-union-offsets ] (define-struct-class) ;
+    make-slots
+    [ compute-union-offsets ] [ struct-alignment ]
+    (define-struct-class) ;
 
 ERROR: invalid-struct-slot token ;
 
@@ -352,6 +373,10 @@ PRIVATE>
 
 SYNTAX: STRUCT:
     parse-struct-definition define-struct-class ;
+
+SYNTAX: PACKED-STRUCT:
+    parse-struct-definition define-packed-struct-class ;
+
 SYNTAX: UNION-STRUCT:
     parse-struct-definition define-union-struct-class ;
 
@@ -377,6 +402,7 @@ SYNTAX: S@
         { "{" [ parse-struct-slot` t ] }
         [ invalid-struct-slot ]
     } case ;
+
 PRIVATE>
 
 FUNCTOR-SYNTAX: STRUCT:
index ac529d297a8c1dd01320cb824d32bed69edf2180..d0043f55cfea2ea8057282762f3147d267a2920f 100644 (file)
@@ -49,7 +49,7 @@ $nl
     "objc-calling"
     "objc-subclassing"
 }
-"A utility library is built to faciliate the development of Cocoa applications in Factor:"
+"A utility library is built to facilitate the development of Cocoa applications in Factor:"
 { $subsections
     "cocoa-application-utils"
     "cocoa-dialogs"
index 067360530d23b84f613e49ec6ab386a4ce011b94..db9a6b8e121d957642718d42296e3011de7a4833 100644 (file)
@@ -135,7 +135,7 @@ $nl
 ARTICLE: "cli" "Command line arguments"
 "Factor command line usage:"
 { $code "factor [VM args...] [script] [args...]" }
-"Zero or more VM arguments can be passed in, followed by an optional script file name. If the script file is specified, it will be run on startup, any arguments after the script file are stored in the following variable, with no further processing by Factor itself:"
+"Zero or more VM arguments can be passed in, followed by an optional script file name. If the script file is specified, it will be run on startup using " { $link run-script } ". Any arguments after the script file are stored in the following variable, with no further processing by Factor itself:"
 { $subsections command-line }
 "Instead of running a script, it is also possible to run a vocabulary; this invokes the vocabulary's " { $link POSTPONE: MAIN: } " word:"
 { $code "factor [system switches...] -run=<vocab name>" }
@@ -159,4 +159,9 @@ $nl
 "There is a way to override the default vocabulary to run on startup, if no script name or " { $snippet "-run" } " switch is specified:"
 { $subsections main-vocab-hook } ;
 
+HELP: run-script
+{ $values { "file" "a pathname string" } }
+{ $description "Parses the Factor source code stored in a file and runs it. The initial vocabulary search path is used. If the source file contains a " { $link POSTPONE: MAIN: } " declaration, the main entry point of the file will be also be executed. Loading messages will be suppressed." }
+{ $errors "Throws an error if loading the file fails, there input is malformed, or if a runtime error occurs while calling the parsed quotation or executing the main entry point." }  ;
+
 ABOUT: "cli"
index 88ade747d2b3cc5d0f5fb1120128f7a55e5cfedd..0b55798b2d4fb8e0a63822506e0d3114e478d11c 100644 (file)
@@ -2,7 +2,8 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: init continuations hashtables io io.encodings.utf8
 io.files io.pathnames kernel kernel.private namespaces parser
-sequences strings system splitting vocabs.loader alien.strings ;
+sequences source-files strings system splitting vocabs.loader
+alien.strings accessors eval ;
 IN: command-line
 
 SYMBOL: script
@@ -39,7 +40,10 @@ SYMBOL: command-line
     "=" split1 [ var-param ] [ bool-param ] if* ;
 
 : run-script ( file -- )
-    t "quiet" set-global run-file ;
+    t "quiet" [
+        [ run-file ]
+        [ source-file main>> [ execute( -- ) ] when* ] bi
+    ] with-variable ;
 
 : parse-command-line ( args -- )
     [ command-line off script off ] [
@@ -67,3 +71,41 @@ SYMBOL: main-vocab-hook
     ] bind ;
 
 [ default-cli-args ] "command-line" add-startup-hook
+
+: cli-usage ( -- )
+"""
+Usage: """ write vm file-name write """ [Factor arguments] [script] [script arguments]
+
+Common arguments:
+    -help            print this message and exit
+    -i=<image>       load Factor image file <image> (default """ write vm file-name write """.image)
+    -run=<vocab>     run the MAIN: entry point of <vocab>
+    -e=<code>        evaluate <code>
+    -quiet           suppress "Loading vocab.factor" messages
+    -no-user-init    suppress loading of .factor-rc
+
+Enter
+    "command-line" help
+from within Factor for more information.
+
+""" write ;
+
+: command-line-startup ( -- )
+    (command-line) parse-command-line
+    "help" get "-help" get or "h" get or [ cli-usage ] [
+        "e" get script get or "quiet" [
+            load-vocab-roots
+            run-user-init
+
+            "e" get script get or [
+                "e" get [ eval( -- ) ] when*
+                script get [ run-script ] when*
+            ] [
+                "run" get run
+            ] if
+        ] with-variable
+    ] if
+
+    output-stream get [ stream-flush ] when*
+    0 exit ;
+
index 4c961deb96889ebe038009381768ed486c83f5c1..29c90bcdd5fee53f28198f3cfe76ce9ece9f3aac 100644 (file)
@@ -16,7 +16,7 @@ HELP: await
 { $description "Waits until the count-down value reaches zero." } ;\r
 \r
 ARTICLE: "concurrency.count-downs" "Count-down latches"\r
-"The " { $vocab-link "concurrency.count-downs" } " vocabulary implements the " { $emphasis "count-down latch" } " data type, whichis a wrapper for a non-negative integer value which tends towards zero. A thread can either decrement the value, or wait for it to become zero."\r
+"The " { $vocab-link "concurrency.count-downs" } " vocabulary implements the " { $emphasis "count-down latch" } " data type, which is a wrapper for a non-negative integer value which tends towards zero. A thread can either decrement the value, or wait for it to become zero."\r
 { $subsections\r
     <count-down>\r
     count-down\r
diff --git a/basis/cpu/ppc/32/linux/tags.txt b/basis/cpu/ppc/32/linux/tags.txt
new file mode 100644 (file)
index 0000000..44629a5
--- /dev/null
@@ -0,0 +1,2 @@
+not loaded
+compiler
diff --git a/basis/cpu/ppc/32/tags.txt b/basis/cpu/ppc/32/tags.txt
new file mode 100644 (file)
index 0000000..44629a5
--- /dev/null
@@ -0,0 +1,2 @@
+not loaded
+compiler
diff --git a/basis/cpu/ppc/64/linux/tags.txt b/basis/cpu/ppc/64/linux/tags.txt
new file mode 100644 (file)
index 0000000..44629a5
--- /dev/null
@@ -0,0 +1,2 @@
+not loaded
+compiler
diff --git a/basis/cpu/ppc/64/tags.txt b/basis/cpu/ppc/64/tags.txt
new file mode 100644 (file)
index 0000000..44629a5
--- /dev/null
@@ -0,0 +1,2 @@
+not loaded
+compiler
diff --git a/basis/cpu/ppc/tags.txt b/basis/cpu/ppc/tags.txt
new file mode 100644 (file)
index 0000000..44629a5
--- /dev/null
@@ -0,0 +1,2 @@
+not loaded
+compiler
index 50f60d8adb29aca8e6dcd351a02550a6d5fa080a..bbda3c3cc8cc9afb5ea921926deaf97dfe31147a 100644 (file)
@@ -158,7 +158,7 @@ ARTICLE: "db-tuples" "High-level tuple/database integration"
 { $subsections "db.types" }
 "Useful words:"
 { $subsections "db-tuples-words" }
-"For porting db.tuples to other databases:"
+"For porting " { $vocab-link "db.tuples" } " to other databases:"
 { $subsections "db-tuples-protocol" }
 ;
 
index 451016cc6c9f46e57fdb2346d164576b720ef767..30151bd634c69a3a4de0cf33b118ba9aa6d003a6 100644 (file)
@@ -46,7 +46,7 @@ ARTICLE: "delegate" "Delegation"
 $nl
 "A " { $emphasis "protocol" } " is a collection of related generic words. An object is said to " { $emphasis "consult" } " another object if it implements a protocol by forwarding all methods onto the other object."
 $nl
-"Using this vocabulary, protocols can be defined and consulation can be set up without any repetitive boilerplate."
+"Using this vocabulary, protocols can be defined and consultation can be set up without any repetitive boilerplate."
 $nl
 "Unlike " { $link "tuple-subclassing" } ", which expresses " { $emphasis "is-a" } " relationships by statically including the methods and slots of the superclass in all subclasses, consultation forwards generic word calls to another distinct object."
 $nl
index 4d42f71dc03a40407ddcfeac3347fa19c1981ec8..9cf4bd01a7f22508d782f5050f638b2d987364b6 100644 (file)
@@ -135,7 +135,7 @@ PROTOCOL: silly-protocol do-me ;
 ! Method should be there
 [ ] [ T{ a-tuple } do-me ] unit-test
 
-! Now try removing the consulation
+! Now try removing the consultation
 [ [ ] ] [
     "IN: delegate.tests" <string-reader> "delegate-test" parse-stream
 ] unit-test
index 3779d0e680813b06101e1dcf602bdf3b2f45cbc7..4d1d5aab8f34f97d43e5aaa382e532f3371ea8f9 100644 (file)
@@ -18,7 +18,7 @@ HELP: (write-farkup)
 { $description "Converts a Farkup syntax tree node to XML." } ;
 
 ARTICLE: "farkup-ast" "Farkup syntax tree nodes"
-"The " { $link parse-farkup } " word outputs a tree of nodes corresponding to the Farkup syntax of the input string. This tree can be programatically traversed and mutated before being passed on to " { $link write-farkup } "."
+"The " { $link parse-farkup } " word outputs a tree of nodes corresponding to the Farkup syntax of the input string. This tree can be programmatically traversed and mutated before being passed on to " { $link write-farkup } "."
 { $subsections
     heading1
     heading2
index 7889ffc626e43c898fa1af55a0121125062347e7..4ac03ce839b9302e0d07282d39b4fda581527120 100644 (file)
@@ -39,7 +39,8 @@ M: recaptcha call-responder*
     XML] ;
 
 : recaptcha-url ( secure? -- ? )
-    "https://api.recaptcha.net/challenge" "http://api.recaptcha.net/challenge" ?
+    "http://www.google.com/recaptcha/api/challenge"
+    "https://www.google.com/recaptcha/api/challenge" ?
     recaptcha-error cget [ "?error=" glue ] when* >url ;
 
 : render-recaptcha ( -- xml )
index 5a5460a17928e315d6ae72e4584f2fb798725921..941ad535d33fb4ac6ff5814ad309d6d745d96ade 100644 (file)
@@ -173,7 +173,7 @@ ARTICLE: "http.client.options" "OPTIONS requests with the HTTP client"
 { $subsections
     <options-request>
 }
-"RFC2616 does not define any use for an entity body, yet allows for the inclusion of one as part of the OPTIONS method. This is not supported with this version of the http.client. The current implementation of http-options only supports a " { $link url } " request with no corresponding post-data, as per the stack effect." ;
+"RFC2616 does not define any use for an entity body, yet allows for the inclusion of one as part of the OPTIONS method. This is not supported with this version of the " { $vocab-link "http.client" } ". The current implementation of " { $link http-options } " only supports a " { $link url } " request with no corresponding post-data, as per the stack effect." ;
 
 ARTICLE: "http.client.trace" "TRACE requests with the HTTP client"
 "Basic usage involves passing a " { $link url } " and getting a " { $link response } " and data back:"
index 7418eb0a196e48b5a6d42a6f9aa6d0c98fb39338..9afc5286f5a58fc0358cf1f59eee6aa5bb92130e 100644 (file)
@@ -84,7 +84,7 @@ ARTICLE: "io.mmap.examples" "Memory-mapped file examples"
     "    [ reverse! drop ] each"
     "] with-mapped-array"
 }
-"Normalize a file containing packed quadrupes of floats:"
+"Normalize a file containing packed quadruples of floats:"
 { $code
     "USING: kernel io.mmap math.vectors math.vectors.simd" "sequences specialized-arrays ;"
     "SPECIALIZED-ARRAY: float-4"
index 0f15faff9091d29d0d0ef0fad2e50aebcf86d487..b303feee80416479bcfb940925a622499312a6e2 100644 (file)
@@ -1,7 +1,8 @@
 USING: io io.pipes io.streams.string io.encodings.utf8
 io.encodings.binary io.streams.duplex io.encodings io.timeouts
 namespaces continuations tools.test kernel calendar destructors
-accessors debugger math sequences ;
+accessors debugger math sequences threads
+concurrency.count-downs fry ;
 IN: io.pipes.tests
 
 [ "Hello" ] [
@@ -11,6 +12,7 @@ IN: io.pipes.tests
     ] with-stream
 ] unit-test
 
+! Test run-pipeline
 [ { } ] [ { } run-pipeline ] unit-test
 [ { f } ] [ { [ f ] } run-pipeline ] unit-test
 [ { "Hello" } ] [
@@ -26,6 +28,7 @@ IN: io.pipes.tests
     } run-pipeline
 ] unit-test
 
+! Test timeout
 [
     utf8 <pipe> [
         1 seconds over set-timeout
@@ -33,6 +36,7 @@ IN: io.pipes.tests
     ] with-disposal
 ] must-fail
 
+! Test writing to a half-open pipe
 [ ] [
     1000 [
         utf8 <pipe> [
@@ -43,6 +47,34 @@ IN: io.pipes.tests
     ] times
 ] unit-test
 
+! Test non-blocking operation
+[ ] [
+    [
+        2 <count-down> "count-down" set
+
+        utf8 <pipe> &dispose
+        utf8 <pipe> &dispose
+        [
+            [
+                '[
+                    _ stream-read1 drop
+                    "count-down" get count-down
+                ] in-thread
+            ] bi@
+            
+            ! Give the threads enough time to start blocking on
+            ! read
+            1 seconds sleep
+        ]
+        ! At this point, two threads are blocking on read
+        [ [ "Hi" over stream-write stream-flush ] bi@ ]
+        ! At this point, both threads should wake up
+        2bi
+
+        "count-down" get await
+    ] with-destructors
+] unit-test
+
 ! 0 read should not block
 [ f ] [
     [
index ffc1c04ec974c5ef02f7ee1db2d56fc0bb39fcf9..139e0362416b9b8294117ade72e05e60fe7f3f24 100644 (file)
@@ -57,7 +57,7 @@ $nl
 "This slot is required for secure server sockets." ;
 
 ARTICLE: "ssl-ephemeral-rsa" "Ephemeral RSA key bits"
-"The " { $snippet "ephemeral-key-bits" } " slot of a " { $link secure-config } " contains the length of the empheral RSA key, in bits."
+"The " { $snippet "ephemeral-key-bits" } " slot of a " { $link secure-config } " contains the length of the ephemeral RSA key, in bits."
 $nl
 "The default value is 1024, and anything less than that is considered insecure. This slot is required for secure server sockets." ;
 
@@ -113,7 +113,7 @@ HELP: accept-secure-handshake
 { $errors "Throws " { $link upgrade-on-non-socket } " or " { $link upgrade-buffers-full } " if used improperly." } ;
 
 ARTICLE: "ssl-upgrade" "Upgrading existing connections"
-"Some protocols, such as HTTPS, require that the connection be established as an SSL/TLS connection. Others, such as secure SMTP and POP3 require that the client and server initiate an SSL/TLS handshake upon the client sending a plain-text request. The latter use-case is accomodated by a pair of words."
+"Some protocols, such as HTTPS, require that the connection be established as an SSL/TLS connection. Others, such as secure SMTP and POP3 require that the client and server initiate an SSL/TLS handshake upon the client sending a plain-text request. The latter use-case is accommodated by a pair of words."
 $nl
 "Upgrading a connection to a secure socket by initiating an SSL/TLS handshake with the server:"
 { $subsections send-secure-handshake }
index 7e57f87a9ea6568870ae1c41f2903d9b293b3bdd..685d5a649ad4d4ff64b29a152cbb9458c2c60277 100644 (file)
@@ -29,6 +29,12 @@ os unix? [
 
 [ T{ inet f "google.com" 80 } ] [ "google.com" 80 with-port ] unit-test
 
+! Test bad hostnames
+[ "google.com" f <inet4> ] must-fail
+[ "a.b.c.d" f <inet4> ] must-fail
+[ "google.com" f <inet6> ] must-fail
+[ "a.b.c.d" f <inet6> ] must-fail
+
 ! Test present on addrspecs
 [ "4.4.4.4:12" ] [ "4.4.4.4" 12 <inet4> present ] unit-test
 [ "::1:12" ] [ "::1" 12 <inet6> present ] unit-test
index 0865500f76f02da25a22c80c14c049e01ffa3645..2da840833cb1e6fe1e824520d24e31b8c3349545 100644 (file)
@@ -68,27 +68,32 @@ SLOT: port
 
 TUPLE: ipv4 { host ?string read-only } ;
 
-C: <ipv4> ipv4
+<PRIVATE
 
-M: ipv4 inet-ntop ( data addrspec -- str )
-    drop 4 memory>byte-array [ number>string ] { } map-as "." join ;
+ERROR: invalid-ipv4 string reason ;
 
-<PRIVATE
+M: invalid-ipv4 summary drop "Invalid IPv4 address" ;
 
 ERROR: malformed-ipv4 sequence ;
 
 ERROR: bad-ipv4-component string ;
 
 : parse-ipv4 ( string -- seq )
-    "." split dup length 4 = [ malformed-ipv4 ] unless
-    [ dup string>number [ ] [ bad-ipv4-component ] ?if ] B{ } map-as ;
-
-ERROR: invalid-ipv4 string reason ;
+    [ f ] [
+        "." split dup length 4 = [ malformed-ipv4 ] unless
+        [ dup string>number [ ] [ bad-ipv4-component ] ?if ] B{ } map-as
+    ] if-empty ;
 
-M: invalid-ipv4 summary drop "Invalid IPv4 address" ;
+: check-ipv4 ( string -- )
+    [ parse-ipv4 drop ] [ invalid-ipv4 ] recover ;
 
 PRIVATE>
 
+: <ipv4> ( host -- ipv4 ) dup check-ipv4 ipv4 boa ;
+
+M: ipv4 inet-ntop ( data addrspec -- str )
+    drop 4 memory>byte-array [ number>string ] { } map-as "." join ;
+
 M: ipv4 inet-pton ( str addrspec -- data )
     drop [ parse-ipv4 ] [ invalid-ipv4 ] recover ;
 
@@ -113,7 +118,8 @@ M: ipv4 parse-sockaddr ( sockaddr-in addrspec -- newaddrspec )
 
 TUPLE: inet4 < ipv4 { port integer read-only } ;
 
-C: <inet4> inet4
+: <inet4> ( host port -- inet4 )
+    over check-ipv4 inet4 boa ;
 
 M: ipv4 with-port [ host>> ] dip <inet4> ;
 
@@ -129,14 +135,11 @@ TUPLE: ipv6
 { host ?string read-only }
 { scope-id integer read-only } ;
 
-: <ipv6> ( host -- ipv6 ) 0 ipv6 boa ;
+<PRIVATE
 
-M: ipv6 inet-ntop ( data addrspec -- str )
-    drop 16 memory>byte-array 2 <groups> [ be> >hex ] map ":" join ;
+ERROR: invalid-ipv6 host reason ;
 
-ERROR: invalid-ipv6 string reason ;
-
-<PRIVATE
+M: invalid-ipv6 summary drop "Invalid IPv6 address" ;
 
 ERROR: bad-ipv6-component obj ;
 
@@ -157,6 +160,18 @@ ERROR: more-than-8-components ;
         ] if
     ] if-empty ;
 
+: check-ipv6 ( string -- )
+    [ "::" split1 [ parse-ipv6 ] bi@ 2drop ] [ invalid-ipv6 ] recover ;
+
+PRIVATE>
+
+: <ipv6> ( host -- ipv6 ) dup check-ipv6 0 ipv6 boa ;
+
+M: ipv6 inet-ntop ( data addrspec -- str )
+    drop 16 memory>byte-array 2 <groups> [ be> >hex ] map ":" join ;
+
+<PRIVATE
+
 : pad-ipv6 ( string1 string2 -- seq )
     2dup [ length ] bi@ + 8 swap -
     dup 0 < [ more-than-8-components ] when
@@ -200,7 +215,8 @@ M: ipv6 present
 
 TUPLE: inet6 < ipv6 { port integer read-only } ;
 
-: <inet6> ( host port -- inet6 ) [ 0 ] dip inet6 boa ;
+: <inet6> ( host port -- inet6 )
+    [ dup check-ipv6 0 ] dip inet6 boa ;
 
 M: ipv6 with-port
     [ [ host>> ] [ scope-id>> ] bi ] dip
index 75eb46791a9c8f5fe986c62bc069abc9453e521a..58cd3fbdd8e9e672f1227b444accdaae65168bf4 100644 (file)
@@ -7,13 +7,22 @@ IN: io.thread
 ! over completely.
 SYMBOL: io-thread-running?
 
-: io-thread ( -- )
-    sleep-time io-multiplex yield ;
+TUPLE: io-thread < thread ;
+
+: <io-thread> ( -- thread )
+    [
+        [ io-thread-running? get-global ]
+        [ sleep-time io-multiplex yield ]
+        while
+    ]
+    "I/O wait"
+    io-thread new-thread ;
+
+M: io-thread error-in-thread [ die ] call( error thread -- ) ;
 
 : start-io-thread ( -- )
     t io-thread-running? set-global
-    [ [ io-thread-running? get-global ] [ io-thread ] while ]
-    "I/O wait" spawn drop ;
+    <io-thread> (spawn) ;
 
 : stop-io-thread ( -- )
     f io-thread-running? set-global ;
index a78f444b21dbc76b0c159c7fa4f462046f268019..938e9e7a4c2567f12b3060e7d2013dccd3fe677f 100644 (file)
@@ -55,7 +55,7 @@ HELP: unique-primes
 { $description "Generates a sequence of " { $snippet "n" } " unique prime numbers with exactly " { $snippet "numbits" } " bits." } ;
 
 ARTICLE: "math.primes" "Prime numbers"
-"The " { $vocab-link "math.primes" } " vocabulary implements words related to prime numbers. Serveral useful vocabularies exist for testing primality. The Sieve of Eratosthenes in " { $vocab-link "math.primes.erato" } " is useful for testing primality below five million. For larger integers, " { $vocab-link "math.primes.miller-rabin" } " is a fast probabilstic primality test. The " { $vocab-link "math.primes.lucas-lehmer" } " vocabulary implements an algorithm for finding huge Mersenne prime numbers." $nl
+"The " { $vocab-link "math.primes" } " vocabulary implements words related to prime numbers. Several useful vocabularies exist for testing primality. The Sieve of Eratosthenes in " { $vocab-link "math.primes.erato" } " is useful for testing primality below five million. For larger integers, " { $vocab-link "math.primes.miller-rabin" } " is a fast probabilistic primality test. The " { $vocab-link "math.primes.lucas-lehmer" } " vocabulary implements an algorithm for finding huge Mersenne prime numbers." $nl
 "Testing if a number is prime:"
 { $subsections prime? }
 "Generating prime numbers:"
index 742bc7cb454a476390384ee2a90923b4e6a92b46..3f35d684cde583b26bd3e5023a52842b327f3a6a 100644 (file)
@@ -31,7 +31,7 @@ $nl
 $nl
 "On PowerPC, or older x86 chips without SSE, software fallbacks are used for all high-level vector operations. SIMD code can run with no loss in functionality, just decreased performance."
 $nl
-"The primities in the " { $vocab-link "math.vectors.simd.intrinsics" } " vocabulary do not have software fallbacks, but they should not be called directly in any case." ;
+"The primitives in the " { $vocab-link "math.vectors.simd.intrinsics" } " vocabulary do not have software fallbacks, but they should not be called directly in any case." ;
 
 ARTICLE: "math.vectors.simd.types" "SIMD vector types"
 "Each SIMD vector type is named " { $snippet "scalar-count" } ", where " { $snippet "scalar" } " is a scalar C type and " { $snippet "count" } " is a vector dimension."
index 26d8a3d0b67c8175b2a410d18de2c4a8165a30ac..e7287254046dcdfa0d6402c3a959425a61bc9f96 100644 (file)
@@ -279,7 +279,7 @@ ARTICLE: "peg.ebnf.semantic-action" "Semantic Action"
 "matched rule that returns success or failure. The result of the parse is decided by "
 "the result of the semantic action. The stack effect for the quotation is "
 { $snippet ( ast -- ? ) } ". "
-"A semantic action follows the rule it applies to and is delimeted by '?[' and ']?'."
+"A semantic action follows the rule it applies to and is delimited by '?[' and ']?'."
 { $examples
     { $example
        "USING: prettyprint peg.ebnf math math.parser ;"
@@ -431,7 +431,7 @@ $nl
 "working in one pass. There is no tokenization occurring over the whole string "
 "followed by the parse of that result. It tokenizes as it needs to. You can even "
 "switch tokenizers multiple times during a grammar. Rules use the tokenizer that "
-"was defined lexically before the rule. This is usefull in the JavaScript grammar:"
+"was defined lexically before the rule. This is useful in the JavaScript grammar:"
 { $examples
     { $code
         "EBNF: javascript"
index 5c9210e44a6e39d0d8837a1c6903e0f73fb757b2..c37df58519fc08c9fd54874f8144047333fc006c 100644 (file)
@@ -4,7 +4,7 @@ USING: accessors kernel math sorting words parser io summary
 quotations sequences sequences.generalizations prettyprint
 continuations effects definitions compiler.units namespaces
 assocs tools.time generic inspector fry locals generalizations
-macros ;
+macros sequences.deep ;
 IN: tools.annotations
 
 <PRIVATE
@@ -46,11 +46,24 @@ M: word (annotate)
     [ dup def>> 2dup "unannotated-def" set-word-prop ] dip
     call( old -- new ) define ;
 
+GENERIC# (deep-annotate) 1 ( word quot -- )
+
+M: generic (deep-annotate)
+    [ "methods" word-prop values ] dip '[ _ (deep-annotate) ] each ;
+
+M: word (deep-annotate)
+    [ check-annotate-twice ] dip
+    [ dup def>> 2dup "unannotated-def" set-word-prop ] dip
+    '[ dup callable? [ _ call( old -- new ) ] when ] deep-map define ;
+
 PRIVATE>
 
 : annotate ( word quot -- )
     [ (annotate) ] with-compilation-unit ;
 
+: deep-annotate ( word quot -- )
+    [ (deep-annotate) ] with-compilation-unit ;
+
 <PRIVATE
 
 :: trace-quot ( word effect quot str -- quot' )
diff --git a/basis/tools/code-coverage/authors.txt b/basis/tools/code-coverage/authors.txt
new file mode 100644 (file)
index 0000000..7c1b2f2
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
diff --git a/basis/tools/code-coverage/code-coverage.factor b/basis/tools/code-coverage/code-coverage.factor
new file mode 100644 (file)
index 0000000..5aabb1f
--- /dev/null
@@ -0,0 +1,51 @@
+! Copyright (C) 2011 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors assocs fry kernel quotations sequences strings
+tools.annotations vocabs words prettyprint io ;
+IN: tools.code-coverage
+
+TUPLE: coverage < identity-tuple executed? ;
+
+C: <coverage> coverage
+
+GENERIC: code-coverage-on ( object -- )
+
+GENERIC: code-coverage-off ( object -- )
+
+M: string code-coverage-on
+    words [ code-coverage-on ] each ;
+
+M: string code-coverage-off ( vocabulary -- )
+    words [ code-coverage-off ] each ;
+
+M: word code-coverage-on ( word -- )
+    H{ } clone [ "code-coverage" set-word-prop ] 2keep
+    '[
+        coverage new [ _ set-at ] 2keep
+        '[ _ t >>executed? drop ] [ ] surround
+    ] deep-annotate ;
+
+M: word code-coverage-off ( word -- )
+    [ reset ] [ f "code-coverage" set-word-prop ] bi ;
+
+GENERIC: untested ( object -- seq )
+
+M: string untested
+    words [ dup untested ] { } map>assoc ;
+
+M: word untested ( word -- seq )
+    "code-coverage" word-prop >alist
+    [ drop executed?>> not ] assoc-filter values ;
+
+GENERIC: show-untested ( object -- )
+
+M: string show-untested
+    words [ show-untested ] each ;
+
+M: word show-untested
+    dup untested [
+        drop
+    ] [
+        [ name>> ":" append print ]
+        [ [ bl bl bl bl . ] each ] bi*
+    ] if-empty ;
diff --git a/basis/tools/code-coverage/summary.txt b/basis/tools/code-coverage/summary.txt
new file mode 100644 (file)
index 0000000..02279b3
--- /dev/null
@@ -0,0 +1 @@
+A tool that uses annotations to determine which code paths are taken.
index 6609612baa1e9ed0f3458359fe844e0b207c064f..df8e72bc0cc7271cabf6816ba44906e6640d5b8a 100644 (file)
@@ -1,7 +1,8 @@
-! Copyright (C) 2008 Slava Pestov.
+! Copyright (C) 2008, 2011 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 IN: unix.linux.epoll
-USING: alien.c-types alien.syntax classes.struct math unix.types ;
+USING: alien.c-types alien.syntax classes.struct math
+unix.types ;
 
 FUNCTION: int epoll_create ( int size ) ;
 
@@ -11,7 +12,7 @@ UNION-STRUCT: epoll-data
     { u32 uint32_t }
     { u64 uint64_t } ;
 
-STRUCT: epoll-event
+PACKED-STRUCT: epoll-event
     { events uint32_t   }
     { data   epoll-data } ;
 
index c177196786e534f72304757c00f8fa3654842e26..62c9683a9741ec3867a355201cf3d0696580afe7 100644 (file)
@@ -199,7 +199,7 @@ $nl
 }
 "Creating " { $link "network-addressing" } " from URLs:"
 { $subsections url-addr }
-"The URL implemention encodes and decodes components of " { $link url } " instances automatically, but sometimes this functionality is needed for non-URL strings."
+"The URL implementation encodes and decodes components of " { $link url } " instances automatically, but sometimes this functionality is needed for non-URL strings."
 { $subsections "url-encoding" }
 "Utility words used by the URL implementation:"
 { $subsections "url-utilities" } ;
index 376c9b3f0ccf8ff1a68804f943f5e809a6e5ac7c..d1e3781dc8ad303a45e457039abe7a84bdff013b 100644 (file)
@@ -6,7 +6,7 @@ IN: xml.syntax
 ABOUT: "xml.syntax"
 
 ARTICLE: "xml.syntax" "Syntax extensions for XML"
-"The " { $link "xml.syntax" } " vocabulary defines a number of new parsing words forXML processing."
+"The " { $link "xml.syntax" } " vocabulary defines a number of new parsing words for XML processing."
 { $subsections
     { "xml.syntax" "tags" }
     { "xml.syntax" "literals" }
index 5b66b021bd26c02abdd3d9f8f754be7b09a1ab81..77f4808bfa37d91c4c4464799e02361c93684ef3 100644 (file)
@@ -16,7 +16,7 @@ ARTICLE: "xml.writer" "Writing XML"
     pprint-xml>string
     pprint-xml
 }
-"Certain variables can be changed to mainpulate prettyprinting"
+"Certain variables can be changed to manipulate prettyprinting"
 { $subsections
     sensitive-tags
     indenter
index 6587889de6b5157b99b5d5a27b426e4fa828a8af..07df34cdad64eb6563db659cefc6b6e7d66ee7f6 100644 (file)
@@ -125,30 +125,30 @@ ARTICLE: "tuple-inheritance-example" "Tuple subclassing example"
 "Rectangles, parallelograms and circles are all shapes. We support two operations on shapes:"
 { $list
     "Computing the area"
-    "Computing the perimiter"
+    "Computing the perimeter"
 }
-"Rectangles and parallelograms use the same algorithm for computing the area, whereas they use different algorithms for computing perimiter. Also, rectangles and parallelograms both have " { $snippet "width" } " and " { $snippet "height" } " slots. We can exploit this with subclassing:"
+"Rectangles and parallelograms use the same algorithm for computing the area, whereas they use different algorithms for computing perimeter. Also, rectangles and parallelograms both have " { $snippet "width" } " and " { $snippet "height" } " slots. We can exploit this with subclassing:"
 { $code
     "USING: accessors kernel math math.constants math.functions ;"
     "GENERIC: area ( shape -- n )"
-    "GENERIC: perimiter ( shape -- n )"
+    "GENERIC: perimeter ( shape -- n )"
     ""
     "TUPLE: shape ;"
     ""
     "TUPLE: circle < shape radius ;"
     "M: circle area radius>> sq pi * ;"
-    "M: circle perimiter radius>> 2 * pi * ;"
+    "M: circle perimeter radius>> 2 * pi * ;"
     ""
     "TUPLE: quad < shape width height ;"
     "M: quad area [ width>> ] [ height>> ] bi * ;"
     ""
     "TUPLE: rectangle < quad ;"
-    "M: rectangle perimiter [ width>> 2 * ] [ height>> 2 * ] bi + ;"
+    "M: rectangle perimeter [ width>> 2 * ] [ height>> 2 * ] bi + ;"
     ""
     ": hypot ( a b -- c ) [ sq ] bi@ + sqrt ;"
     ""
     "TUPLE: parallelogram < quad skew ;"
-    "M: parallelogram perimiter"
+    "M: parallelogram perimeter"
     "    [ width>> 2 * ] [ [ height>> ] [ skew>> ] bi hypot 2 * ] bi + ;"
 } ;
 
index 6e29b608099dd3d21341afe7a8bbda92a429b1b4..ecfdcf93f196a961af8aa640c1a141aac9204947 100644 (file)
@@ -396,7 +396,7 @@ $nl
 HELP: distribute-buckets
 { $values { "alist" "an alist" } { "initial" object } { "quot" { $quotation "( obj -- assoc )" } } { "buckets" "a new array" } }
 { $description "Sorts the entries of " { $snippet "assoc" } " into buckets, using the quotation to yield a set of keys for each entry. The hashcode of each key is computed, and the entry is placed in all corresponding buckets. Each bucket is initially cloned from " { $snippet "initial" } "; this should either be an empty vector or a one-element vector containing a pair." }
-{ $notes "This word is used in the implemention of " { $link hash-case-quot } " and " { $link standard-combination } "." } ;
+{ $notes "This word is used in the implementation of " { $link hash-case-quot } " and " { $link standard-combination } "." } ;
 
 HELP: dispatch ( n array -- )
 { $values { "n" "a fixnum" } { "array" "an array of quotations" } }
index b553c0c3848dacc3c284ca6da187e68ae29446a9..810f853ef252ff4b86288a158ca46318932bf01b 100644 (file)
@@ -61,7 +61,7 @@ $nl
     "errors-post-mortem"
     "errors-anti-examples"
 }
-"When Factor encouters a critical error, it calls the following word:"
+"When Factor encounters a critical error, it calls the following word:"
 { $subsections die } ;
 
 ARTICLE: "continuations.private" "Continuation implementation details"
index f69cd2a8231b82b6bfc9a411facbb5717ae19000..d3b2c46cc217f8f03a6e115709728e8c11766977 100644 (file)
@@ -94,25 +94,25 @@ M: circle area radius>> sq pi * ;
 [ 12 ] [ 4 3 2 <parallelogram> area ] unit-test
 [ t ] [ 2 <circle> area 4 pi * = ] unit-test
 
-GENERIC: perimiter ( shape -- n )
+GENERIC: perimeter ( shape -- n )
 
-: rectangle-perimiter ( l w -- n ) + 2 * ;
+: rectangle-perimeter ( l w -- n ) + 2 * ;
 
-M: rectangle perimiter
+M: rectangle perimeter
     [ width>> ] [ height>> ] bi
-    rectangle-perimiter ;
+    rectangle-perimeter ;
 
 : hypotenuse ( a b -- c ) [ sq ] bi@ + sqrt ;
 
-M: parallelogram perimiter
+M: parallelogram perimeter
     [ width>> ]
     [ [ height>> ] [ skew>> ] bi hypotenuse ] bi
-    rectangle-perimiter ;
+    rectangle-perimeter ;
 
-M: circle perimiter 2 * pi * ;
+M: circle perimeter 2 * pi * ;
 
-[ 14 ] [ 4 3 <rectangle> perimiter ] unit-test
-[ 30.0 ] [ 10 4 3 <parallelogram> perimiter ] unit-test
+[ 14 ] [ 4 3 <rectangle> perimeter ] unit-test
+[ 30.0 ] [ 10 4 3 <parallelogram> perimeter ] unit-test
 
 PREDICATE: very-funny < funnies number? ;
 
index e0397e2042551dd73034d9b0f0b12a257672bdf0..144e7433c2561fd7889bbec1a0867d7ed8fa4334 100644 (file)
@@ -4,7 +4,7 @@ namespaces assocs ;
 IN: hashtables
 
 ARTICLE: "hashtables.private" "Hashtable implementation details"
-"This hashtable implementation uses only one auxilliary array in addition to the hashtable tuple itself. The array stores keys in even slots and values in odd slots. Values are looked up with a hashing strategy that uses linear probing to resolve collisions."
+"This hashtable implementation uses only one auxiliary array in addition to the hashtable tuple itself. The array stores keys in even slots and values in odd slots. Values are looked up with a hashing strategy that uses linear probing to resolve collisions."
 $nl
 "There are two special objects: the " { $link ((tombstone)) } " marker and the " { $link ((empty)) } " marker. Neither of these markers can be used as hashtable keys."
 $nl
index 1fbd7c64dccd36a7a86105e5198a4c79db97bdb5..892850ad4c2033c94225139b0e582a59df33b200 100644 (file)
@@ -656,14 +656,14 @@ $nl
 } ;
 
 HELP: when*
-{ $values { "?" "a generalized boolean" } { "true" { $quotation "( cond -- ... )" } } }
+{ $values { "?" "a generalized boolean" } { "true" { $quotation "( ..a ? -- ..a )" } } }
 { $description "Variant of " { $link if* } " with no false quotation."
 $nl
 "The following two lines are equivalent:"
 { $code "X [ Y ] when*" "X dup [ Y ] [ drop ] if" } } ;
 
 HELP: unless*
-{ $values { "?" "a generalized boolean" } { "false" "a quotation " } }
+{ $values { "?" "a generalized boolean" } { "false" { $quotation "( ..a -- ..a x )" } } { "x" object } }
 { $description "Variant of " { $link if* } " with no true quotation." }
 { $notes
 "The following two lines are equivalent:"
index 493365db1afa444d133db7dab77c433938bbd756..6ac1ffc5349623a69a0ff4858a51889418a2d04a 100644 (file)
@@ -403,7 +403,7 @@ PRIVATE>
     [ 2drop f f ]
     if ; inline
 
-: (accumulate) ( seq identity quot -- seq identity quot )
+: (accumulate) ( seq identity quot -- identity seq quot )
     [ swap ] dip [ curry keep ] curry ; inline
 
 PRIVATE>
index df6185671c098c015e28d54f0e530b6c8159b586..15b251736b139de04bc66db1c652ac8975daf80e 100644 (file)
@@ -3,68 +3,61 @@
 USING: sets tools.test kernel prettyprint hash-sets sorting ;
 IN: sets.tests
 
-[ { } ] [ { } { } intersect ] unit-test
-[ { 2 3 } ] [ { 1 2 3 } { 2 3 4 } intersect ] unit-test
-[ { 2 3 } ] [ { 1 2 3 } { 2 3 4 5 } intersect ] unit-test
-[ { 2 3 4 } ] [ { 1 2 3 4 } { 2 3 4 } intersect ] unit-test
-[ { 2 3 } ] [ { 1 2 2 3 } { 2 3 3 4 } intersect ] unit-test
+[ V{ 1 2 3 } ] [ 3 V{ 1 2 } clone [ adjoin ] keep ] unit-test
+[ V{ 1 2 } ] [ 2 V{ 1 2 } clone [ adjoin ] keep ] unit-test
 
-[ { } ] [ { } { } diff ] unit-test
-[ { 1 } ] [ { 1 2 3 } { 2 3 4 } diff ] unit-test
-[ { 1 } ] [ { 1 2 3 } { 2 3 4 5 } diff ] unit-test
-[ { 1 } ] [ { 1 2 3 4 } { 2 3 4 } diff ] unit-test
-[ { 1 } ] [ { 1 1 2 3 } { 2 3 4 4 } diff ] unit-test
+[ t ] [ 4 { 2 4 5 } in? ] unit-test
+[ f ] [ 1 { 2 4 5 } in? ] unit-test
 
-[ { } ] [ { } { } within ] unit-test
-[ { 2 3 } ] [ { 1 2 3 } { 2 3 4 } within ] unit-test
-[ { 2 2 3 } ] [ { 1 2 2 3 } { 2 3 3 4 } within ] unit-test
+[ V{ 1 2 } ] [ 3 V{ 1 2 } clone [ delete ] keep ] unit-test
+[ V{ 2 } ] [ 1 V{ 1 2 } clone [ delete ] keep ] unit-test
 
-[ { } ] [ { } { } without ] unit-test
-[ { 1 } ] [ { 1 2 3 } { 2 3 4 } without ] unit-test
-[ { 1 1 } ] [ { 1 1 2 3 3 } { 2 3 4 4 } without ] unit-test
+[ { 1 2 3 } ] [ { 1 1 1 2 2 3 3 3 3 3 } dup set-like natural-sort ] unit-test
+[ { 1 2 3 } ] [ HS{ 1 2 3 } { } set-like natural-sort ] unit-test
+[ { 1 2 3 } ] [ { 1 2 2 3 3 } { } set-like ] unit-test
+[ { 3 2 1 } ] [ { 3 3 2 2 1 } { } set-like ] unit-test
+
+[ HS{ 1 2 3 } ] [ { 1 2 3 } fast-set ] unit-test
+
+[ { 1 } ] [ { 1 } members ] unit-test
 
 [ { } ] [ { } { } union ] unit-test
 [ { 1 2 3 4 } ] [ { 1 2 3 } { 2 3 4 } union ] unit-test
 
-[ t ] [ { 1 2 } { 1 3 } intersects? ] unit-test
+[ { } ] [ { } { } intersect ] unit-test
+[ { 2 3 } ] [ { 1 2 3 } { 2 3 4 } intersect ] unit-test
+[ { 2 3 } ] [ { 1 2 3 } { 2 3 4 5 } intersect ] unit-test
+[ { 2 3 4 } ] [ { 1 2 3 4 } { 2 3 4 } intersect ] unit-test
+[ { 2 3 } ] [ { 1 2 2 3 } { 2 3 3 4 } intersect ] unit-test
 
+[ t ] [ { 1 2 } { 1 3 } intersects? ] unit-test
 [ f ] [ { 4 2 } { 1 3 } intersects? ] unit-test
-
 [ f ] [ { } { 1 } intersects? ] unit-test
-
 [ f ] [ { 1 } { } intersects? ] unit-test
+[ f ] [ { } { } intersects? ] unit-test
 
-[ t ] [ 4 { 2 4 5 } in? ] unit-test
-[ f ] [ 1 { 2 4 5 } in? ] unit-test
+[ { } ] [ { } { } diff ] unit-test
+[ { 1 } ] [ { 1 2 3 } { 2 3 4 } diff ] unit-test
+[ { 1 } ] [ { 1 2 3 } { 2 3 4 5 } diff ] unit-test
+[ { 1 } ] [ { 1 2 3 4 } { 2 3 4 } diff ] unit-test
+[ { 1 } ] [ { 1 1 2 3 } { 2 3 4 4 } diff ] unit-test
 
-[ V{ 1 2 3 } ] [ 3 V{ 1 2 } clone [ adjoin ] keep ] unit-test
-[ V{ 1 2 } ] [ 2 V{ 1 2 } clone [ adjoin ] keep ] unit-test
-[ V{ 1 2 } ] [ 3 V{ 1 2 } clone [ delete ] keep ] unit-test
-[ V{ 2 } ] [ 1 V{ 1 2 } clone [ delete ] keep ] unit-test
+[ f ] [ { 1 2 3 4 } { 1 2 } subset? ] unit-test
+[ t ] [ { 1 2 3 4 } { 1 2 } swap subset? ] unit-test
+[ t ] [ { 1 2 } { 1 2 } subset? ] unit-test
+[ t ] [ { } { 1 2 } subset? ] unit-test
+[ t ] [ { } { } subset? ] unit-test
+[ f ] [ { 1 } { } subset? ] unit-test
 
 [ t ] [ { 1 2 3 } { 2 1 3 } set= ] unit-test
 [ f ] [ { 2 3 } { 1 2 3 } set= ] unit-test
 [ f ] [ { 1 2 3 } { 2 3 } set= ] unit-test
 
-[ { 1 } ] [ { 1 } members ] unit-test
-
-[ { 1 2 3 } ] [ { 1 1 1 2 2 3 3 3 3 3 } dup set-like natural-sort ] unit-test
-[ { 1 2 3 } ] [ HS{ 1 2 3 } { } set-like natural-sort ] unit-test
-
-[ HS{ 1 2 3 } ] [ { 1 2 3 } fast-set ] unit-test
-
-[ { 1 2 3 } ] [ { { 1 } { 2 } { 1 3 } } combine ] unit-test
-
-[ f ] [ { 0 1 1 2 3 5 } all-unique? ] unit-test
-[ t ] [ { 0 1 2 3 4 5 } all-unique? ] unit-test
-
-[ { 1 2 3 } ] [ { 1 2 2 3 3 } { } set-like ] unit-test
-[ { 3 2 1 } ] [ { 3 3 2 2 1 } { } set-like ] unit-test
-
 [ { 2 1 2 1 } ] [ { 1 2 3 2 1 2 1 } duplicates ] unit-test
 [ f ] [ HS{ 1 2 3 1 2 1 } duplicates ] unit-test
 
-[ H{ { 3 HS{ 1 2 } } } ] [ H{ } clone 1 3 pick adjoin-at 2 3 pick adjoin-at ] unit-test
+[ f ] [ { 0 1 1 2 3 5 } all-unique? ] unit-test
+[ t ] [ { 0 1 2 3 4 5 } all-unique? ] unit-test
 
 [ t ] [ f null? ] unit-test
 [ f ] [ { 4 } null? ] unit-test
@@ -74,3 +67,18 @@ IN: sets.tests
 [ 1 ] [ { 1 } cardinality ] unit-test
 [ 1 ] [ HS{ 1 } cardinality ] unit-test
 [ 3 ] [ HS{ 1 2 3 } cardinality ] unit-test
+
+[ { } ] [ { } { } within ] unit-test
+[ { 2 3 } ] [ { 1 2 3 } { 2 3 4 } within ] unit-test
+[ { 2 2 3 } ] [ { 1 2 2 3 } { 2 3 3 4 } within ] unit-test
+
+[ { } ] [ { } { } without ] unit-test
+[ { 1 } ] [ { 1 2 3 } { 2 3 4 } without ] unit-test
+[ { 1 1 } ] [ { 1 1 2 3 3 } { 2 3 4 4 } without ] unit-test
+
+[ { 1 2 3 } ] [ { { 1 } { 2 } { 1 3 } } combine ] unit-test
+
+[ H{ { 3 HS{ 1 2 } } } ] [ H{ } clone 1 3 pick adjoin-at 2 3 pick adjoin-at ] unit-test
+
+[ H{ { 3 H{ { 1 1 } { 2 2 } } } } ] [ H{ } clone 1 3 pick conjoin-at 2 3 pick conjoin-at ] unit-test
+
index 06f6e04655417689af351b0194c2dbfe6635f173..8a84cc597b215dae57825a542cdc0a74dd8bfdc8 100644 (file)
@@ -61,7 +61,7 @@ M: set intersects?
     small/large sequence/tester any? ;
 
 M: set subset?
-    small/large sequence/tester all? ;
+    sequence/tester all? ;
 
 M: set set=
     2dup [ cardinality ] bi@ eq? [ subset? ] [ 2drop f ] if ;
index 120d91bb2269f8165aefda082d3a8b60c1cc0b8a..6807e51515b0b2aed64354b16f21d78c04ccdf56 100644 (file)
@@ -13,7 +13,8 @@ TUPLE: source-file
 path
 top-level-form
 checksum
-definitions ;
+definitions
+main ;
 
 : record-top-level-form ( quot file -- )
     top-level-form<<
index 869543fc0a2cbd71bb463837702ab7840ca5cac0..28e5398bfea48a52f309e2123d148b57652d1398 100644 (file)
@@ -64,12 +64,13 @@ unit-test
 "hello world" "s" set
 
 [ ] [ HEX: 1234 1 "s" get set-nth ] unit-test
+[ HEX: 1234 ] [ 1 "s" get nth ] unit-test
+
 [ ] [ HEX: 4321 3 "s" get set-nth ] unit-test
-[ ] [ HEX: 654321 5 "s" get set-nth ] unit-test
+[ HEX: 4321 ] [ 3 "s" get nth ] unit-test
 
-[ ] [ HEX: -1 5 "s" get set-nth ] unit-test
-[ ] [ HEX: 80,0000 5 "s" get set-nth ] unit-test
-[ ] [ HEX: 100,0000 5 "s" get set-nth ] unit-test
+[ ] [ HEX: 654321 5 "s" get set-nth ] unit-test
+[ HEX: 654321 ] [ 5 "s" get nth ] unit-test
 
 [
     {
@@ -125,3 +126,10 @@ unit-test
         [ <string> clone resize-string first ] keep =
     ] all-integers?
 ] unit-test
+
+"X" "s" set
+[ ] [ HEX: 100,0000 0 "s" get set-nth ] unit-test
+[ 0 ] [ 0 "s" get nth ] unit-test
+
+[ ] [ -1 0 "s" get set-nth ] unit-test
+[ HEX: 7fffff ] [ 0 "s" get nth ] unit-test
index 2afefe1f2bf10cc65431df546de1acf879b8a22d..0472d6394d07a2b673c7e3ab3cfad956716824c0 100644 (file)
@@ -1,7 +1,7 @@
 USING: generic help.syntax help.markup kernel math parser words
 effects classes classes.tuple generic.math generic.single arrays
 io.pathnames vocabs.loader io sequences assocs words.symbol
-words.alias words.constant combinators vocabs.parser ;
+words.alias words.constant combinators vocabs.parser command-line ;
 IN: syntax
 
 ARTICLE: "parser-algorithm" "Parser algorithm"
@@ -858,7 +858,7 @@ HELP: C:
 HELP: MAIN:
 { $syntax "MAIN: word" }
 { $values { "word" word } }
-{ $description "Defines the main entry point for the current vocabulary. This word will be executed when this vocabulary is passed to " { $link run } "." } ;
+{ $description "Defines the main entry point for the current vocabulary and source file. This word will be executed when this vocabulary is passed to " { $link run } " or the source file is passed to " { $link run-script } "." } ;
 
 HELP: <PRIVATE
 { $syntax "<PRIVATE ... PRIVATE>" }
index 07ff0d3c922a99020c39524e9fd14d1ab26a0c8d..864c67d172cbc568a281a46699e049250a5e421a 100644 (file)
@@ -8,7 +8,7 @@ generic.standard generic.hook generic.math generic.parser classes
 io.pathnames vocabs vocabs.parser classes.parser classes.union
 classes.intersection classes.mixin classes.predicate
 classes.singleton classes.tuple.parser compiler.units
-combinators effects.parser slots hash-sets ;
+combinators effects.parser slots hash-sets source-files ;
 IN: bootstrap.syntax
 
 ! These words are defined as a top-level form, instead of with
@@ -233,7 +233,11 @@ IN: bootstrap.syntax
         "))" parse-effect suffix!
     ] define-core-syntax
 
-    "MAIN:" [ scan-word current-vocab main<< ] define-core-syntax
+    "MAIN:" [
+        scan-word
+        [ current-vocab main<< ]
+        [ file get [ main<< ] [ drop ] if* ] bi
+    ] define-core-syntax
 
     "<<" [
         [
diff --git a/extra/anagrams/anagrams.factor b/extra/anagrams/anagrams.factor
new file mode 100644 (file)
index 0000000..f5f87af
--- /dev/null
@@ -0,0 +1,35 @@
+! Copyright (C) 2010 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: arrays ascii assocs fry io.encodings.ascii io.files
+kernel math math.order memoize sequences sorting ;
+
+IN: anagrams
+
+: (all-anagrams) ( seq assoc -- )
+    '[ dup natural-sort _ push-at ] each ;
+
+: all-anagrams ( seq -- assoc )
+    H{ } clone [ (all-anagrams) ] keep
+    [ nip length 1 > ] assoc-filter ;
+
+MEMO: dict-words ( -- seq )
+    "/usr/share/dict/words" ascii file-lines [ >lower ] map ;
+
+MEMO: dict-anagrams ( -- assoc )
+    dict-words all-anagrams ;
+
+: anagrams ( str -- seq/f )
+    >lower natural-sort dict-anagrams at ;
+
+: longest ( seq -- subseq )
+    dup 0 [ length max ] reduce '[ length _ = ] filter ;
+
+: most-anagrams ( -- seq )
+    dict-anagrams values longest ;
+
+: longest-anagrams ( -- seq )
+    dict-anagrams [ keys longest ] keep '[ _ at ] map ;
+
+
+
diff --git a/extra/anagrams/authors.txt b/extra/anagrams/authors.txt
new file mode 100644 (file)
index 0000000..e091bb8
--- /dev/null
@@ -0,0 +1 @@
+John Benediktsson
diff --git a/extra/anagrams/platforms.txt b/extra/anagrams/platforms.txt
new file mode 100644 (file)
index 0000000..509143d
--- /dev/null
@@ -0,0 +1 @@
+unix
diff --git a/extra/benchmark/echo/echo.factor b/extra/benchmark/echo/echo.factor
new file mode 100644 (file)
index 0000000..13ae0d2
--- /dev/null
@@ -0,0 +1,20 @@
+! Copyright (C) 2011 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: accessors destructors kernel io.binary io.sockets
+sequences ;
+
+IN: benchmark.echo
+
+: send/recv ( packet server client -- )
+    [ over over addr>> ] [ send ] bi* receive drop assert= ;
+
+: udp-echo ( -- )
+    [
+        10000 iota [ 4 >be ] map
+        f 0 <inet4> <datagram>
+        f 0 <inet4> <datagram>
+        [ send/recv ] 2curry each
+    ] with-destructors ;
+
+MAIN: udp-echo
index f29e7dc8ae0b3a9df628043236a183a69883b689..859bcc28629faeaced1b637c6979c468674c4b3b 100644 (file)
@@ -1,8 +1,8 @@
 ! Copyright (C) 2009 John Benediktsson
 ! See http://factorcode.org/license.txt for BSD license
 
-USING: accessors assocs fry io io.streams.string kernel macros math 
-peg.ebnf prettyprint quotations sequences strings ;
+USING: accessors assocs fry io io.streams.string kernel macros
+math peg.ebnf prettyprint sequences strings ;
 
 IN: brainfuck
 
@@ -10,7 +10,7 @@ IN: brainfuck
 
 TUPLE: brainfuck pointer memory ;
 
-: <brainfuck> ( -- brainfuck ) 
+: <brainfuck> ( -- brainfuck )
     0 H{ } clone brainfuck boa ;
 
 : get-memory ( brainfuck -- brainfuck value )
@@ -37,31 +37,31 @@ TUPLE: brainfuck pointer memory ;
 : (>) ( brainfuck n -- brainfuck )
     [ dup pointer>> ] dip + >>pointer ;
 
-: (<) ( brainfuck n -- brainfuck ) 
+: (<) ( brainfuck n -- brainfuck )
     [ dup pointer>> ] dip - >>pointer ;
 
-: (#) ( brainfuck -- brainfuck ) 
-    dup 
-    [ "ptr=" write pointer>> pprint ] 
+: (#) ( brainfuck -- brainfuck )
+    dup
+    [ "ptr=" write pointer>> pprint ]
     [ ",mem=" write memory>> pprint nl ] bi ;
 
-: compose-all ( seq -- quot ) 
+: compose-all ( seq -- quot )
     [ ] [ compose ] reduce ;
 
 EBNF: parse-brainfuck
 
-inc-ptr  = (">")+  => [[ length 1quotation [ (>) ] append ]]
-dec-ptr  = ("<")+  => [[ length 1quotation [ (<) ] append ]]
-inc-mem  = ("+")+  => [[ length 1quotation [ (+) ] append ]]
-dec-mem  = ("-")+  => [[ length 1quotation [ (-) ] append ]]
+inc-ptr  = (">")+  => [[ length [ (>) ] curry ]]
+dec-ptr  = ("<")+  => [[ length [ (<) ] curry ]]
+inc-mem  = ("+")+  => [[ length [ (+) ] curry ]]
+dec-mem  = ("-")+  => [[ length [ (-) ] curry ]]
 output   = "."  => [[ [ (.) ] ]]
 input    = ","  => [[ [ (,) ] ]]
 debug    = "#"  => [[ [ (#) ] ]]
-space    = (" "|"\t"|"\r\n"|"\n")+ => [[ [ ] ]] 
+space    = (" "|"\t"|"\r\n"|"\n")+ => [[ [ ] ]]
 unknown  = (.)  => [[ "Invalid input" throw ]]
 
 ops   = inc-ptr|dec-ptr|inc-mem|dec-mem|output|input|debug|space
-loop  = "[" {loop|ops}+ "]" => [[ second compose-all 1quotation [ [ (?) ] ] prepend [ while ] append ]]
+loop  = "[" {loop|ops}+ "]" => [[ second compose-all [ while ] curry [ (?) ] prefix ]]
 
 code  = (loop|ops|unknown)*  => [[ compose-all ]]
 
@@ -72,6 +72,6 @@ PRIVATE>
 MACRO: run-brainfuck ( code -- )
     [ <brainfuck> ] swap parse-brainfuck [ drop flush ] 3append ;
 
-: get-brainfuck ( code -- result ) 
-    [ run-brainfuck ] with-string-writer ; inline 
+: get-brainfuck ( code -- result )
+    [ run-brainfuck ] with-string-writer ; inline
 
index 795ab7496e4fa45716c7438601a0d06454fcecbf..31065c9f3174ba880266700cee1d2feff9140ba8 100644 (file)
@@ -127,9 +127,14 @@ Factor.prototype.using = function(v, next) {
   factor.get_word("kernel", "using").execute(next);
 }
 
+var fjsc_repl = false;
+
 Factor.prototype.set_in = function(v, next) {
   factor.cont.data_stack.push(v);
   factor.get_word("kernel", "set-in").execute(next);
+  if (fjsc_repl) {
+    fjsc_repl.ps = '( ' + v + ' )';
+  }
 }
 
 Factor.prototype.get_word = function(vocab,name) {
index e7b797fc199b811d0a429c0135f56205265e7dc9..b643614226cafd40d38d90b89d800b68ba62a83b 100644 (file)
@@ -1,20 +1,12 @@
 ! Copyright (C) 2009, 2010 Jose Antonio Ortega Ruiz.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: accessors debugger io io.encodings.utf8 io.servers
-kernel listener math namespaces ;
-IN: fuel.remote
 
-<PRIVATE
+USING: accessors io io.encodings.utf8 io.servers kernel math
+namespaces tty-server ;
 
-: start-listener ( -- )
-    [ [ drop print-error-and-restarts ] error-hook set listener ] with-scope ;
+IN: fuel.remote
 
-: server ( port -- server )
-    utf8 <threaded-server>
-        "tty-server" >>name
-        swap local-server >>insecure
-        [ start-listener ] >>handler
-        f >>timeout ;
+<PRIVATE
 
 : print-banner ( -- )
     "Starting server. Connect with 'M-x connect-to-factor' in Emacs"
@@ -23,7 +15,7 @@ IN: fuel.remote
 PRIVATE>
 
 : fuel-start-remote-listener ( port/f -- )
-    print-banner integer? [ 9000 ] unless* server start-server drop ;
+    print-banner integer? [ 9000 ] unless* <tty-server> start-server drop ;
 
 : fuel-start-remote-listener* ( -- ) f fuel-start-remote-listener ;
 
diff --git a/extra/gestalt/authors.txt b/extra/gestalt/authors.txt
new file mode 100644 (file)
index 0000000..e091bb8
--- /dev/null
@@ -0,0 +1 @@
+John Benediktsson
diff --git a/extra/gestalt/gestalt.factor b/extra/gestalt/gestalt.factor
new file mode 100644 (file)
index 0000000..d88ea9e
--- /dev/null
@@ -0,0 +1,53 @@
+! Copyright (C) 2011 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: alien.data alien.syntax combinators core-foundation
+formatting io.binary kernel math ;
+
+IN: gestalt
+
+<PRIVATE
+
+TYPEDEF: SInt16 OSErr
+
+TYPEDEF: UInt32 OSType
+
+FUNCTION: OSErr Gestalt ( OSType selector, SInt32* response ) ;
+
+PRIVATE>
+
+: gestalt ( selector -- response )
+    0 SInt32 <ref> [ Gestalt ] keep
+    swap [ throw ] unless-zero le> ;
+
+: system-version ( -- n )
+    "sysv" be> gestalt ;
+
+: system-version-major ( -- n )
+    "sys1" be> gestalt ;
+
+: system-version-minor ( -- n )
+    "sys2" be> gestalt ;
+
+: system-version-bugfix ( -- n )
+    "sys3" be> gestalt ;
+
+: system-version-string ( -- str )
+    system-version-major
+    system-version-minor
+    system-version-bugfix
+    "%s.%s.%s" sprintf ;
+
+: system-code-name ( -- str )
+    system-version HEX: FFF0 bitand {
+        { HEX: 1070 [ "Lion"         ] }
+        { HEX: 1060 [ "Snow Leopard" ] }
+        { HEX: 1050 [ "Leopard"      ] }
+        { HEX: 1040 [ "Tiger"        ] }
+        { HEX: 1030 [ "Panther"      ] }
+        { HEX: 1020 [ "Jaguar"       ] }
+        { HEX: 1010 [ "Puma"         ] }
+        { HEX: 1000 [ "Cheetah"      ] }
+        [ drop "Unknown" ]
+    } case ;
+
diff --git a/extra/gestalt/platforms.txt b/extra/gestalt/platforms.txt
new file mode 100644 (file)
index 0000000..6e806f4
--- /dev/null
@@ -0,0 +1 @@
+macosx
index f7d89c905030e2bf001bec5836a6abf7edba06eb..d5b88c244b953bbaba8dfdf5190b0d882f9576c0 100644 (file)
@@ -242,7 +242,7 @@ CONSTANT: google-slides
     { $slide "Unicode strings"
         "Strings are sequences of 21-bit Unicode code points"
         "Efficient implementation: ASCII byte string unless it has chars > 127"
-        "If a byte char has high bit set, the remaining 14 bits come from auxilliary vector"
+        "If a byte char has high bit set, the remaining 14 bits come from auxiliary vector"
     }
     { $slide "Unicode strings"
         "Unicode-aware case conversion, char classes, collation, word breaks, and so on..."
diff --git a/extra/google/charts/authors.txt b/extra/google/charts/authors.txt
new file mode 100644 (file)
index 0000000..e091bb8
--- /dev/null
@@ -0,0 +1 @@
+John Benediktsson
diff --git a/extra/google/charts/charts.factor b/extra/google/charts/charts.factor
new file mode 100644 (file)
index 0000000..d97a97b
--- /dev/null
@@ -0,0 +1,105 @@
+! Copyright (C) 2011 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: accessors arrays assocs colors.hex combinators formatting
+http.client images.http images.loader images.loader.private
+images.viewer kernel math math.order present sequences splitting
+urls ;
+
+IN: google.charts
+
+TUPLE: chart type width height title data data-scale labels
+background foreground margin bar-width ;
+
+: <chart> ( type -- chart )
+    chart new
+        swap >>type
+        320 >>width
+        240 >>height ;
+
+<PRIVATE
+
+: x,y ( seq -- str ) [ present ] map "," join ;
+
+: x|y ( seq -- str ) [ present ] map "|" join ;
+
+: chd ( chart seq -- chart )
+    [ x,y >>data ] [
+        [ infimum 0 min ] [ supremum 0 max ] bi 2array
+        x,y >>data-scale
+    ] bi ;
+
+: chl ( chart seq -- chart ) x|y >>labels ;
+
+: chd/chl ( chart assoc -- chart )
+    [ values chd ] [ keys chl ] bi ;
+
+PRIVATE>
+
+: <pie> ( assoc -- chart )
+    [ "p" <chart> ] dip chd/chl ;
+
+: <pie-3d> ( assoc -- chart )
+    [ "p3" <chart> ] dip chd/chl ;
+
+: <bar> ( assoc -- chart )
+    [ "bvs" <chart> ] dip chd/chl ;
+
+: <line> ( seq -- chart )
+    [ "lc" <chart> ] dip chd ;
+
+: <line-xy> ( seq -- chart )
+    [ "lxy" <chart> ] dip [ keys ] [ values ] bi
+    [ x,y ] bi@ "|" glue >>data ;
+
+: <scatter> ( seq -- chart )
+    [ "s" <chart> ] dip [ keys ] [ values ] bi
+    [ x,y ] bi@ "|" glue >>data ;
+
+: <sparkline> ( seq -- chart )
+    [ "ls" <chart> ] dip chd ;
+
+: <radar> ( seq -- chart )
+    [ "rs" <chart> ] dip chd ;
+
+: <qr-code> ( str -- chart )
+    [ "qr" <chart> ] dip 1array chl ;
+
+: <formula> ( str -- chart )
+    [ "tx" <chart> ] dip 1array chl f >>width f >>height ;
+
+<PRIVATE
+
+: chart>url ( chart -- url )
+    [ URL" http://chart.googleapis.com/chart" ] dip {
+        [ type>> "cht" set-query-param ]
+        [
+            [ width>> ] [ height>> ] bi 2dup and [
+                "%sx%s" sprintf "chs" set-query-param
+            ] [ 2drop ] if
+        ]
+        [ title>> "chtt" set-query-param ]
+        [ data>> "t:" prepend "chd" set-query-param ]
+        [ data-scale>> [ "chds" set-query-param ] when* ]
+        [ labels>> "chl" set-query-param ]
+        [
+            background>> [
+                rgba>hex "bg,s," prepend "chf" set-query-param
+            ] when*
+        ]
+        [
+            foreground>> [
+                rgba>hex "chco" set-query-param
+            ] when*
+        ]
+        [ margin>> [ x,y "chma" set-query-param ] when* ]
+        [ bar-width>> [ "chbh" set-query-param ] when* ]
+    } cleave ;
+
+PRIVATE>
+
+: chart. ( chart -- )
+    chart>url present dup length 2000 < [ http-image. ] [
+        "?" split1 swap http-post nip
+        "png" (image-class) load-image* image.
+    ] if ;
diff --git a/extra/google/charts/summary.txt b/extra/google/charts/summary.txt
new file mode 100644 (file)
index 0000000..574659f
--- /dev/null
@@ -0,0 +1 @@
+Google Chart API
diff --git a/extra/google/translate/authors.txt b/extra/google/translate/authors.txt
new file mode 100644 (file)
index 0000000..7c1b2f2
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
diff --git a/extra/google/translate/translate.factor b/extra/google/translate/translate.factor
new file mode 100644 (file)
index 0000000..61bea20
--- /dev/null
@@ -0,0 +1,55 @@
+! Copyright (C) 2010 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: assocs combinators fry grouping http.client io
+json.reader kernel locals namespaces sequences ;
+IN: google.translate
+
+CONSTANT: google-translate-url "http://ajax.googleapis.com/ajax/services/language/translate"
+
+CONSTANT: maximum-translation-size 5120
+
+: parameters>assoc ( text from to -- assoc )
+    "|" glue [
+        [ "q" set ] [ "langpair" set ] bi*
+        "1.0" "v" set
+    ] { } make-assoc ;
+
+: assoc>query-response ( assoc -- response )
+    google-translate-url http-post nip ;
+
+ERROR: response-error response error ;
+
+: throw-response-error ( response -- * )
+    "responseDetails" over at response-error ;
+
+: check-response ( response -- response )
+    "responseStatus" over at {
+        { 200 [ ] }
+        { 400 [ throw-response-error ] }
+        [ drop throw-response-error ]
+    } case ;
+
+: query-response>text ( response -- text )
+    json> check-response
+    "responseData" swap at
+    "translatedText" swap at ;
+
+: (translate) ( text from to -- text' )
+    parameters>assoc
+    assoc>query-response
+    query-response>text ;
+
+: translate ( text from to -- text' )
+    [ maximum-translation-size group ] 2dip
+    '[ _ _ (translate) ] map concat ;
+
+:: translation-party ( text source target -- )
+    text dup print [
+        dup source target translate dup print
+        target source translate dup print
+        swap dupd = not
+    ] loop drop ;
+
+! Example:
+! "dog" "en" "de" translate .
+! "Hund"
diff --git a/extra/hamurabi/authors.txt b/extra/hamurabi/authors.txt
new file mode 100644 (file)
index 0000000..e091bb8
--- /dev/null
@@ -0,0 +1 @@
+John Benediktsson
diff --git a/extra/hamurabi/hamurabi.factor b/extra/hamurabi/hamurabi.factor
new file mode 100644 (file)
index 0000000..d0d7291
--- /dev/null
@@ -0,0 +1,251 @@
+! Copyright (C) 2010 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: accessors combinators combinators.short-circuit
+continuations formatting fry io kernel math math.functions
+math.order math.parser math.ranges random sequences strings ;
+
+IN: hamurabi
+
+<PRIVATE
+
+TUPLE: game year population births deaths stores harvest yield
+plague acres eaten cost feed planted birth-factor rat-factor
+total-births total-deaths ;
+
+: <game> ( -- game )
+    game new
+        0 >>year
+        95 >>population
+        5 >>births
+        0 >>deaths
+        2800 >>stores
+        3000 >>harvest
+        3 >>yield
+        f >>plague
+        0 >>cost
+    dup births>> >>total-births
+    dup deaths>> >>total-deaths
+    dup births>> '[ _ + ] change-population
+    dup [ harvest>> ] [ yield>> ] bi / >>acres
+    dup [ harvest>> ] [ stores>> ] bi - >>eaten ;
+
+: #acres-available ( game -- n )
+    [ stores>> ] [ cost>> ] bi /i ;
+
+: #acres-per-person ( game -- n )
+    [ acres>> ] [ population>> ] bi / ;
+
+: #harvested ( game -- n )
+    [ planted>> ] [ yield>> ] bi * ;
+
+: #eaten ( game -- n )
+    dup rat-factor>> odd?
+    [ [ stores>> ] [ rat-factor>> ] bi / ] [ drop 0 ] if ;
+
+: #stored ( game -- n )
+    [ harvest>> ] [ eaten>> ] bi - ;
+
+: #percent-died ( game -- n )
+    [ total-deaths>> 100 * ] [ total-births>> ] [ year>> ] tri / / ;
+
+: #births ( game -- n )
+    {
+        [ acres>> 20 * ]
+        [ stores>> + ]
+        [ birth-factor>> * ]
+        [ population>> / ]
+    } cleave 100 /i 1 + ;
+
+: #starved ( game -- n )
+    [ population>> ] [ feed>> 20 /i ] bi - 0 max ;
+
+: leave-fink ( -- )
+    "DUE TO THIS EXTREME MISMANAGEMENT YOU HAVE NOT ONLY" print
+    "BEEN IMPEACHED AND THROWN OUT OF OFFICE BUT YOU HAVE" print
+    "ALSO BEEN DECLARED 'NATIONAL FINK' !!" print ;
+
+: leave-starved ( game -- game )
+    dup deaths>> "YOU STARVED %d PEOPLE IN ONE YEAR!!!\n" printf
+    leave-fink "exit" throw ;
+
+: leave-nero ( -- )
+    "YOUR HEAVY-HANDED PERFORMANCE SMACKS OF NERO AND IVAN IV." print
+    "THE PEOPLE (REMAINING) FIND YOU AN UNPLEASANT RULER, AND" print
+    "FRANKLY, HATE YOUR GUTS!" print ;
+
+: leave-not-too-bad ( game -- game )
+    "YOUR PERFORMANCE COULD HAVE BEEN SOMEWHAT BETTER, BUT" print
+    "REALLY WASN'T TOO BAD AT ALL." print
+    dup population>> 4/5 * floor [0,b] random
+    "%d PEOPLE WOULD DEARLY LIKE TO SEE YOU ASSASSINATED\n" printf
+    "BUT WE ALL HAVE OUR TRIVIAL PROBLEMS" print ;
+
+: leave-best ( -- )
+    "A FANTASTIC PERFORMANCE!!!  CHARLEMANGE, DISRAELI, AND" print
+    "JEFFERSON COMBINED COULD NOT HAVE DONE BETTER!" print ;
+
+: leave ( game -- )
+    dup [ #percent-died ] [ #acres-per-person ] bi
+    {
+        { [ 2dup [ 33 > ] [ 7 < ] bi* or ] [ leave-fink ] }
+        { [ 2dup [ 10 > ] [ 9 < ] bi* or ] [ leave-nero ] }
+        { [ 2dup [ 3 > ] [ 10 < ] bi* or ] [ leave-not-too-bad ] }
+        [ leave-best ]
+    } cond 3drop ;
+
+: check-number ( n -- )
+    { [ f eq? ] [ 0 < ] [ fixnum? not ] } 1|| [
+        "HAMURABI:  I CANNOT DO WHAT YOU WISH." print
+        "GET YOURSELF ANOTHER STEWARD!!!!!" print
+        "exit" throw
+    ] when ;
+
+: input ( prompt -- n/f )
+    write flush readln string>number [ check-number ] keep ;
+
+: bad-stores ( game -- )
+    stores>>
+    "HAMURABI:  THINK AGAIN. YOU HAVE ONLY" print
+    "%d BUSHELS OF STORES. NOW THEN," printf nl ;
+
+: bad-acres ( game -- )
+    acres>>
+    "HAMURABI:  THINK AGAIN. YOU ONLY OWN %d ACRES. NOW THEN,"
+    printf nl ;
+
+: bad-population ( game -- )
+    population>>
+    "BUT YOU HAVE ONLY %d PEOPLE TO TEND THE FIELDS. NOW THEN,"
+    printf nl ;
+
+: check-error ( game n error -- game n ? )
+    {
+        { "acres" [ over bad-acres t ] }
+        { "stores" [ over bad-stores t ] }
+        { "population" [ over bad-population t ] }
+        [ drop f ]
+    } case ;
+
+: adjust-acres ( game n -- game )
+    [ '[ _ + ] change-acres ]
+    [ over cost>> * '[ _ - ] change-stores ] bi ;
+
+: buy-acres ( game -- game )
+    "HOW MANY ACRES DO YOU WISH TO BUY? " input
+    over #acres-available dupd > "stores" and check-error
+    [ drop buy-acres ] [ adjust-acres ] if ;
+
+: sell-acres ( game -- game )
+    "HOW MANY ACRES DO YOU WISH TO SELL? " input
+    over acres>> dupd >= "acres" and check-error
+    [ drop sell-acres ] [ neg adjust-acres ] if nl ;
+
+: trade-land ( game -- game )
+    dup cost>> "LAND IS TRADING AT %d BUSHELS PER ACRE.\n" printf
+    buy-acres sell-acres ;
+
+: feed-people ( game -- game )
+    "HOW MANY BUSHELS DO YOU WISH TO FEED YOUR PEOPLE? " input
+    over stores>> dupd > "stores" and check-error
+    [ drop feed-people ] [
+        [ >>feed ] [ '[ _ - ] change-stores ] bi
+    ] if nl ;
+
+: plant-seeds ( game -- game )
+    "HOW MANY ACRES DO YOU WISH TO PLANT WITH SEED? " input {
+        { [ over acres>> dupd > ] [ "acres" ] }
+        { [ over stores>> 2 * dupd > ] [ "stores" ] }
+        { [ over population>> 10 * dupd > ] [ "population" ] }
+        [ f ]
+    } cond check-error [ drop plant-seeds ] [
+        [ >>planted ] [ 2/ '[ _ - ] change-stores ] bi
+    ] if nl ;
+
+: report-status ( game -- game )
+    "HAMURABI:  I BEG TO REPORT TO YOU," print
+    dup [ year>> ] [ deaths>> ] [ births>> ] tri
+    "IN YEAR %d, %d PEOPLE STARVED, %d CAME TO THE CITY\n" printf
+    dup plague>> [
+        "A HORRIBLE PLAGUE STRUCK!  HALF THE PEOPLE DIED." print
+    ] when
+    dup population>> "POPULATION IS NOW %d.\n" printf
+    dup acres>> "THE CITY NOW OWNS %d ACRES.\n" printf
+    dup yield>> "YOU HARVESTED %d BUSHELS PER ACRE.\n" printf
+    dup eaten>> "RATS ATE %d BUSHELS.\n" printf
+    dup stores>> "YOU NOW HAVE %d BUSHELS IN STORE.\n\n" printf ;
+
+: update-randomness ( game -- game )
+    17 26 [a,b] random >>cost
+    5 [1,b] random >>yield
+    5 [1,b] random >>birth-factor
+    5 [1,b] random >>rat-factor
+    100 random 15 < >>plague ;
+
+: update-stores ( game -- game )
+    dup #harvested >>harvest
+    dup #eaten >>eaten
+    dup #stored '[ _ + ] change-stores ;
+
+: update-births ( game -- game )
+    dup #births
+    [ >>births ]
+    [ '[ _ + ] change-total-births ]
+    [ '[ _ + ] change-population ] tri ;
+
+: update-deaths ( game -- game )
+    dup #starved
+    [ >>deaths ]
+    [ '[ _ + ] change-total-deaths ]
+    [ '[ _ - ] change-population ] tri ;
+
+: check-plague ( game -- game )
+    dup plague>> [ [ 2/ ] change-population ] when ;
+
+: check-starvation ( game -- game )
+    dup [ deaths>> ] [ population>> 0.45 * ] bi >
+    [ leave-starved ] when ;
+
+: year ( game -- game )
+    [ 1 + ] change-year
+    report-status
+    update-randomness
+    trade-land
+    feed-people
+    plant-seeds
+    update-stores
+    update-births
+    update-deaths
+    check-plague
+    check-starvation ;
+
+: spaces ( n -- )
+    CHAR: \s <string> write ;
+
+: welcome ( -- )
+    32 spaces "HAMURABI" print
+    15 spaces "CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY" print
+    nl nl nl
+    "TRY YOUR HAND AT GOVERNING ANCIENT SUMERIA" print
+    "SUCCESSFULLY FOR A TEN-YEAR TERM OF OFFICE" print nl ;
+
+: finish ( game -- )
+    dup #percent-died
+    "IN YOUR 10-YEAR TERM OF OFFICE, %d PERCENT OF THE\n" printf
+    "POPULATION STARVED PER YEAR ON AVERAGE, I.E., A TOTAL OF" print
+    dup total-deaths>> "%d PEOPLE DIED!!\n" printf
+    "YOU STARTED WITH 10 ACRES PER PERSON AND ENDED WITH" print
+    dup #acres-per-person "%d ACRES PER PERSON\n" printf
+    nl leave nl "SO LONG FOR NOW." print ;
+
+PRIVATE>
+
+! FIXME: "exit" throw is used to break early, perhaps use bool?
+
+: hamurabi ( -- )
+    welcome <game> [
+        10 [ year ] times finish
+    ] [ 2drop ] recover ;
+
+MAIN: hamurabi
+
diff --git a/extra/hamurabi/summary.txt b/extra/hamurabi/summary.txt
new file mode 100644 (file)
index 0000000..8bc7b6d
--- /dev/null
@@ -0,0 +1 @@
+Port of the HAMURABI.BAS game
index 4e1b00527697b5c9a9882f797387c160a449a85b..02880071146340d91ef47fe1950d247606803221 100644 (file)
@@ -72,7 +72,7 @@ ARTICLE: "images.viewer" "Displaying Images"
 "The " { $vocab-link "images.viewer" } " vocabulary uses the " { $vocab-link "opengl.textures" }
 " vocabulary to display any instance of " { $link image } "."$nl
 "An " { $link image-gadget } " can be used for static images and " { $instance image-control }
-" for changing images (for example a video feed). For changing images, the image should be containted in " { $instance model }
+" for changing images (for example a video feed). For changing images, the image should be contained in " { $instance model }
 ". Change the model value with " { $link set-model } " or mutate the image and call "
 { $link notify-connections } " when you want to update the image. To stop refreshing the image, call " { $link stop-control } "."
 " To start refreshing again, call " { $link start-control } "."
diff --git a/extra/ini-file/authors.txt b/extra/ini-file/authors.txt
new file mode 100644 (file)
index 0000000..e091bb8
--- /dev/null
@@ -0,0 +1 @@
+John Benediktsson
diff --git a/extra/ini-file/ini-file-docs.factor b/extra/ini-file/ini-file-docs.factor
new file mode 100644 (file)
index 0000000..c108dff
--- /dev/null
@@ -0,0 +1,36 @@
+! Copyright (C) 2010 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: assocs hashtables help.syntax help.markup io strings ;
+
+IN: ini-file
+
+HELP: read-ini
+{ $values { "assoc" assoc } }
+{ $description
+    "Reads and parses an INI configuration from the " { $link input-stream }
+    " and returns the result as a nested " { $link hashtable }
+    "."
+} ;
+
+HELP: write-ini
+{ $values { "assoc" assoc } }
+{ $description
+    "Writes a configuration to the " { $link output-stream }
+    " in the INI format."
+} ;
+
+HELP: string>ini
+{ $values { "str" string } { "assoc" assoc } }
+{ $description
+    "Parses the specified " { $link string } " as an INI configuration"
+    " and returns the result as a nested " { $link hashtable }
+    "."
+} ;
+
+HELP: ini>string
+{ $values { "assoc" assoc } { "str" string } }
+{ $description
+    "Encodes the specified " { $link hashtable } " as an INI configuration."
+} ;
+
diff --git a/extra/ini-file/ini-file-tests.factor b/extra/ini-file/ini-file-tests.factor
new file mode 100644 (file)
index 0000000..072ae6e
--- /dev/null
@@ -0,0 +1,131 @@
+! Copyright (C) 2010 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: ini-file tools.test ;
+
+IN: ini-file.tests
+
+[ H{ } ] [ "" string>ini ] unit-test
+
+[ H{ { "section" H{ } } } ] [ "[section]" string>ini ] unit-test
+
+[ H{ { "section" H{ } } } ] [ "[\"section\" ]" string>ini ] unit-test
+
+[ H{ { "   some name with spaces " H{ } } } ]
+[ "[ \"   some name with spaces \"]" string>ini ] unit-test
+
+[ H{ { "[]" H{ } } } ] [ "[\\[\\]]" string>ini ] unit-test
+
+[ H{ { "foo" "bar" } } ] [ "foo=bar" string>ini ] unit-test
+
+[ H{ { "foo" "bar" } { "baz" "quz" } } ]
+[ "foo=bar\nbaz= quz" string>ini ] unit-test
+
+[ H{ { "section" H{ { "foo" "abc def" } } } } ]
+[
+    """
+    [section]
+    foo = abc def
+    """ string>ini
+] unit-test
+
+[ H{ { "section" H{ { "foo" "abc def" } } } } ]
+[
+    """
+    [section]
+    foo = abc    \\
+          "def"
+    """ string>ini
+] unit-test
+
+[ H{ { "section" H{ { "foo" "abc def" } } } } ]
+[
+    """
+    [section]
+    foo = "abc " \\
+          def
+    """ string>ini
+] unit-test
+
+[ H{ { "section" H{ { "foo" "abc def" } } } } ]
+[
+    """
+    [section]   foo = "abc def"
+    """ string>ini
+] unit-test
+
+[ H{ { "section" H{ { "foo" "abc def" } } } } ]
+[
+    """
+    [section]   foo = abc \\
+    "def"
+    """ string>ini
+] unit-test
+
+[ H{ { "section" H{ { "foo" "" } } } } ]
+[
+    """
+    [section]
+    foo=
+    """ string>ini
+] unit-test
+
+[ H{ { "section" H{ { "foo" "" } } } } ]
+[
+    """
+    [section]
+    foo
+    """ string>ini
+] unit-test
+
+[ H{ { "" H{ { "" "" } } } } ]
+[
+    """
+    []
+    =
+    """ string>ini
+] unit-test
+
+[ H{ { "owner" H{ { "name" "John Doe" }
+                  { "organization" "Acme Widgets Inc." } } }
+     { "database" H{ { "server" "192.0.2.62" }
+                     { "port" "143" }
+                     { "file" "payroll.dat" } } } } ]
+[
+    """
+    ; last modified 1 April 2001 by John Doe
+    [owner]
+    name=John Doe
+    organization=Acme Widgets Inc.
+
+    [database]
+    server=192.0.2.62     ; use IP address in case network name resolution is not working
+    port=143
+    file = "payroll.dat"
+    """ string>ini
+] unit-test
+
+[ H{ { "a long section name"
+       H{ { "a long key name" "a long value name" } } } } ]
+[
+    """
+    [a long section name ]
+    a long key name=  a long value name
+    """ string>ini
+] unit-test
+
+[ H{ { "key with \n esc\ape \r codes \""
+       "value with \t esc\ape codes" } } ]
+[
+    """
+    key with \\n esc\\ape \\r codes \\\" = value with \\t esc\\ape codes
+    """ string>ini
+] unit-test
+
+
+[ """key with \\n esc\\ape \\r codes \\\"=value with \\t esc\\ape codes\n""" ]
+[
+    H{ { "key with \n esc\ape \r codes \""
+         "value with \t esc\ape codes" } } ini>string
+] unit-test
+
diff --git a/extra/ini-file/ini-file.factor b/extra/ini-file/ini-file.factor
new file mode 100644 (file)
index 0000000..51a309b
--- /dev/null
@@ -0,0 +1,149 @@
+! Copyright (C) 2010 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: arrays assocs combinators combinators.short-circuit
+formatting hashtables io io.streams.string kernel make math
+namespaces quoting sequences splitting strings strings.parser ;
+
+IN: ini-file
+
+<PRIVATE
+
+: escape ( ch -- ch' )
+    H{
+        { CHAR: a   CHAR: \a }
+        { CHAR: b   HEX: 08 } ! \b
+        { CHAR: f   HEX: 0c } ! \f
+        { CHAR: n   CHAR: \n }
+        { CHAR: r   CHAR: \r }
+        { CHAR: t   CHAR: \t }
+        { CHAR: v   HEX: 0b } ! \v
+        { CHAR: '   CHAR: ' }
+        { CHAR: "   CHAR: " }
+        { CHAR: \\  CHAR: \\ }
+        { CHAR: ?   CHAR: ? }
+        { CHAR: ;   CHAR: ; }
+        { CHAR: [   CHAR: [ }
+        { CHAR: ]   CHAR: ] }
+        { CHAR: =   CHAR: = }
+    } ?at [ bad-escape ] unless ;
+
+: (unescape-string) ( str -- )
+    CHAR: \\ over index [
+        cut-slice [ % ] dip rest-slice
+        dup empty? [ "Missing escape code" throw ] when
+        unclip-slice escape , (unescape-string)
+    ] [ % ] if* ;
+
+: unescape-string ( str -- str' )
+    [ (unescape-string) ] "" make ;
+
+USE: xml.entities
+
+: escape-string ( str -- str' )
+    H{
+        { CHAR: \a   "\\a"  }
+        { HEX: 08    "\\b"  }
+        { HEX: 0c    "\\f"  }
+        { CHAR: \n   "\\n"  }
+        { CHAR: \r   "\\r"  }
+        { CHAR: \t   "\\t"  }
+        { HEX: 0b    "\\v"  }
+        { CHAR: '    "\\'"  }
+        { CHAR: "    "\\\"" }
+        { CHAR: \\   "\\\\" }
+        { CHAR: ?    "\\?"  }
+        { CHAR: ;    "\\;"  }
+        { CHAR: [    "\\["  }
+        { CHAR: ]    "\\]"  }
+        { CHAR: =    "\\="  }
+    } escape-string-by ;
+
+: space? ( ch -- ? )
+    {
+        [ CHAR: \s = ]
+        [ CHAR: \t = ]
+        [ CHAR: \n = ]
+        [ CHAR: \r = ]
+        [ HEX: 0c = ] ! \f
+        [ HEX: 0b = ] ! \v
+    } 1|| ;
+
+: unspace ( str -- str' )
+    [ space? ] trim ;
+
+: unwrap ( str -- str' )
+    1 swap [ length 1 - ] keep subseq ;
+
+: uncomment ( str -- str' )
+    ";#" [ over index [ head ] when* ] each ;
+
+: cleanup-string ( str -- str' )
+    unspace unquote unescape-string ;
+
+SYMBOL: section
+SYMBOL: option
+
+: section? ( line -- index/f )
+    {
+        [ length 1 > ]
+        [ first CHAR: [ = ]
+        [ CHAR: ] swap last-index ]
+    } 1&& ;
+
+: line-continues? ( line -- ? )
+    { [ empty? not ] [ last CHAR: \ = ] } 1&& ;
+
+: section, ( -- )
+    section get [ , ] when* ;
+
+: option, ( name value -- )
+    section get [ second swapd set-at ] [ 2array , ] if* ;
+
+: [section] ( line -- )
+    unwrap cleanup-string H{ } clone 2array section set ;
+
+: name=value ( line -- )
+    option [
+        [ swap [ first2 ] dip ] [
+            "=" split1 [ cleanup-string "" ] [ "" or ] bi*
+        ] if*
+        dup line-continues? [
+            dup length 1 - head cleanup-string
+            dup last space? [ " " append ] unless append 2array
+        ] [
+            cleanup-string append option, f
+        ] if
+    ] change ;
+
+: parse-line ( line -- )
+    uncomment unspace dup section? [
+        section, 1 + cut [ [section] ] [ unspace ] bi*
+    ] when* [ name=value ] unless-empty ;
+
+PRIVATE>
+
+: read-ini ( -- assoc )
+    section off option off
+    [ [ parse-line ] each-line section, ] { } make
+    >hashtable ;
+
+: write-ini ( assoc -- )
+    [
+        dup string?
+        [ [ escape-string ] bi@ "%s=%s\n" printf ]
+        [
+            [ escape-string "[%s]\n" printf ] dip
+            [ [ escape-string ] bi@ "%s=%s\n" printf ]
+            assoc-each nl
+        ] if
+    ] assoc-each ;
+
+! FIXME: escaped comments "\;" don't work
+
+: string>ini ( str -- assoc )
+    [ read-ini ] with-string-reader ;
+
+: ini>string ( assoc -- str )
+    [ write-ini ] with-string-writer ;
+
diff --git a/extra/ini-file/summary.txt b/extra/ini-file/summary.txt
new file mode 100644 (file)
index 0000000..7566fd3
--- /dev/null
@@ -0,0 +1 @@
+Parses INI configuration files.
diff --git a/extra/io/files/trash/authors.txt b/extra/io/files/trash/authors.txt
new file mode 100644 (file)
index 0000000..e091bb8
--- /dev/null
@@ -0,0 +1 @@
+John Benediktsson
diff --git a/extra/io/files/trash/macosx/macosx.factor b/extra/io/files/trash/macosx/macosx.factor
new file mode 100644 (file)
index 0000000..42a1509
--- /dev/null
@@ -0,0 +1,65 @@
+! Copyright (C) 2010 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: alien.c-types alien.strings alien.syntax classes.struct
+core-foundation io.encodings.utf8 io.files.trash kernel system ;
+
+IN: io.files.trash.macosx
+
+<PRIVATE
+
+STRUCT: FSRef
+    { hidden UInt8[80] } ;
+
+TYPEDEF: SInt32 OSStatus
+
+TYPEDEF: UInt32 OptionBits
+
+CONSTANT: noErr 0
+
+CONSTANT: kFSFileOperationDefaultOptions HEX: 00
+CONSTANT: kFSFileOperationOverwrite HEX: 01
+CONSTANT: kFSFileOperationSkipSourcePermissionErrors HEX: 02
+CONSTANT: kFSFileOperationDoNotMoveAcrossVolumes HEX: 04
+CONSTANT: kFSFileOperationSkipPreflight HEX: 08
+
+CONSTANT: kFSPathMakeRefDefaultOptions HEX: 00
+CONSTANT: kFSPathMakeRefDoNotFollowLeafSymlink HEX: 01
+
+FUNCTION: OSStatus FSMoveObjectToTrashSync (
+    FSRef* source,
+    FSRef* target,
+    OptionBits options
+) ;
+
+FUNCTION: char* GetMacOSStatusCommentString (
+    OSStatus err
+) ;
+
+FUNCTION: OSStatus FSPathMakeRefWithOptions (
+    UInt8* path,
+    OptionBits options,
+    FSRef* ref,
+    Boolean* isDirectory
+) ;
+
+: check-err ( err -- )
+    dup noErr = [ drop ] [
+        GetMacOSStatusCommentString utf8 alien>string throw
+    ] if ;
+
+! FIXME: check isDirectory?
+
+: <fs-ref> ( path -- fs-ref )
+    utf8 string>alien
+    kFSPathMakeRefDoNotFollowLeafSymlink
+    FSRef <struct>
+    [ f FSPathMakeRefWithOptions check-err ] keep ;
+
+PRIVATE>
+
+M: macosx send-to-trash ( path -- )
+    <fs-ref> f kFSFileOperationDefaultOptions
+    FSMoveObjectToTrashSync check-err ;
+
+
diff --git a/extra/io/files/trash/macosx/platforms.txt b/extra/io/files/trash/macosx/platforms.txt
new file mode 100644 (file)
index 0000000..6e806f4
--- /dev/null
@@ -0,0 +1 @@
+macosx
diff --git a/extra/io/files/trash/summary.txt b/extra/io/files/trash/summary.txt
new file mode 100644 (file)
index 0000000..b8c0053
--- /dev/null
@@ -0,0 +1 @@
+Send files to the trash bin.
diff --git a/extra/io/files/trash/trash-docs.factor b/extra/io/files/trash/trash-docs.factor
new file mode 100644 (file)
index 0000000..1652d9e
--- /dev/null
@@ -0,0 +1,12 @@
+! Copyright (C) 2010 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: help.markup help.syntax io.files.trash ;
+
+IN: io.files.trash
+
+HELP: send-to-trash
+{ $values { "path" "a file path" } }
+{ $description
+    "Send a file path to the trash bin."
+} ;
diff --git a/extra/io/files/trash/trash.factor b/extra/io/files/trash/trash.factor
new file mode 100644 (file)
index 0000000..2539fc9
--- /dev/null
@@ -0,0 +1,15 @@
+! Copyright (C) 2010 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: combinators system vocabs.loader ;
+
+IN: io.files.trash
+
+HOOK: send-to-trash os ( path -- )
+
+{
+    { [ os macosx? ] [ "io.files.trash.macosx"  ] }
+    { [ os unix?   ] [ "io.files.trash.unix"    ] }
+    { [ os winnt?  ] [ "io.files.trash.windows" ] }
+} cond require
+
diff --git a/extra/io/files/trash/unix/platforms.txt b/extra/io/files/trash/unix/platforms.txt
new file mode 100644 (file)
index 0000000..509143d
--- /dev/null
@@ -0,0 +1 @@
+unix
diff --git a/extra/io/files/trash/unix/unix.factor b/extra/io/files/trash/unix/unix.factor
new file mode 100644 (file)
index 0000000..e8b8489
--- /dev/null
@@ -0,0 +1,83 @@
+! Copyright (C) 2010 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: accessors calendar combinators.short-circuit environment
+formatting io io.directories io.encodings.utf8 io.files
+io.files.info io.files.info.unix io.files.trash io.files.types
+io.pathnames kernel math math.parser sequences system unix.stat
+unix.users ;
+
+IN: io.files.trash.unix
+
+! Implements the FreeDesktop.org Trash Specification 0.7
+
+<PRIVATE
+
+: top-directory? ( path -- ? )
+    dup ".." append-path [ link-status ] bi@
+    [ [ st_dev>> ] bi@ = not ] [ [ st_ino>> ] bi@ = ] 2bi or ;
+
+: top-directory ( path -- path' )
+    [ dup top-directory? not ] [ ".." append-path ] while ;
+
+: make-user-directory ( path -- )
+    [ make-directories ] [ OCT: 700 set-file-permissions ] bi ;
+
+: check-trash-path ( path -- )
+    {
+        [ file-info directory? ]
+        [ sticky? ]
+        [ link-info type>> +symbolic-link+ = not ]
+    } 1&& [ "invalid trash path" throw ] unless ;
+
+: trash-home ( -- path )
+    "XDG_DATA_HOME" os-env
+    home ".local/share" append-path or
+    "Trash" append-path dup check-trash-path ;
+
+: trash-1 ( root -- path )
+    ".Trash" append-path dup check-trash-path
+    real-user-id number>string append-path ;
+
+: trash-2 ( root -- path )
+    real-user-id ".Trash-%d" sprintf append-path ;
+
+: trash-path ( path -- path' )
+    top-directory dup trash-home top-directory = [
+        drop trash-home
+    ] [
+        dup ".Trash" append-path exists?
+        [ trash-1 ] [ trash-2 ] if
+        [ make-user-directory ] keep
+    ] if ;
+
+: (safe-file-name) ( path counter -- path' )
+    [
+        [ parent-directory ]
+        [ file-stem ]
+        [ file-extension dup [ "." prepend ] when ] tri
+    ] dip swap "%s%s %s%s" sprintf ;
+
+: safe-file-name ( path -- path' )
+    dup 0 [ over exists? ] [
+        [ parent-directory to-directory ] [ 1 + ] bi*
+        [ (safe-file-name) ] keep
+    ] while drop nip ;
+
+PRIVATE>
+
+M: unix send-to-trash ( path -- )
+    dup trash-path [
+        "files" append-path [ make-user-directory ] keep
+        to-directory safe-file-name
+    ] [
+        "info" append-path [ make-user-directory ] keep
+        to-directory ".trashinfo" append [ over ] dip utf8 [
+            "[Trash Info]" write nl
+            "Path=" write write nl
+            "DeletionDate=" write
+            now "%Y-%m-%dT%H:%M:%S" strftime write nl
+        ] with-file-writer
+    ] bi move-file ;
+
+
diff --git a/extra/io/files/trash/windows/platforms.txt b/extra/io/files/trash/windows/platforms.txt
new file mode 100644 (file)
index 0000000..8e1a559
--- /dev/null
@@ -0,0 +1 @@
+windows
diff --git a/extra/io/files/trash/windows/windows.factor b/extra/io/files/trash/windows/windows.factor
new file mode 100644 (file)
index 0000000..ce14cfa
--- /dev/null
@@ -0,0 +1,73 @@
+! Copyright (C) 2010 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: accessors alien.c-types alien.data alien.strings
+alien.syntax classes.struct destructors kernel
+io.encodings.utf16n io.files.trash libc math sequences system
+windows.types ;
+
+IN: io.files.trash.windows
+
+<PRIVATE
+
+LIBRARY: shell32
+
+TYPEDEF: WORD FILEOP_FLAGS
+
+PACKED-STRUCT: SHFILEOPSTRUCTW
+    { hwnd HWND }
+    { wFunc UINT }
+    { pFrom LPCWSTR* }
+    { pTo LPCWSTR* }
+    { fFlags FILEOP_FLAGS }
+    { fAnyOperationsAborted BOOL }
+    { hNameMappings LPVOID }
+    { lpszProgressTitle LPCWSTR } ;
+
+FUNCTION: int SHFileOperationW ( SHFILEOPSTRUCTW* lpFileOp ) ;
+
+CONSTANT: FO_MOVE HEX: 0001
+CONSTANT: FO_COPY HEX: 0002
+CONSTANT: FO_DELETE HEX: 0003
+CONSTANT: FO_RENAME HEX: 0004
+
+CONSTANT: FOF_MULTIDESTFILES HEX: 0001
+CONSTANT: FOF_CONFIRMMOUSE HEX: 0002
+CONSTANT: FOF_SILENT HEX: 0004
+CONSTANT: FOF_RENAMEONCOLLISION HEX: 0008
+CONSTANT: FOF_NOCONFIRMATION HEX: 0010
+CONSTANT: FOF_WANTMAPPINGHANDLE HEX: 0020
+CONSTANT: FOF_ALLOWUNDO HEX: 0040
+CONSTANT: FOF_FILESONLY HEX: 0080
+CONSTANT: FOF_SIMPLEPROGRESS HEX: 0100
+CONSTANT: FOF_NOCONFIRMMKDIR HEX: 0200
+CONSTANT: FOF_NOERRORUI HEX: 0400
+CONSTANT: FOF_NOCOPYSECURITYATTRIBS HEX: 0800
+CONSTANT: FOF_NORECURSION HEX: 1000
+CONSTANT: FOF_NO_CONNECTED_ELEMENTS HEX: 2000
+CONSTANT: FOF_WANTNUKEWARNING HEX: 4000
+CONSTANT: FOF_NORECURSEREPARSE HEX: 8000
+
+PRIVATE>
+
+M: windows send-to-trash ( path -- )
+    [
+        utf16n string>alien B{ 0 0 } append
+        malloc-byte-array &free
+
+        SHFILEOPSTRUCTW <struct>
+            f >>hwnd
+            FO_DELETE >>wFunc
+            swap >>pFrom
+            f >>pTo
+            FOF_ALLOWUNDO
+            FOF_NOCONFIRMATION bitor
+            FOF_NOERRORUI bitor
+            FOF_SILENT bitor >>fFlags
+
+        SHFileOperationW [ throw ] unless-zero
+
+    ] with-destructors ;
+
+
+
index c8cdb3b6ee6301c80183343592b42d998c264e3d..2d1612229264bb860ff3fd1d1e4ff3c57e4b4aef 100644 (file)
@@ -15,7 +15,7 @@ ARTICLE: { "lunar-rescue" "lunar-rescue" } "Lunar Rescue Emulator"
 "Provides an emulation of the original 8080 Arcade Game 'Lunar Rescue'." $nl\r
 "More information on the arcade game can be obtained from " { $url "http://www.mameworld.net/maws/romset/lrescue" } "." $nl\r
 "To play the game you need the ROM files for the arcade game. They should "\r
-"be placed in a directory called 'lrescue' in the location specified by "\r
+"be placed in a directory called " { $snippet "lrescue" } " in the location specified by "\r
 "the variable " { $link rom-root } ". The specific files needed are:"\r
 { $list\r
   "lrescue/lrescue.1"\r
index 9d8c8b86924f0e2f18a898abbcd2667d4cbb125e..5e0ad51b4fdc6d7ab354fb8ce6dc457884362c48 100644 (file)
@@ -20,16 +20,12 @@ SYMBOL: builder-recipients
 ! (Optional) CPU architecture to build for.
 SYMBOL: target-cpu
 
-target-cpu get-global [
-    cpu name>> target-cpu set-global
-] unless
+target-cpu get-global [ cpu target-cpu set-global ] unless
 
 ! (Optional) OS to build for.
 SYMBOL: target-os
 
-target-os get-global [
-    os name>> target-os set-global
-] unless
+target-os get-global [ os target-os set-global ] unless
 
 ! Keep test-log around?
 SYMBOL: builder-debug
diff --git a/extra/mason/platform/platform-tests.factor b/extra/mason/platform/platform-tests.factor
new file mode 100644 (file)
index 0000000..8a5c00f
--- /dev/null
@@ -0,0 +1,4 @@
+USING: tools.test strings mason.platform ;
+IN: mason.platform.tests
+
+[ t ] [ platform string? ] unit-test
diff --git a/extra/math/approx/approx-docs.factor b/extra/math/approx/approx-docs.factor
new file mode 100644 (file)
index 0000000..1bbfd08
--- /dev/null
@@ -0,0 +1,19 @@
+! Copyright (C) 2010 John Benediktsson.
+! See http://factorcode.org/license.txt for BSD license
+
+USING: help.markup help.syntax math math.approx ;
+
+IN: math.approx
+
+HELP: approximate
+{ $values { "x" ratio } { "epsilon" ratio } { "y" ratio } }
+{ $description
+"Applied to two fractional numbers \"x\" and \"epsilon\", returns the "
+"simplest rational number within \"epsilon\" of \"x\"."
+$nl
+"A rational number \"y\" is said to be simpler than another \"y'\" if "
+"abs numerator y <= abs numerator y', and denominator y <= demoniator y'"
+$nl
+"Any real interval contains a unique simplest rational; in particular note "
+"that 0/1 is the simplest rational of all."
+} ;
diff --git a/extra/math/approx/approx-tests.factor b/extra/math/approx/approx-tests.factor
new file mode 100644 (file)
index 0000000..a8d387b
--- /dev/null
@@ -0,0 +1,21 @@
+! Copyright (C) 2010 John Benediktsson.
+! See http://factorcode.org/license.txt for BSD license
+
+USING: kernel math math.approx math.constants
+math.floating-point sequences tools.test ;
+
+IN: math.approx.tests
+
+[ { 3 3 13/4 16/5 19/6 22/7 } ]
+[
+    pi double>ratio
+    { 1/2 1/4 1/8 1/16 1/32 1/64 }
+    [ approximate ] with map
+] unit-test
+
+[ { -3 -3 -13/4 -16/5 -19/6 -22/7 } ]
+[
+    pi double>ratio neg
+    { 1/2 1/4 1/8 1/16 1/32 1/64 }
+    [ approximate ] with map
+] unit-test
diff --git a/extra/math/approx/approx.factor b/extra/math/approx/approx.factor
new file mode 100644 (file)
index 0000000..070243c
--- /dev/null
@@ -0,0 +1,38 @@
+! Copyright (C) 2010 John Benediktsson.
+! See http://factorcode.org/license.txt for BSD license
+
+USING: combinators kernel locals math math.functions ;
+
+IN: math.approx
+
+<PRIVATE
+
+:: (simplest) ( n d n' d' -- val ) ! assumes 0 < n/d < n'/d'
+    n  d  /mod :> ( q  r  )
+    n' d' /mod :> ( q' r' )
+    {
+        { [ r zero? ] [ q ] }
+        { [ q q' = not ] [ q 1 + ] }
+        [
+            d' r' d r (simplest) >fraction :> ( n'' d'' )
+            q n'' * d'' + n'' /
+        ]
+    } cond ;
+
+:: simplest ( x y -- val )
+    {
+        { [ x y > ] [ y x simplest ] }
+        { [ x y = ] [ x ] }
+        { [ x 0 > ] [ x y [ >fraction ] bi@ (simplest) ] }
+        { [ y 0 < ] [ y x [ neg >fraction ] bi@ (simplest) neg ] }
+        [ 0 ]
+    } cond ;
+
+: check-float ( x -- x )
+    dup float? [ "can't be floats" throw ] when ;
+
+PRIVATE>
+
+: approximate ( x epsilon -- y )
+    [ check-float ] bi@ [ - ] [ + ] 2bi simplest ;
+
diff --git a/extra/math/approx/authors.txt b/extra/math/approx/authors.txt
new file mode 100644 (file)
index 0000000..e091bb8
--- /dev/null
@@ -0,0 +1 @@
+John Benediktsson
diff --git a/extra/math/approx/summary.txt b/extra/math/approx/summary.txt
new file mode 100644 (file)
index 0000000..1e7c451
--- /dev/null
@@ -0,0 +1 @@
+Approximating rational numbers.
diff --git a/extra/memcached/authors.txt b/extra/memcached/authors.txt
new file mode 100644 (file)
index 0000000..e091bb8
--- /dev/null
@@ -0,0 +1 @@
+John Benediktsson
diff --git a/extra/memcached/memcached-docs.factor b/extra/memcached/memcached-docs.factor
new file mode 100644 (file)
index 0000000..c8963ac
--- /dev/null
@@ -0,0 +1,123 @@
+! Copyright (C) 2010 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: help.syntax help.markup io.sockets math memcached
+quotations sequences strings ;
+
+IN: memcached
+
+HELP: memcached-server
+{ $var-description
+    "Holds an " { $link inet } " object with the address of "
+    "an Memcached server." 
+} ;
+
+HELP: with-memcached
+{ $values { "quot" quotation } }
+{ $description
+    "Opens a network connection to the " { $link memcached-server }
+    " and runs the specified quotation."
+} ;
+
+HELP: m/get
+{ $values { "key" string } { "val" string } }
+{ $description
+    "Gets a single key."
+} ;
+
+HELP: m/set
+{ $values { "val" string } { "key" string } }
+{ $description
+    "Sets a single key to a particular value, whether the item "
+    "exists or not."
+} ;
+
+HELP: m/add
+{ $values { "val" string } { "key" string } }
+{ $description
+    "Adds an item only if the item does not already exist. "
+    "If the item already exists, throws an error."
+} ;
+
+HELP: m/replace
+{ $values { "val" string } { "key" string } }
+{ $description
+    "Replaces an item only if it already eixsts. "
+    "If the item does not exist, throws an error."
+} ;
+
+HELP: m/delete
+{ $values { "key" string } }
+{ $description
+    "Deletes an item."
+} ;
+
+HELP: m/append
+{ $values { "val" string } { "key" string } }
+{ $description
+    "Appends the value to the specified item."
+} ;
+
+HELP: m/prepend
+{ $values { "val" string } { "key" string } }
+{ $description
+    "Prepends the value to the specified item."
+} ;
+
+HELP: m/incr
+{ $values { "key" string } { "val" string } }
+{ $description
+    "Increments the value of the specified item by 1."
+} ;
+
+HELP: m/incr-val
+{ $values { "amt" string } { "key" string } { "val" string } }
+{ $description
+    "Increments the value of the specified item by the specified amount."
+} ;
+
+HELP: m/decr
+{ $values { "key" string } { "val" string } }
+{ $description
+    "Decrements the value of the specified item by 1."
+} ;
+
+HELP: m/decr-val
+{ $values { "amt" string } { "key" string } { "val" string } }
+{ $description
+    "Decrements the value of the specified item by the specified amount."
+} ;
+
+HELP: m/version
+{ $values { "version" string } }
+{ $description
+    "Retrieves the version of the " { $link memcached-server } "."
+} ;
+
+HELP: m/noop
+{ $description
+    "Used as a keep-alive.  Also flushes any outstanding quiet gets."
+} ;
+
+HELP: m/stats
+{ $values { "stats" sequence } }
+{ $description
+    "Get various statistics about the " { $link memcached-server } "."
+} ;
+
+HELP: m/flush
+{ $description
+    "Deletes all the items in the cache now."
+} ;
+
+HELP: m/flush-later
+{ $values { "seconds" integer } }
+{ $description
+    "Deletes all the items in the cache sometime in the future."
+} ;
+
+HELP: m/quit
+{ $description
+    "Close the connection to the " { $link memcached-server } "."
+} ;
+
diff --git a/extra/memcached/memcached-tests.factor b/extra/memcached/memcached-tests.factor
new file mode 100644 (file)
index 0000000..17c93c2
--- /dev/null
@@ -0,0 +1,97 @@
+! Copyright (C) 2010 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: calendar math math.functions memcached memcached.private
+kernel sequences threads tools.test ;
+
+IN: memcached.tests
+
+<PRIVATE
+
+: not-found? ( quot -- )
+    [ "key not found" = ] must-fail-with ;
+
+PRIVATE>
+
+! test version
+[ t ] [ [ m/version ] with-memcached length 0 > ] unit-test
+
+! test simple set get
+[ m/flush ] with-memcached
+[ "valuex" "x" m/set ] with-memcached
+[ "valuex" ] [ [ "x" m/get ] with-memcached ] unit-test
+
+! test flush
+[ m/flush ] with-memcached
+[ "valuex" "x" m/set "valuey" "y" m/set ] with-memcached
+[ "valuex" ] [ [ "x" m/get ] with-memcached ] unit-test
+[ "valuey" ] [ [ "y" m/get ] with-memcached ] unit-test
+[ m/flush ] with-memcached
+[ [ "x" m/get ] with-memcached ] not-found?
+[ [ "y" m/get ] with-memcached ] not-found?
+
+! test noop
+[ m/noop ] with-memcached
+
+! test delete
+[ m/flush ] with-memcached
+[ "valuex" "x" m/set ] with-memcached
+[ "valuex" ] [ [ "x" m/get ] with-memcached ] unit-test
+[ "x" m/delete ] with-memcached
+[ [ "x" m/get ] with-memcached ] not-found?
+
+! test replace
+[ m/flush ] with-memcached
+[ [ "x" m/get ] with-memcached ] not-found?
+[ [ "ex" "x" m/replace ] with-memcached ] not-found?
+[ "ex" "x" m/add ] with-memcached
+[ "ex" ] [ [ "x" m/get ] with-memcached ] unit-test
+[ "ex2" "x" m/replace ] with-memcached
+[ "ex2" ] [ [ "x" m/get ] with-memcached ] unit-test
+
+! test incr
+[ m/flush ] with-memcached
+[ 0 ] [ [ "x" m/incr ] with-memcached ] unit-test
+[ 1 ] [ [ "x" m/incr ] with-memcached ] unit-test
+[ 212 ] [ [ 211 "x" m/incr-val ] with-memcached ] unit-test
+[ 8589934804 ] [ [ 2 33 ^ "x" m/incr-val ] with-memcached ] unit-test
+
+! test decr
+[ m/flush ] with-memcached
+[ "5" "x" m/set ] with-memcached
+[ 4 ] [ [ "x" m/decr ] with-memcached ] unit-test
+[ 0 ] [ [ 211 "x" m/decr-val ] with-memcached ] unit-test
+
+! test timebombed flush
+[ m/flush ] with-memcached
+[ [ "x" m/get ] with-memcached ] not-found?
+[ "valuex" "x" m/set ] with-memcached
+[ "valuex" ] [ [ "x" m/get ] with-memcached ] unit-test
+[ 2 m/flush-later ] with-memcached
+[ "valuex" ] [ [ "x" m/get ] with-memcached ] unit-test
+3 seconds sleep
+[ [ "x" m/get ] with-memcached ] not-found?
+
+! test append
+[ m/flush ] with-memcached
+[ "some" "x" m/set ] with-memcached
+[ "thing" "x" m/append ] with-memcached
+[ "something" ] [ [ "x" m/get ] with-memcached ] unit-test
+
+! test prepend
+[ m/flush ] with-memcached
+[ "some" "x" m/set ] with-memcached
+[ "thing" "x" m/prepend ] with-memcached
+[ "thingsome" ] [ [ "x" m/get ] with-memcached ] unit-test
+
+! test multi-get
+[ m/flush ] with-memcached
+[ H{ } ] [ [ { "x" "y" "z" } m/getseq ] with-memcached ] unit-test
+[ "5" "x" m/set ] with-memcached
+[ "valuex" "y" m/set ] with-memcached
+[ H{ { "x" "5" } { "y" "valuex" } } ]
+[ [ { "x" "y" "z" } m/getseq ] with-memcached ] unit-test
+
+
+
+
diff --git a/extra/memcached/memcached.factor b/extra/memcached/memcached.factor
new file mode 100644 (file)
index 0000000..12bf28b
--- /dev/null
@@ -0,0 +1,219 @@
+! Copyright (C) 2010 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: accessors arrays assocs byte-arrays combinators fry
+io io.encodings.binary io.sockets kernel make math math.parser
+namespaces pack random sequences strings ;
+
+IN: memcached
+
+! TODO:
+! - quiet commands
+! - CAS
+! - expirations
+! - initial-value for incr/decr
+
+
+SYMBOL: memcached-server
+"127.0.0.1" 11211 <inet> memcached-server set-global
+
+: with-memcached ( quot -- )
+    memcached-server get-global
+    binary [ call ] with-client ; inline
+
+<PRIVATE
+
+! Commands
+CONSTANT: GET      HEX: 00
+CONSTANT: SET      HEX: 01
+CONSTANT: ADD      HEX: 02
+CONSTANT: REPLACE  HEX: 03
+CONSTANT: DELETE   HEX: 04
+CONSTANT: INCR     HEX: 05
+CONSTANT: DECR     HEX: 06
+CONSTANT: QUIT     HEX: 07
+CONSTANT: FLUSH    HEX: 08
+CONSTANT: GETQ     HEX: 09
+CONSTANT: NOOP     HEX: 0A
+CONSTANT: VERSION  HEX: 0B
+CONSTANT: GETK     HEX: 0C
+CONSTANT: GETKQ    HEX: 0D
+CONSTANT: APPEND   HEX: 0E
+CONSTANT: PREPEND  HEX: 0F
+CONSTANT: STAT     HEX: 10
+CONSTANT: SETQ     HEX: 11
+CONSTANT: ADDQ     HEX: 12
+CONSTANT: REPLACEQ HEX: 13
+CONSTANT: DELETEQ  HEX: 14
+CONSTANT: INCRQ    HEX: 15
+CONSTANT: DECRQ    HEX: 16
+CONSTANT: QUITQ    HEX: 17
+CONSTANT: FLUSHQ   HEX: 18
+CONSTANT: APPENDQ  HEX: 19
+CONSTANT: PREPENDQ HEX: 1A
+
+! Errors
+CONSTANT: NOT_FOUND    HEX: 01
+CONSTANT: EXISTS       HEX: 02
+CONSTANT: TOO_LARGE    HEX: 03
+CONSTANT: INVALID_ARGS HEX: 04
+CONSTANT: NOT_STORED   HEX: 05
+CONSTANT: NOT_NUMERIC  HEX: 06
+CONSTANT: UNKNOWN_CMD  HEX: 81
+CONSTANT: MEMORY       HEX: 82
+
+TUPLE: request cmd key val extra opaque cas ;
+
+: <request> ( cmd -- request )
+    "" "" "" random-32 0 \ request boa ;
+
+: send-header ( request -- )
+    {
+        [ cmd>> ]
+        [ key>> length ]
+        [ extra>> length ]
+        [
+            [ key>> length ]
+            [ extra>> length ]
+            [ val>> length ] tri + +
+        ]
+        [ opaque>> ]
+        [ cas>> ]
+    } cleave
+    ! magic, opcode, keylen, extralen, datatype, status,
+    ! bodylen, opaque, cas [ big-endian ]
+    '[ HEX: 80 _ _ _ 0 0 _ _ _ ] "CCSCCSIIQ" pack-be write ;
+
+: (send) ( str -- )
+    [ >byte-array write ] unless-empty ;
+
+: send-request ( request -- )
+    {
+        [ send-header    ]
+        [ extra>> (send) ]
+        [ key>>   (send) ]
+        [ val>>   (send) ]
+    } cleave flush ;
+
+: read-header ( -- header )
+    "CCSCCSIIQ" [ packed-length read ] [ unpack-be ] bi ;
+
+: check-magic ( header -- )
+    first HEX: 81 = [ "bad magic" throw ] unless ;
+
+: check-status ( header -- )
+    [ 5 ] dip nth {
+        { NOT_FOUND    [ "key not found" throw     ] }
+        { EXISTS       [ "key exists" throw        ] }
+        { TOO_LARGE    [ "value too large" throw   ] }
+        { INVALID_ARGS [ "invalid arguments" throw ] }
+        { NOT_STORED   [ "item not stored" throw   ] }
+        { NOT_NUMERIC  [ "value not numeric" throw ] }
+        { UNKNOWN_CMD  [ "unknown command" throw   ] }
+        { MEMORY       [ "out of memory" throw     ] }
+        [ drop ]
+    } case ;
+
+: check-opaque ( opaque header -- ? )
+    [ 7 ] dip nth = ;
+
+: (read) ( n -- str )
+    dup 0 > [ read >string ] [ drop "" ] if ;
+
+: read-key ( header -- key )
+    [ 2 ] dip nth (read) ;
+
+: read-val ( header -- val )
+    [ [ 6 ] dip nth ] [ [ 2 ] dip nth ] bi - (read) ;
+
+: read-body ( header -- val key )
+    {
+        [ check-magic  ]
+        [ check-status ]
+        [ read-key     ]
+        [ read-val     ]
+    } cleave swap ;
+
+: read-response ( -- val key )
+    read-header read-body ;
+
+: submit ( request -- response )
+    send-request read-response drop ;
+
+: (cmd) ( key cmd -- request )
+    <request> swap >>key ;
+
+: (incr/decr) ( amt key cmd -- response )
+    (cmd) swap '[ _ 0 0 ] "QQI" pack-be >>extra ! amt init exp
+    submit "Q" unpack-be first ;
+
+: (mutate) ( val key cmd -- )
+    (cmd) swap >>val { 0 0 } "II" pack-be >>extra ! flags exp
+    submit drop ;
+
+: (cat) ( val key cmd -- )
+    (cmd) swap >>val submit drop ;
+
+PRIVATE>
+
+: m/version ( -- version ) VERSION <request> submit ;
+
+: m/noop ( -- ) NOOP <request> submit drop ;
+
+: m/incr-val ( amt key -- val ) INCR (incr/decr) ;
+
+: m/incr ( key -- val ) 1 swap m/incr-val ;
+
+: m/decr-val ( amt key -- val ) DECR (incr/decr) ;
+
+: m/decr ( key -- val ) 1 swap m/decr-val ;
+
+: m/get ( key -- val ) GET (cmd) submit 4 tail ;
+
+: m/getq ( opaque key -- )
+    GETQ (cmd) swap >>opaque send-request ;
+
+: m/getseq ( keys -- vals )
+    [ H{ } clone ] dip
+    [ <enum> [ m/getq ] assoc-each ]
+    [ length 10 + NOOP <request> swap >>opaque send-request ]
+    [
+        <enum> [
+            assoc-size 10 + '[
+                _ read-header [ check-opaque ] keep swap
+            ]
+        ] [
+            '[
+                [ read-body drop 4 tail ]
+                [ [ 7 ] dip nth _ at ]
+                bi pick set-at
+            ]
+        ] bi until drop
+    ] tri ;
+
+: m/set ( val key -- ) SET (mutate) ;
+
+: m/add ( val key -- ) ADD (mutate) ;
+
+: m/replace ( val key -- ) REPLACE (mutate) ;
+
+: m/delete ( key -- ) DELETE (cmd) submit drop ;
+
+: m/append ( val key -- ) APPEND (cat) ;
+
+: m/prepend ( val key -- ) PREPEND (cat) ;
+
+: m/flush-later ( seconds -- )
+    FLUSH <request> swap 1array "I" pack-be >>extra ! timebomb
+    submit drop ;
+
+: m/flush ( -- ) 0 m/flush-later ;
+
+: m/stats ( -- stats )
+    STAT <request> send-request
+    [ read-response dup length 0 > ]
+    [ swap 2array ] produce 2nip ;
+
+: m/quit ( -- ) QUIT <request> submit drop ;
+
+
diff --git a/extra/memcached/summary.txt b/extra/memcached/summary.txt
new file mode 100644 (file)
index 0000000..d2af7c9
--- /dev/null
@@ -0,0 +1 @@
+Provides access to memcached, a high-performance, distributed memory object caching system.
diff --git a/extra/ntp/authors.txt b/extra/ntp/authors.txt
new file mode 100644 (file)
index 0000000..e091bb8
--- /dev/null
@@ -0,0 +1 @@
+John Benediktsson
diff --git a/extra/ntp/ntp-docs.factor b/extra/ntp/ntp-docs.factor
new file mode 100644 (file)
index 0000000..406d7f2
--- /dev/null
@@ -0,0 +1,13 @@
+! Copyright (C) 2010 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: help.syntax help.markup ntp ntp.private strings ;
+
+IN: ntp
+
+HELP: <ntp>
+{ $values { "host" string } { "ntp" ntp } }
+{ $description
+    "Requests the time from the specified NTP time server."
+} ;
+
diff --git a/extra/ntp/ntp.factor b/extra/ntp/ntp.factor
new file mode 100644 (file)
index 0000000..064d1e1
--- /dev/null
@@ -0,0 +1,116 @@
+! Copyright (C) 2010 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: accessors arrays calendar combinators destructors
+fry formatting kernel io io.sockets math pack random
+sequences ;
+
+IN: ntp
+
+<PRIVATE
+
+CONSTANT: REQUEST B{ HEX: 1b 0 0 0 0 0 0 0
+                     0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+                     0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+                     0 0 0 0 0 0 0 0 }
+
+: (time) ( sequence -- timestamp )
+    [ first ] [ second 32 2^ / ] bi + seconds
+    1900 1 1 0 0 0 instant <timestamp> time+ ;
+
+: (leap) ( leap -- string/f )
+    {
+        { 0 [ "no warning" ] }
+        { 1 [ "last minute has 61 seconds" ] }
+        { 2 [ "last minute has 59 seconds" ] }
+        { 3 [ "alarm condition (clock not synchronized)" ] }
+        [ drop f ]
+    } case ;
+
+: (mode) ( mode -- string )
+    {
+        { 0 [ "unspecified" ] }
+        { 1 [ "symmetric active" ] }
+        { 2 [ "symmetric passive" ] }
+        { 3 [ "client" ] }
+        { 4 [ "server" ] }
+        { 5 [ "broadcast" ] }
+        { 6 [ "reserved for NTP control message" ] }
+        { 7 [ "reserved for private use" ] }
+        [ drop f ]
+    } case ;
+
+: (stratum) ( stratum -- string )
+    {
+        { 0 [ "unspecified or unavailable" ] }
+        { 1 [ "primary reference (e.g., radio clock)" ] }
+        [
+            [ 1 > ] [ 255 < ] bi and
+            [ "secondary reference (via NTP or SNTP)" ]
+            [ "invalid stratum" throw ] if
+        ]
+    } case ;
+
+: (ref-id) ( ref-id stratum -- string )
+    [
+        {
+            [ -24 shift HEX: ff bitand ]
+            [ -16 shift HEX: ff bitand ]
+            [ -8 shift HEX: ff bitand ]
+            [ HEX: ff bitand ]
+        } cleave
+    ] dip {
+        { 0 [ "%c%c%c%c" sprintf ] }
+        { 1 [ "%c%c%c%c" sprintf ] }
+        [
+            [ 1 > ] [ 255 < ] bi and
+            [ "%d.%d.%d.%d" sprintf ]
+            [ "invalid stratum" throw ] if
+        ]
+    } case ;
+
+TUPLE: ntp leap version mode stratum poll precision
+root-delay root-dispersion ref-id ref-timestamp
+orig-timestamp recv-timestamp tx-timestamp ;
+
+: (ntp) ( payload -- ntp )
+    "CCCcIIIIIIIIIII" unpack-be {
+        [ first -6 shift HEX: 3 bitand ]  ! leap
+        [ first -3 shift HEX: 7 bitand ]  ! version
+        [ first HEX: 7 bitand ]           ! mode
+        [ second ]                        ! stratum
+        [ third ]                         ! poll
+        [ [ 3 ] dip nth ]                 ! precision
+        [ [ 4 ] dip nth 16 2^ / ]         ! root-delay
+        [ [ 5 ] dip nth 16 2^ / ]         ! root-dispersion
+        [ [ 6 ] dip nth ]                 ! ref-id
+        [ [ { 7 8 } ] dip nths (time) ]   ! ref-timestamp
+        [ [ { 9 10 } ] dip nths (time) ]  ! orig-timestamp
+        [ [ { 11 12 } ] dip nths (time) ] ! recv-timestamp
+        [ [ { 13 14 } ] dip nths (time) ] ! tx-timestamp 
+    } cleave ntp boa
+    dup stratum>> '[ _ (ref-id) ] change-ref-id
+    [ dup (leap) 2array ] change-leap
+    [ dup (mode) 2array ] change-mode
+    [ dup (stratum) 2array ] change-stratum ;
+
+PRIVATE>
+
+! TODO:
+! - socket timeout?
+! - format request properly?
+! - strftime should format millis?
+! - why does <inet4> resolve-host not work?
+
+: <ntp> ( host -- ntp )
+    123 <inet> resolve-host [ inet4? ] filter random
+    f 0 <inet4> <datagram> [
+        [ REQUEST ] 2dip [ send ] [ receive drop ] bi (ntp)
+    ] with-disposal ;
+
+: default-ntp ( -- ntp )
+    "pool.ntp.org" <ntp> ;
+
+: local-ntp ( -- ntp )
+    "localhost" <ntp> ;
+
diff --git a/extra/ntp/summary.txt b/extra/ntp/summary.txt
new file mode 100644 (file)
index 0000000..b70772b
--- /dev/null
@@ -0,0 +1 @@
+Client for NTP protocol
index 1c648e6369508b434c4c2722c014ec87d7e8d12f..231700c0e0c5ccaac5cee2479d22591ac65d7eea 100644 (file)
@@ -224,7 +224,7 @@ var price = (order == null ? null : order.price);""" }
     }
     ! { $slide "Stack languages are fundamental"
     !     "Very simple semantics"
-    !     "Easy to generate stack code programatically"
+    !     "Easy to generate stack code programmatically"
     !     "Everything is almost entirely library code in Factor"
     !     "Factor is easy to extend"
     ! }
index 22af8787cce96723f91ee6b6995de9381d828438..f1082de9547bfed06acea08af7ff7d43ecccdcfb 100644 (file)
@@ -25,8 +25,11 @@ HELP: set-completion
 } ;
 
 ARTICLE: "readline" "Readline"
-{ $vocab-link "readline" }
-;
+"The " { $vocab-link "readline" } " vocabulary binds to the C readline library and provides Emacs-style key bindings for editing text. Currently, it only works from the non-graphical UI." $nl
 
+"To read a line:"
+{ $subsections readline }
+"To set a completion hook:"
+{ $subsections set-completion } ;
 
 ABOUT: "readline"
diff --git a/extra/tnetstrings/authors.txt b/extra/tnetstrings/authors.txt
new file mode 100644 (file)
index 0000000..e091bb8
--- /dev/null
@@ -0,0 +1 @@
+John Benediktsson
diff --git a/extra/tnetstrings/summary.txt b/extra/tnetstrings/summary.txt
new file mode 100644 (file)
index 0000000..4db1c3f
--- /dev/null
@@ -0,0 +1 @@
+Reader and writer for "tagged netstrings"
diff --git a/extra/tnetstrings/tnetstrings-tests.factor b/extra/tnetstrings/tnetstrings-tests.factor
new file mode 100644 (file)
index 0000000..f6d7329
--- /dev/null
@@ -0,0 +1,26 @@
+! Copyright (C) 2011 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: kernel tnetstrings sequences tools.test ;
+
+[ t ] [
+    {
+        { H{ } "0:}" }
+        { { } "0:]" }
+        { "" "0:\"" }
+        { t "4:true!" }
+        { f "5:false!" }
+        { 12345 "5:12345#" }
+        { "this is cool" "12:this is cool\"" }
+        {
+            H{ { "hello" { 12345678901 "this" } } }
+            "34:5:hello\"22:11:12345678901#4:this\"]}"
+        }
+        {
+            { 12345 67890 "xxxxx" }
+            "24:5:12345#5:67890#5:xxxxx\"]"
+        }
+    } [
+        first2 [ tnetstring> = ] [ swap >tnetstring = ] 2bi and
+    ] all?
+] unit-test
diff --git a/extra/tnetstrings/tnetstrings.factor b/extra/tnetstrings/tnetstrings.factor
new file mode 100644 (file)
index 0000000..d9b9f1c
--- /dev/null
@@ -0,0 +1,98 @@
+! Copyright (C) 2011 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: arrays assocs combinators formatting hashtables kernel
+math math.parser sequences splitting strings ;
+
+IN: tnetstrings
+
+<PRIVATE
+
+: parse-payload ( data -- remain payload payload-type )
+    ":" split1 swap string>number cut unclip swapd ;
+
+DEFER: parse-tnetstring
+
+: parse-list ( data -- value )
+    [ { } ] [
+        [ dup empty? not ] [ parse-tnetstring ] produce nip
+    ] if-empty ;
+
+: parse-pair ( data -- extra value key )
+    parse-tnetstring [
+        [ "Unbalanced dictionary store" throw ] when-empty
+        parse-tnetstring
+        [ "Invalid value, null not allowed" throw ] unless*
+    ] dip ;
+
+: parse-dict ( data -- value )
+    [ H{ } ] [
+        [ dup empty? not ] [ parse-pair swap 2array ] produce
+        nip >hashtable
+    ] if-empty ;
+
+: parse-bool ( data -- ? )
+    {
+        { "true" [ t ] }
+        { "false" [ f ] }
+        [ "Invalid bool: %s" sprintf throw ]
+    } case ;
+
+: parse-null ( data -- f )
+    [ f ] [ drop "Payload must be 0 length" throw ] if-empty ;
+
+: parse-tnetstring ( data -- remain value )
+    parse-payload {
+        { CHAR: # [ string>number ] }
+        { CHAR: " [ ] }
+        { CHAR: } [ parse-dict ] }
+        { CHAR: ] [ parse-list ] }
+        { CHAR: ! [ parse-bool ] }
+        { CHAR: ~ [ parse-null ] }
+        { CHAR: , [ ] }
+        [ "Invalid payload type: %c" sprintf throw ]
+    } case ;
+
+PRIVATE>
+
+: tnetstring> ( string -- value )
+    parse-tnetstring swap [
+        "Had trailing junk: %s" sprintf throw
+    ] unless-empty ;
+
+<PRIVATE
+
+DEFER: dump-tnetstring
+
+: dump ( string type -- string )
+    [ [ length ] keep ] dip "%d:%s%s" sprintf ;
+
+: dump-number ( data -- string ) number>string "#" dump ;
+
+: dump-string ( data -- string ) "\"" dump ;
+
+: dump-list ( data -- string )
+    [ dump-tnetstring ] map "" concat-as "]" dump ;
+
+: dump-dict ( data -- string )
+    >alist [ first2 [ dump-tnetstring ] bi@ append ] map
+    "" concat-as "}" dump ;
+
+: dump-bool ( ? -- string )
+    "4:true!" "5:false!" ? ;
+
+: dump-tnetstring ( data -- string )
+    {
+        { [ dup boolean?  ] [ dump-bool ] }
+        { [ dup number?   ] [ dump-number ] }
+        { [ dup string?   ] [ dump-string ] }
+        { [ dup sequence? ] [ dump-list ] }
+        { [ dup assoc?    ] [ dump-dict ] }
+        [ "Can't serialize object" throw ]
+    } cond ;
+
+PRIVATE>
+
+: >tnetstring ( value -- string )
+    dump-tnetstring ;
+
index 438faa0decf4f64ce5601457a869138e91e2c1b3..6fef3b9ef4afc031e2b063e67c3f19fbf6ef8723 100644 (file)
@@ -1,13 +1,19 @@
-USING: listener io.servers io.encodings.utf8 accessors kernel ;
+USING: accessors debugger kernel listener io.servers
+io.encodings.utf8 namespaces ;
+
 IN: tty-server
 
-: <tty-server> ( port -- )
+: start-listener ( -- )
+    [ [ drop print-error-and-restarts ] error-hook set listener ] with-scope ;
+
+: <tty-server> ( port -- server )
     utf8 <threaded-server>
         "tty-server" >>name
         swap local-server >>insecure
-        [ listener ] >>handler
-    start-server drop ;
+        [ start-listener ] >>handler
+        f >>timeout ;
 
-: tty-server ( -- ) 9999 <tty-server> ;
+: run-tty-server ( -- )
+    9999 <tty-server> start-server drop ;
 
-MAIN: tty-server
+MAIN: run-tty-server
index b0a4b146d49d97604da27ab6309d030d090a254a..a09d17356a16c8428cbed94515c57f0521ad1ec3 100644 (file)
@@ -90,7 +90,7 @@ CONSTANT: vpri-slides
         }
     }
     { $slide "Object system"
-        "We can compute perimiters now."
+        "We can compute perimeters now."
         { $code "100 20 <rectangle> perimeter ." }
         { $code "3 <circle> perimeter ." }
     }
diff --git a/extra/webapps/benchmark/benchmark.factor b/extra/webapps/benchmark/benchmark.factor
new file mode 100644 (file)
index 0000000..8f6154c
--- /dev/null
@@ -0,0 +1,34 @@
+! Copyright (C) 2011 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: accessors furnace.actions http.server
+http.server.dispatchers http.server.responses http.server.static
+kernel namespaces ;
+
+IN: webapps.benchmark
+
+: <hello-action> ( -- action )
+    <page-action>
+        [ "Hello, world!" "text/plain" <content> ] >>display ;
+
+TUPLE: benchmark < dispatcher ;
+
+: <benchmark> ( -- dispatcher )
+    benchmark new-dispatcher
+        <hello-action> "hello" add-responder
+        "resource:" <static> "static" add-responder ;
+
+: run-benchmark ( -- )
+    <benchmark>
+        main-responder set-global
+    8080 httpd drop ;
+
+! Use this with apachebench:
+!
+!   * dynamic content
+!     http://localhost:8080/hello
+!
+!   * static content
+!     http://localhost:8080/static/readme.html
+
+MAIN: run-benchmark
index 3bc8bdce84d8ff4d99e4ead81d2b4a60b6e743d9..c0488b3d3e9c2b5f340dec56c8d0897f636ddb9a 100644 (file)
@@ -1,99 +1,99 @@
-/* Copyright (C) 2007 Chris Double. All Rights Reserved.\r
-   See http://factorcode.org/license.txt for BSD license. */\r
-\r
-var fjsc_repl = false;\r
-\r
-function fjsc_repl_handler() {\r
-  var my_term = this;\r
-  this.newLine();\r
-  if(this.lineBuffer != '') {\r
-    factor.server_eval(\r
-      this.lineBuffer, \r
-      function(text, result) { \r
-        document.getElementById("compiled").value = result;\r
-        display_datastack();        \r
-      }, \r
-      function() { my_term.prompt(); });\r
-  }\r
-  else\r
-    my_term.prompt();\r
-}\r
-\r
-function fjsc_init_handler() {\r
-  this.write(\r
-    [\r
-      TermGlobals.center('********************************************************'),\r
-      TermGlobals.center('*                                                      *'),\r
-      TermGlobals.center('*       Factor to Javascript Compiler Example          *'),\r
-      TermGlobals.center('*                                                      *'),\r
-      TermGlobals.center('********************************************************')\r
-    ]);\r
-  \r
-  this.prompt();\r
-}\r
-\r
-function startup() {\r
-  var conf = {\r
-    x: 0,\r
-    y: 0,\r
-    cols: 64,\r
-    rows: 18,\r
-    termDiv: "repl",\r
-    crsrBlinkMode: true,\r
-    ps: "scratchpad ",\r
-    initHandler: fjsc_init_handler,\r
-    handler: fjsc_repl_handler\r
-  };\r
-  fjsc_repl = new Terminal(conf);\r
-  fjsc_repl.open();\r
-}\r
-\r
-function display_datastack() {\r
-   var html=[];\r
-   html.push("<table border='1'>")\r
-   for(var i = 0; i < factor.cont.data_stack.length; ++i) {\r
-      html.push("<tr><td>")\r
-      html.push(factor.cont.data_stack[i])\r
-      html.push("</td></tr>")\r
-   }\r
-   html.push("</table>")\r
-   document.getElementById('stack').innerHTML=html.join("");\r
-}\r
-\r
-jQuery(function() {\r
-  startup();\r
-  display_datastack();\r
-});\r
-\r
-factor.add_word("kernel", ".s", "primitive", function(next) {   \r
-  var stack = factor.cont.data_stack;\r
-  var term = fjsc_repl;\r
-  for(var i=0; i<stack.length; ++i) {\r
-    term.type(""+stack[i]);\r
-    term.newLine();\r
-  }\r
-  factor.call_next(next);\r
-});\r
-\r
-factor.add_word("io", "print", "primitive", function(next) {   \r
-  var stack = factor.cont.data_stack;\r
-  var term = fjsc_repl;\r
-  term.type(""+stack.pop());\r
-  term.newLine();\r
-  factor.call_next(next);\r
-});\r
-\r
-factor.add_word("io", "write", "primitive", function(next) {   \r
-  var stack = factor.cont.data_stack;\r
-  var term = fjsc_repl;\r
-  term.type(""+stack.pop());\r
-  factor.call_next(next);\r
-});\r
-\r
-factor.add_word("io", ".", "primitive", function(next) {   \r
-  var stack = factor.cont.data_stack;\r
-  var term = fjsc_repl;\r
-  term.type(""+stack.pop());\r
-  term.newLine();\r
-  factor.call_next(next);\r
-});\r
+/* Copyright (C) 2007 Chris Double. All Rights Reserved.
+   See http://factorcode.org/license.txt for BSD license. */
+
+var fjsc_repl = false;
+
+function fjsc_repl_handler() {
+  var my_term = this;
+  this.newLine();
+  if(this.lineBuffer != '') {
+    factor.server_eval(
+      this.lineBuffer,
+      function(text, result) {
+        document.getElementById("compiled").value = result;
+        display_datastack();
+      },
+      function() { my_term.prompt(); });
+  }
+  else
+    my_term.prompt();
+}
+
+function fjsc_init_handler() {
+  this.write(
+    [
+      TermGlobals.center('********************************************************'),
+      TermGlobals.center('*                                                      *'),
+      TermGlobals.center('*       Factor to Javascript Compiler Example          *'),
+      TermGlobals.center('*                                                      *'),
+      TermGlobals.center('********************************************************')
+    ]);
+
+  this.prompt();
+}
+
+function startup() {
+  var conf = {
+    x: 0,
+    y: 0,
+    cols: 64,
+    rows: 18,
+    termDiv: "repl",
+    crsrBlinkMode: true,
+    ps: "( scratchpad )",
+    initHandler: fjsc_init_handler,
+    handler: fjsc_repl_handler
+  };
+  fjsc_repl = new Terminal(conf);
+  fjsc_repl.open();
+}
+
+function display_datastack() {
+   var html=[];
+   html.push("<table border='1'>")
+   for(var i = 0; i < factor.cont.data_stack.length; ++i) {
+      html.push("<tr><td>")
+      html.push(factor.cont.data_stack[i])
+      html.push("</td></tr>")
+   }
+   html.push("</table>")
+   document.getElementById('stack').innerHTML=html.join("");
+}
+
+jQuery(function() {
+  startup();
+  display_datastack();
+});
+
+factor.add_word("kernel", ".s", "primitive", function(next) {
+  var stack = factor.cont.data_stack;
+  var term = fjsc_repl;
+  for(var i=0; i<stack.length; ++i) {
+    term.type(""+stack[i]);
+    term.newLine();
+  }
+  factor.call_next(next);
+});
+
+factor.add_word("io", "print", "primitive", function(next) {
+  var stack = factor.cont.data_stack;
+  var term = fjsc_repl;
+  term.type(""+stack.pop());
+  term.newLine();
+  factor.call_next(next);
+});
+
+factor.add_word("io", "write", "primitive", function(next) {
+  var stack = factor.cont.data_stack;
+  var term = fjsc_repl;
+  term.type(""+stack.pop());
+  factor.call_next(next);
+});
+
+factor.add_word("io", ".", "primitive", function(next) {
+  var stack = factor.cont.data_stack;
+  var term = fjsc_repl;
+  term.type(""+stack.pop());
+  term.newLine();
+  factor.call_next(next);
+});
index d86c57bd388ee4a6e222c018beda85b4729eb44f..9302b4d1bd0113bf75938c07cd24fbbb5bd2b311 100644 (file)
@@ -16,6 +16,8 @@ SLOT: cpu
 : platform ( builder -- string )
     [ os>> ] [ cpu>> ] bi (platform) ;
 
+SLOT: last-release
+
 : binary-package-name ( builder -- string )
     [ [ platform % "/" % ] [ last-release>> % ] bi ] "" make
     remote-directory ;
index edf5eaaa842f7c79014d9d53f6e7e0f2a9db3d98..9e8ecb2b62923c16e6ae8e5d1c4c9ca24c751c21 100644 (file)
@@ -34,6 +34,7 @@ xml.writer xmode.highlight ; %>
 <li><a href="http://concatenative.org/wiki/view/Factor/FAQ">Get answers to frequently-asked questions</a></li>
 <li><a href="http://docs.factorcode.org/">Read Factor reference documentation online</a></li>
 <li><a href="http://concatenative.org/wiki/view/Concatenative%20language">Learn more about concatenative programming</a></li>
+<li><a href="http://github.com/slavapestov/factor/issues">Report a bug</a></li>
 </ul>
 
 <p>Most of the above links point to pages on the <a href="http://concatenative.org">concatenative.org wiki</a>.</p>
@@ -49,7 +50,7 @@ xml.writer xmode.highlight ; %>
 "resource:extra/websites/factorcode/examples.txt" utf8 file-lines
 { "----" } split random
 "factor" [ highlight-lines ] with-html-writer
-[ xml>string write-html ] each
+xml>string write-html
 %></pre>
 
 <p>See the <a href="http://concatenative.org/wiki/view/Factor/Examples">example programs</a> page on the wiki for more.</p>
diff --git a/extra/wolfram-alpha/authors.txt b/extra/wolfram-alpha/authors.txt
new file mode 100644 (file)
index 0000000..e091bb8
--- /dev/null
@@ -0,0 +1 @@
+John Benediktsson
diff --git a/extra/wolfram-alpha/summary.txt b/extra/wolfram-alpha/summary.txt
new file mode 100644 (file)
index 0000000..21a95e5
--- /dev/null
@@ -0,0 +1 @@
+Query API for Wolfram Alpha
diff --git a/extra/wolfram-alpha/wolfram-alpha.factor b/extra/wolfram-alpha/wolfram-alpha.factor
new file mode 100644 (file)
index 0000000..5c6368e
--- /dev/null
@@ -0,0 +1,50 @@
+! Copyright (C) 2011 John Benediktsson
+! See http://factorcode.org/license.txt for BSD license
+
+USING: accessors colors.constants formatting http http.client
+images.gif images.http io io.styles kernel namespaces sequences
+splitting ui urls.encoding xml xml.data xml.traversal ;
+
+IN: wolfram-alpha
+
+SYMBOL: wolfram-api-id
+
+! "XXXXXX-XXXXXXXXXX" wolfram-api-id set-global
+
+<PRIVATE
+
+: query ( query -- xml )
+    url-encode wolfram-api-id get-global
+    "http://api.wolframalpha.com/v2/query?input=%s&appid=%s"
+    sprintf http-get nip string>xml ;
+
+PRIVATE>
+
+: wolfram-image. ( query -- )
+    query "pod" tags-named [
+        [
+            "title" attr "%s:\n" sprintf H{
+                { foreground COLOR: slate-gray }
+                { font-name "sans-serif" }
+                { font-style bold }
+            } format
+        ] [
+            "img" deep-tags-named [
+                "src" attr "  " write http-image.
+            ] each
+        ] bi
+    ] each ;
+
+: wolfram-text. ( query -- )
+    query "pod" tags-named [
+        [ "title" attr "%s:\n" printf ]
+        [
+            "plaintext" deep-tags-named [
+                children>string string-lines
+                [ "  %s\n" printf ] each
+            ] each
+        ] bi
+    ] each ;
+
+: wolfram. ( query -- )
+    ui-running? [ wolfram-image. ] [ wolfram-text. ] if ;