diff --git a/core/alien/alien-docs.factor b/core/alien/alien-docs.factor index 7d13080e3c..0caf0e9a9f 100755 --- a/core/alien/alien-docs.factor +++ b/core/alien/alien-docs.factor @@ -265,7 +265,7 @@ ARTICLE: "embedding-restrictions" "Embedding API restrictions" ARTICLE: "embedding-factor" "What embedding looks like from Factor" "Factor code will run inside an embedded instance in the same way it would run in a stand-alone instance." $nl -"One exception is the global " { $link stdio } " stream, which is by default not bound to the terminal where the process is running, to avoid conflicting with any I/O the host process might perform. To initialize the terminal stream, " { $link init-stdio } " must be called explicitly." +"One exception is that the global " { $link input-stream } " and " { $link output-stream } " streams are not bound by default, to avoid conflicting with any I/O the host process might perform. The " { $link init-stdio } " words must be called explicitly to initialize terminal streams." $nl "There is a word which can detect when Factor is embedded:" { $subsection embedded? } diff --git a/core/bootstrap/image/image.factor b/core/bootstrap/image/image.factor index cb83dd9488..1ff04bacc2 100755 --- a/core/bootstrap/image/image.factor +++ b/core/bootstrap/image/image.factor @@ -475,7 +475,7 @@ M: quotation ' "Writing image to " write architecture get boot-image-name resource-path [ write "..." print flush ] - [ binary [ (write-image) ] with-stream ] bi ; + [ binary [ (write-image) ] with-file-writer ] bi ; PRIVATE> diff --git a/core/bootstrap/stage2.factor b/core/bootstrap/stage2.factor index 3247832d52..2e087ff5bd 100755 --- a/core/bootstrap/stage2.factor +++ b/core/bootstrap/stage2.factor @@ -87,7 +87,7 @@ f error-continuation set-global parse-command-line run-user-init "run" get run - stdio get [ stream-flush ] when* + output-stream get [ stream-flush ] when* ] [ print-error 1 exit ] recover ] set-boot-quot diff --git a/core/compiler/errors/errors-docs.factor b/core/compiler/errors/errors-docs.factor index dd71eb704f..d86587662b 100755 --- a/core/compiler/errors/errors-docs.factor +++ b/core/compiler/errors/errors-docs.factor @@ -21,19 +21,19 @@ HELP: compiler-error HELP: compiler-error. { $values { "error" "an error" } { "word" word } } -{ $description "Prints a compiler error to the " { $link stdio } " stream." } ; +{ $description "Prints a compiler error to " { $link output-stream } "." } ; HELP: compiler-errors. { $values { "type" symbol } } -{ $description "Prints compiler errors to the " { $link stdio } " stream. The type parameter is one of " { $link +error+ } ", " { $link +warning+ } ", or " { $link +linkage+ } "." } ; +{ $description "Prints compiler errors to " { $link output-stream } ". The type parameter is one of " { $link +error+ } ", " { $link +warning+ } ", or " { $link +linkage+ } "." } ; HELP: :errors -{ $description "Prints all serious compiler errors from the most recent compile to the " { $link stdio } " stream." } ; +{ $description "Prints all serious compiler errors from the most recent compile to " { $link output-stream } "." } ; HELP: :warnings -{ $description "Prints all ignorable compiler warnings from the most recent compile to the " { $link stdio } " stream." } ; +{ $description "Prints all ignorable compiler warnings from the most recent compile to " { $link output-stream } "." } ; HELP: :linkage -{ $description "Prints all C library interface linkage errors from the most recent compile to the " { $link stdio } " stream." } ; +{ $description "Prints all C library interface linkage errors from the most recent compile to " { $link output-stream } "." } ; { :errors :warnings } related-words diff --git a/core/continuations/continuations-docs.factor b/core/continuations/continuations-docs.factor index b1db09b6bc..472136da8e 100755 --- a/core/continuations/continuations-docs.factor +++ b/core/continuations/continuations-docs.factor @@ -34,7 +34,7 @@ $nl { $code " ... do stuff ... dispose" } -"The reason being that if " { $snippet "do stuff" } " throws an error, the resource will not be disposed of. The most important case where this can occur is with I/O streams, and the correct solution is to always use " { $link with-stream } "; see " { $link "stdio" } " for details." ; +"The reason being that if " { $snippet "do stuff" } " throws an error, the resource will not be disposed of. The most important case where this can occur is with I/O streams, and the correct solution is to always use " { $link with-input-stream } " and " { $link with-output-stream } "; see " { $link "stdio" } " for details." ; ARTICLE: "errors" "Error handling" "Support for handling exceptional situations such as bad user input, implementation bugs, and input/output errors is provided by a set of words built using continuations." diff --git a/core/continuations/continuations-tests.factor b/core/continuations/continuations-tests.factor index b0c216e82f..996d17077c 100755 --- a/core/continuations/continuations-tests.factor +++ b/core/continuations/continuations-tests.factor @@ -39,7 +39,7 @@ IN: continuations.tests "!!! The following error is part of the test" print -[ ] [ [ [ "2 car" ] eval ] [ print-error ] recover ] unit-test +[ ] [ [ [ "2 car" ] eval ] try ] unit-test [ f throw ] must-fail diff --git a/core/debugger/debugger-docs.factor b/core/debugger/debugger-docs.factor index ca6aa59cc4..cb79597a73 100755 --- a/core/debugger/debugger-docs.factor +++ b/core/debugger/debugger-docs.factor @@ -64,7 +64,7 @@ HELP: :3 HELP: error. { $values { "error" "an error" } } -{ $contract "Print an error to the " { $link stdio } " stream. You can define methods on this generic word to print human-readable messages for custom errors." } +{ $contract "Print an error to " { $link output-stream } ". You can define methods on this generic word to print human-readable messages for custom errors." } { $notes "Code should call " { $link print-error } " instead, which handles the case where the printing of the error itself throws an error." } ; HELP: error-help @@ -75,11 +75,11 @@ HELP: error-help HELP: print-error { $values { "error" "an error" } } -{ $description "Print an error to the " { $link stdio } " stream." } +{ $description "Print an error to " { $link output-stream } "." } { $notes "This word is called by the listener and other tools which report caught errors to the user." } ; HELP: restarts. -{ $description "Print a list of restarts for the most recently thrown error to the " { $link stdio } " stream." } ; +{ $description "Print a list of restarts for the most recently thrown error to " { $link output-stream } "." } ; HELP: error-hook { $var-description "A quotation with stack effect " { $snippet "( error -- )" } " which is used by " { $link try } " to report the error to the user." } diff --git a/core/debugger/debugger.factor b/core/debugger/debugger.factor index 34fcf8e6bc..e5dd02c25e 100755 --- a/core/debugger/debugger.factor +++ b/core/debugger/debugger.factor @@ -1,13 +1,13 @@ ! Copyright (C) 2004, 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: arrays definitions generic hashtables inspector io kernel -math namespaces prettyprint sequences assocs sequences.private -strings io.styles vectors words system splitting math.parser -classes.tuple continuations continuations.private combinators -generic.math io.streams.duplex classes.builtin classes -compiler.units generic.standard vocabs threads threads.private -init kernel.private libc io.encodings mirrors accessors -math.order ; +math namespaces prettyprint prettyprint.config sequences assocs +sequences.private strings io.styles vectors words system +splitting math.parser classes.tuple continuations +continuations.private combinators generic.math +classes.builtin classes compiler.units generic.standard vocabs +threads threads.private init kernel.private libc io.encodings +mirrors accessors math.order ; IN: debugger GENERIC: error. ( error -- ) @@ -64,17 +64,13 @@ M: string error. print ; [ global [ "Error in print-error!" print drop ] bind ] recover ; -SYMBOL: error-hook - -[ - print-error - restarts. - nl - "Type :help for debugging help." print flush -] error-hook set-global - : try ( quot -- ) - [ error-hook get call ] recover ; + [ + print-error + restarts. + nl + "Type :help for debugging help." print flush + ] recover ; ERROR: assert got expect ; @@ -209,9 +205,6 @@ M: no-next-method summary M: inconsistent-next-method summary drop "Executing call-next-method with inconsistent parameters" ; -M: stream-closed-twice summary - drop "Attempt to perform I/O on closed stream" ; - M: check-method summary drop "Invalid parameters for create-method" ; @@ -241,6 +234,15 @@ M: condition error-help error>> error-help ; M: assert summary drop "Assertion failed" ; +M: assert error. + "Assertion failed" print + standard-table-style [ + 15 length-limit set + 5 line-limit set + [ expect>> [ [ "Expect:" write ] with-cell pprint-cell ] with-row ] + [ got>> [ [ "Got:" write ] with-cell pprint-cell ] with-row ] bi + ] tabular-output ; + M: immutable summary drop "Sequence is immutable" ; M: redefine-error error. diff --git a/core/generic/standard/engines/tuple/tuple.factor b/core/generic/standard/engines/tuple/tuple.factor index 7639d1d499..51ea4f8225 100644 --- a/core/generic/standard/engines/tuple/tuple.factor +++ b/core/generic/standard/engines/tuple/tuple.factor @@ -127,8 +127,6 @@ M: echelon-dispatch-engine engine>quot 1 slot { tuple-layout } declare 5 slot ; inline -: unclip-last [ 1 head* ] [ peek ] bi ; - M: tuple-dispatch-engine engine>quot [ picker % diff --git a/core/inference/inference-docs.factor b/core/inference/inference-docs.factor index e32c94ed37..d79c82ed65 100755 --- a/core/inference/inference-docs.factor +++ b/core/inference/inference-docs.factor @@ -135,7 +135,7 @@ HELP: infer HELP: infer. { $values { "quot" "a quotation" } } -{ $description "Attempts to infer the quotation's stack effect, and prints this data to the " { $link stdio } " stream." } +{ $description "Attempts to infer the quotation's stack effect, and prints this data to " { $link output-stream } "." } { $errors "Throws an " { $link inference-error } " if stack effect inference fails." } ; { infer infer. } related-words diff --git a/core/inspector/inspector-docs.factor b/core/inspector/inspector-docs.factor index 84ae34480d..ab1c38b0b7 100644 --- a/core/inspector/inspector-docs.factor +++ b/core/inspector/inspector-docs.factor @@ -108,4 +108,4 @@ HELP: me HELP: inspector-hook { $var-description "A quotation with stack effect " { $snippet "( obj -- )" } ", called by the inspector to display an overview of an object." $nl -"The default implementation calls " { $link describe } " which outputs on the " { $link stdio } " stream, but the graphical listener sets this variable so that calling " { $link inspect } " in the UI opens the graphical inspector." } ; +"The default implementation calls " { $link describe } " which outputs on " { $link output-stream } ", but the graphical listener sets this variable so that calling " { $link inspect } " in the UI opens the graphical inspector." } ; diff --git a/core/io/backend/backend-docs.factor b/core/io/backend/backend-docs.factor index 8bf761e2a6..48b49ed32b 100644 --- a/core/io/backend/backend-docs.factor +++ b/core/io/backend/backend-docs.factor @@ -9,4 +9,4 @@ HELP: init-io { $contract "Initializes the I/O system. Called on startup." } ; HELP: init-stdio -{ $contract "Initializes the global " { $link stdio } " stream. Called on startup." } ; +{ $contract "Initializes the global " { $link input-stream } " and " { $link output-stream } ". Called on startup." } ; diff --git a/core/io/backend/backend.factor b/core/io/backend/backend.factor index 44b1eea349..0760063f0d 100755 --- a/core/io/backend/backend.factor +++ b/core/io/backend/backend.factor @@ -11,8 +11,10 @@ HOOK: init-io io-backend ( -- ) HOOK: (init-stdio) io-backend ( -- stdin stdout stderr ) : init-stdio ( -- ) - (init-stdio) utf8 stderr set-global - utf8 stdio set-global ; + (init-stdio) + [ utf8 input-stream set-global ] + [ utf8 output-stream set-global ] + [ utf8 error-stream set-global ] tri* ; HOOK: io-multiplex io-backend ( ms -- ) diff --git a/core/io/encodings/encodings-docs.factor b/core/io/encodings/encodings-docs.factor index 8a176ce4ec..92471acb5d 100644 --- a/core/io/encodings/encodings-docs.factor +++ b/core/io/encodings/encodings-docs.factor @@ -12,8 +12,7 @@ ARTICLE: "io.encodings" "I/O encodings" ARTICLE: "encodings-constructors" "Manually constructing an encoded stream" "The following words can be used to construct encoded streams. Note that they are usually not used directly, but rather by the stream constructors themselves. Most stream constructors take an encoding descriptor as a parameter and internally call these constructors." { $subsection } -{ $subsection } -{ $subsection } ; +{ $subsection } ; HELP: { $values { "stream" "an output stream" } @@ -29,16 +28,6 @@ HELP: { $description "Wraps the given stream in a new stream using the given encoding for all input. The encoding descriptor can either be a class or an instance of something conforming to the " { $link "encodings-protocol" } "." } $low-level-note ; -HELP: -{ $values { "stream-in" "an input stream" } - { "stream-out" "an output stream" } - { "encoding" "an encoding descriptor" } - { "duplex" "an encoded duplex stream" } } -{ $description "Wraps the given streams in an encoder or decoder stream, and puts them together in a duplex stream for input and output. If either input stream is already encoded, that encoding is stripped off before it is reencoded. The encoding descriptor must conform to the " { $link "encodings-protocol" } "." } -$low-level-note ; - -{ } related-words - ARTICLE: "encodings-descriptors" "Encoding descriptors" "An encoding descriptor is something which can be used for input or output streams to encode or decode files. It must conform to the " { $link "encodings-protocol" } ". Encodings which you can use are defined in the following vocabularies:" { $subsection "io.encodings.binary" } diff --git a/core/io/encodings/encodings-tests.factor b/core/io/encodings/encodings-tests.factor index 397d1ea89c..79922b019c 100755 --- a/core/io/encodings/encodings-tests.factor +++ b/core/io/encodings/encodings-tests.factor @@ -10,7 +10,7 @@ IN: io.streams.encodings.tests unit-test : lines-test ( stream -- line1 line2 ) - [ readln readln ] with-stream ; + [ readln readln ] with-input-stream ; [ "This is a line." diff --git a/core/io/encodings/encodings.factor b/core/io/encodings/encodings.factor index 4559cec666..0f6e58bdc9 100755 --- a/core/io/encodings/encodings.factor +++ b/core/io/encodings/encodings.factor @@ -2,8 +2,8 @@ ! See http://factorcode.org/license.txt for BSD license. USING: math kernel sequences sbufs vectors namespaces growable strings io classes continuations combinators io.styles -io.streams.plain splitting io.streams.duplex byte-arrays -sequences.private accessors ; +io.streams.plain splitting byte-arrays sequences.private +accessors ; IN: io.encodings ! The encoding descriptor protocol @@ -131,6 +131,3 @@ INSTANCE: encoder plain-writer over decoder? [ >r decoder-stream r> ] when ; PRIVATE> - -: ( stream-in stream-out encoding -- duplex ) - tuck reencode >r redecode r> ; diff --git a/core/io/files/files-docs.factor b/core/io/files/files-docs.factor index ba17223a29..d18babf31b 100755 --- a/core/io/files/files-docs.factor +++ b/core/io/files/files-docs.factor @@ -184,8 +184,12 @@ HELP: +unknown+ { $description "A unknown file type." } ; HELP: -{ $values { "path" "a pathname string" } { "encoding" "an encoding descriptor" { "stream" "an input stream" } } - { "stream" "an input stream" } } +{ + $values + { "path" "a pathname string" } + { "encoding" "an encoding descriptor" } + { "stream" "an input stream" } +} { $description "Outputs an input stream for reading from the specified pathname using the given encoding." } { $errors "Throws an error if the file is unreadable." } ; @@ -201,17 +205,17 @@ HELP: HELP: with-file-reader { $values { "path" "a pathname string" } { "encoding" "an encoding descriptor" } { "quot" "a quotation" } } -{ $description "Opens a file for reading and calls the quotation using " { $link with-stream } "." } +{ $description "Opens a file for reading and calls the quotation using " { $link with-input-stream } "." } { $errors "Throws an error if the file is unreadable." } ; HELP: with-file-writer { $values { "path" "a pathname string" } { "encoding" "an encoding descriptor" } { "quot" "a quotation" } } -{ $description "Opens a file for writing using the given encoding and calls the quotation using " { $link with-stream } "." } +{ $description "Opens a file for writing using the given encoding and calls the quotation using " { $link with-output-stream } "." } { $errors "Throws an error if the file cannot be opened for writing." } ; HELP: with-file-appender { $values { "path" "a pathname string" } { "encoding" "an encoding descriptor" } { "quot" "a quotation" } } -{ $description "Opens a file for appending using the given encoding and calls the quotation using " { $link with-stream } "." } +{ $description "Opens a file for appending using the given encoding and calls the quotation using " { $link with-output-stream } "." } { $errors "Throws an error if the file cannot be opened for writing." } ; HELP: set-file-lines diff --git a/core/io/files/files.factor b/core/io/files/files.factor index 576307b589..76c7b144d0 100755 --- a/core/io/files/files.factor +++ b/core/io/files/files.factor @@ -25,13 +25,13 @@ HOOK: (file-appender) io-backend ( path -- stream ) lines ; : with-file-reader ( path encoding quot -- ) - >r r> with-stream ; inline + >r r> with-input-stream ; inline : file-contents ( path encoding -- str ) contents ; : with-file-writer ( path encoding quot -- ) - >r r> with-stream ; inline + >r r> with-output-stream ; inline : set-file-lines ( seq path encoding -- ) [ [ print ] each ] with-file-writer ; @@ -40,7 +40,7 @@ HOOK: (file-appender) io-backend ( path -- stream ) [ write ] with-file-writer ; : with-file-appender ( path encoding quot -- ) - >r r> with-stream ; inline + >r r> with-output-stream ; inline ! Pathnames : path-separator? ( ch -- ? ) os windows? "/\\" "/" ? member? ; diff --git a/core/io/io-docs.factor b/core/io/io-docs.factor index fd40950e62..ddea4da556 100755 --- a/core/io/io-docs.factor +++ b/core/io/io-docs.factor @@ -5,7 +5,7 @@ IN: io ARTICLE: "stream-protocol" "Stream protocol" "The stream protocol consists of a large number of generic words, many of which are optional." $nl -"Stream protocol words are rarely called directly, since code which only works with one stream at a time should be written use " { $link "stdio" } " instead, wrapping I/O operations such as " { $link read } " and " { $link write } " in a " { $link with-stream } ". This leads more simpler, more reusable and more robust code." +"Stream protocol words are rarely called directly, since code which only works with one stream at a time should be written use " { $link "stdio" } " instead, wrapping I/O operations such as " { $link read } " and " { $link write } " in " { $link with-input-stream } " and " { $link with-output-stream } "." $nl "All streams must implement the " { $link dispose } " word in addition to the stream protocol." $nl @@ -26,24 +26,24 @@ $nl { $subsection stream-write-table } { $see-also "io.timeouts" } ; -ARTICLE: "stdio" "The default stream" -"Most I/O code only operates on one stream at a time. The " { $emphasis "default stream" } " is an implicit parameter used by many I/O words designed for this particular use-case. Using this idiom improves code in three ways:" +ARTICLE: "stdio" "Default input and output streams" +"Most I/O code only operates on one stream at a time. The " { $link input-stream } " and " { $link output-stream } " variables are implicit parameters used by many I/O words. Using this idiom improves code in three ways:" { $list { "Code becomes simpler because there is no need to keep a stream around on the stack." } - { "Code becomes more robust because " { $link with-stream } " automatically closes the stream if there is an error." } - { "Code becomes more reusable because it can be written to not worry about which stream is being used, and instead the caller can use " { $link with-stream } " to specify the source or destination for I/O operations." } + { "Code becomes more robust because " { $link with-input-stream } " and " { $link with-output-stream } " automatically close the streams if there is an error." } + { "Code becomes more reusable because it can be written to not worry about which stream is being used, and instead the caller can use " { $link with-input-stream } " or " { $link with-output-stream } " to specify the source or destination for I/O operations." } } "For example, here is a program which reads the first line of a file, converts it to an integer, then reads that many characters, and splits them into groups of 16:" { $code "USING: continuations kernel io io.files math.parser splitting ;" - "\"data.txt\" " + "\"data.txt\" utf8 " "dup stream-readln number>string over stream-read 16 group" "swap dispose" } "This code has two problems: it has some unnecessary stack shuffling, and if either " { $link stream-readln } " or " { $link stream-read } " throws an I/O error, the stream is not closed because " { $link dispose } " is never reached. So we can add a call to " { $link with-disposal } " to ensure the stream is always closed:" { $code "USING: continuations kernel io io.files math.parser splitting ;" - "\"data.txt\" [" + "\"data.txt\" utf8 [" " dup stream-readln number>string over stream-read" " 16 group" "] with-disposal" @@ -51,17 +51,34 @@ ARTICLE: "stdio" "The default stream" "This code is robust however it is more complex than it needs to be since. This is where the default stream words come in; using them, the above can be rewritten as follows:" { $code "USING: continuations kernel io io.files math.parser splitting ;" - "\"data.txt\" [" + "\"data.txt\" utf8 [" " readln number>string read 16 group" - "] with-stream" + "] with-input-stream" } -"The default stream is stored in a dynamically-scoped variable:" -{ $subsection stdio } -"Unless rebound in a child namespace, this variable will be set to a console stream for interacting with the user." +"An even better implementation that takes advantage of a utility word:" +{ $code + "USING: continuations kernel io io.files math.parser splitting ;" + "\"data.txt\" utf8 [" + " readln number>string read 16 group" + "] with-file-reader" +} +"The default input stream is stored in a dynamically-scoped variable:" +{ $subsection input-stream } +"Unless rebound in a child namespace, this variable will be set to a console stream for reading input from the user." +$nl +"Words reading from the default input stream:" { $subsection read1 } { $subsection read } { $subsection read-until } { $subsection readln } +"A pair of combinators for rebinding the " { $link input-stream } " variable:" +{ $subsection with-input-stream } +{ $subsection with-input-stream* } +"The default output stream is stored in a dynamically-scoped variable:" +{ $subsection output-stream } +"Unless rebound in a child namespace, this variable will be set to a console stream for showing output to the user." +$nl +"Words writing to the default input stream:" { $subsection flush } { $subsection write1 } { $subsection write } @@ -78,9 +95,12 @@ ARTICLE: "stdio" "The default stream" { $subsection with-row } { $subsection with-cell } { $subsection write-cell } -"A pair of combinators support rebinding the " { $link stdio } " variable:" -{ $subsection with-stream } -{ $subsection with-stream* } ; +"A pair of combinators for rebinding the " { $link output-stream } " variable:" +{ $subsection with-output-stream } +{ $subsection with-output-stream* } +"A pair of combinators for rebinding both default streams at once:" +{ $subsection with-streams } +{ $subsection with-streams* } ; ARTICLE: "stream-utils" "Stream utilities" "There are a few useful stream-related words which are not generic, but merely built up from the stream protocol." @@ -204,62 +224,65 @@ HELP: stream-copy { $description "Copies the contents of one stream into another, closing both streams when done." } $io-error ; -HELP: stdio -{ $var-description "Holds a stream, used for various implicit stream operations. Rebound using " { $link with-stream } " and " { $link with-stream* } "." } ; +HELP: input-stream +{ $var-description "Holds an input stream for various implicit stream operations. Rebound using " { $link with-input-stream } " and " { $link with-input-stream* } "." } ; + +HELP: output-stream +{ $var-description "Holds an output stream for various implicit stream operations. Rebound using " { $link with-output-stream } " and " { $link with-output-stream* } "." } ; HELP: readln { $values { "str/f" "a string or " { $link f } } } -{ $description "Reads a line of input from the " { $link stdio } " stream. Outputs " { $link f } " on stream exhaustion." } +{ $description "Reads a line of input from " { $link input-stream } ". Outputs " { $link f } " on stream exhaustion." } $io-error ; HELP: read1 { $values { "ch/f" "a character or " { $link f } } } -{ $description "Reads a character of input from the " { $link stdio } " stream. Outputs " { $link f } " on stream exhaustion." } +{ $description "Reads a character of input from " { $link input-stream } ". Outputs " { $link f } " on stream exhaustion." } $io-error ; HELP: read { $values { "n" "a non-negative integer" } { "str/f" "a string or " { $link f } } } -{ $description "Reads " { $snippet "n" } " characters of input from the " { $link stdio } " stream. Outputs a truncated string or " { $link f } " on stream exhaustion." } +{ $description "Reads " { $snippet "n" } " characters of input from " { $link input-stream } ". Outputs a truncated string or " { $link f } " on stream exhaustion." } $io-error ; HELP: read-until { $values { "seps" string } { "str/f" "a string or " { $link f } } { "sep/f" "a character or " { $link f } } } -{ $contract "Reads characters from the " { $link stdio } " stream. until the first occurrence of a separator character, or stream exhaustion. In the former case, the separator character is pushed on the stack, and is not part of the output string. In the latter case, the entire stream contents are output, along with " { $link f } "." } +{ $contract "Reads characters from " { $link input-stream } ". until the first occurrence of a separator character, or stream exhaustion. In the former case, the separator character is pushed on the stack, and is not part of the output string. In the latter case, the entire stream contents are output, along with " { $link f } "." } $io-error ; HELP: write1 { $values { "ch" "a character" } } -{ $contract "Writes a character of output to the " { $link stdio } " stream. If the stream does buffering, output may not be performed immediately; use " { $link flush } " to force output." } +{ $contract "Writes a character of output to " { $link output-stream } ". If the stream does buffering, output may not be performed immediately; use " { $link flush } " to force output." } $io-error ; HELP: write { $values { "str" string } } -{ $description "Writes a string of output to the " { $link stdio } " stream. If the stream does buffering, output may not be performed immediately; use " { $link flush } " to force output." } +{ $description "Writes a string of output to " { $link output-stream } ". If the stream does buffering, output may not be performed immediately; use " { $link flush } " to force output." } $io-error ; HELP: flush -{ $description "Waits for any pending output to the " { $link stdio } " stream to complete." } +{ $description "Waits for any pending output on " { $link output-stream } " to complete." } $io-error ; HELP: nl -{ $description "Writes a line terminator to the " { $link stdio } " stream. If the stream does buffering, output may not be performed immediately; use " { $link flush } " to force output." } +{ $description "Writes a line terminator to " { $link output-stream } ". If the stream does buffering, output may not be performed immediately; use " { $link flush } " to force output." } $io-error ; HELP: format { $values { "str" string } { "style" "a hashtable" } } -{ $description "Writes formatted text to the " { $link stdio } " stream. If the stream does buffering, output may not be performed immediately; use " { $link flush } " to force output." } +{ $description "Writes formatted text to " { $link output-stream } ". If the stream does buffering, output may not be performed immediately; use " { $link flush } " to force output." } { $notes "Details are in the documentation for " { $link stream-format } "." } $io-error ; HELP: with-nesting -{ $values { "style" "a hashtable" } { "quot" "a quotation" } } -{ $description "Calls the quotation in a new dynamic scope with the " { $link stdio } " stream rebound to a nested paragraph stream, with formatting information applied." } +{ $values { "style" "a hashtable" } { "quot" quotation } } +{ $description "Calls the quotation in a new dynamic scope with " { $link output-stream } " rebound to a nested paragraph stream, with formatting information applied." } { $notes "Details are in the documentation for " { $link make-block-stream } "." } $io-error ; HELP: tabular-output { $values { "style" "a hashtable" } { "quot" quotation } } -{ $description "Calls a quotation which emits a series of equal-length table rows using " { $link with-row } ". The results are laid out in a tabular fashion on the " { $link stdio } " stream." +{ $description "Calls a quotation which emits a series of equal-length table rows using " { $link with-row } ". The results are laid out in a tabular fashion on " { $link output-stream } "." $nl "The " { $snippet "style" } " hashtable holds table style information. See " { $link "table-styles" } "." } { $examples @@ -279,7 +302,7 @@ $io-error ; HELP: with-cell { $values { "quot" quotation } } -{ $description "Calls a quotation in a new scope with the " { $link stdio } " stream rebound. Output performed by the quotation is displayed in a table cell. This word can only be called inside the quotation given to " { $link with-row } "." } +{ $description "Calls a quotation in a new scope with " { $link output-stream } " rebound. Output performed by the quotation is displayed in a table cell. This word can only be called inside the quotation given to " { $link with-row } "." } $io-error ; HELP: write-cell @@ -288,34 +311,54 @@ HELP: write-cell $io-error ; HELP: with-style -{ $values { "style" "a hashtable" } { "quot" "a quotation" } } +{ $values { "style" "a hashtable" } { "quot" quotation } } { $description "Calls the quotation in a new dynamic scope where calls to " { $link write } ", " { $link format } " and other stream output words automatically inherit style settings from " { $snippet "style" } "." } { $notes "Details are in the documentation for " { $link make-span-stream } "." } $io-error ; HELP: print { $values { "string" string } } -{ $description "Writes a newline-terminated string to the " { $link stdio } " stream." } +{ $description "Writes a newline-terminated string to " { $link output-stream } "." } $io-error ; -HELP: with-stream -{ $values { "stream" "an input or output stream" } { "quot" "a quotation" } } -{ $description "Calls the quotation in a new dynamic scope, with the " { $link stdio } " variable rebound to " { $snippet "stream" } ". The stream is closed if the quotation returns or throws an error." } ; +HELP: with-input-stream +{ $values { "stream" "an input stream" } { "quot" quotation } } +{ $description "Calls the quotation in a new dynamic scope, with " { $link input-stream } " rebound to " { $snippet "stream" } ". The stream is closed if the quotation returns or throws an error." } ; -{ with-stream with-stream* } related-words +HELP: with-output-stream +{ $values { "stream" "an output stream" } { "quot" quotation } } +{ $description "Calls the quotation in a new dynamic scope, with " { $link output-stream } " rebound to " { $snippet "stream" } ". The stream is closed if the quotation returns or throws an error." } ; -HELP: with-stream* -{ $values { "stream" "an input or output stream" } { "quot" "a quotation" } } -{ $description "Calls the quotation in a new dynamic scope, with the " { $link stdio } " variable rebound to " { $snippet "stream" } "." } -{ $notes "This word does not close the stream. Compare with " { $link with-stream } "." } ; +HELP: with-streams +{ $values { "input" "an input stream" } { "output" "an output stream" } { "quot" quotation } } +{ $description "Calls the quotation in a new dynamic scope, with " { $link input-stream } " rebound to " { $snippet "input" } " and " { $link output-stream } " rebound to " { $snippet "output" } ". The stream is closed if the quotation returns or throws an error." } ; + +HELP: with-streams* +{ $values { "input" "an input stream" } { "output" "an output stream" } { "quot" quotation } } +{ $description "Calls the quotation in a new dynamic scope, with " { $link input-stream } " rebound to " { $snippet "input" } " and " { $link output-stream } " rebound to " { $snippet "output" } "." } +{ $notes "This word does not close the stream. Compare with " { $link with-streams } "." } ; + +{ with-input-stream with-input-stream* } related-words + +{ with-output-stream with-output-stream* } related-words + +HELP: with-input-stream* +{ $values { "stream" "an input stream" } { "quot" quotation } } +{ $description "Calls the quotation in a new dynamic scope, with " { $link input-stream } " rebound to " { $snippet "stream" } "." } +{ $notes "This word does not close the stream. Compare with " { $link with-input-stream } "." } ; + +HELP: with-output-stream* +{ $values { "stream" "an output stream" } { "quot" quotation } } +{ $description "Calls the quotation in a new dynamic scope, with " { $link output-stream } " rebound to " { $snippet "stream" } "." } +{ $notes "This word does not close the stream. Compare with " { $link with-output-stream } "." } ; HELP: bl -{ $description "Outputs a space character (" { $snippet "\" \"" } ")." } +{ $description "Outputs a space character (" { $snippet "\" \"" } ") to " { $link output-stream } "." } $io-error ; HELP: write-object { $values { "str" string } { "obj" "an object" } } -{ $description "Writes a string to the " { $link stdio } " stream, associating it with the object. If formatted output is supported, the string will become a clickable presentation of the object, otherwise this word behaves like a call to " { $link write } "." } +{ $description "Writes a string to " { $link output-stream } ", associating it with the object. If formatted output is supported, the string will become a clickable presentation of the object, otherwise this word behaves like a call to " { $link write } "." } $io-error ; HELP: lines diff --git a/core/io/io-tests.factor b/core/io/io-tests.factor index b7d1cf81c8..7204bde6fb 100755 --- a/core/io/io-tests.factor +++ b/core/io/io-tests.factor @@ -15,14 +15,14 @@ IN: io.tests "This is a line.\rThis is another line.\r" ] [ "core/io/test/mac-os-eol.txt" - [ 500 read ] with-stream + [ 500 read ] with-input-stream ] unit-test [ 255 ] [ "core/io/test/binary.txt" - [ read1 ] with-stream >fixnum + [ read1 ] with-input-stream >fixnum ] unit-test ! Make sure we use correct to_c_string form when writing @@ -40,7 +40,7 @@ IN: io.tests "J" read-until 2array , "i" read-until 2array , "X" read-until 2array , - ] with-stream + ] with-input-stream ] { } make ] unit-test @@ -49,12 +49,3 @@ IN: io.tests 10 [ 65536 read drop ] times ] with-file-reader ] unit-test - -! [ "" ] [ 0 read ] unit-test - -! [ ] [ "123" write 9000 CHAR: x write flush ] unit-test - -! [ -! "/core/io/test/binary.txt" -! [ 0.2 read ] with-stream -! ] must-fail diff --git a/core/io/io.factor b/core/io/io.factor index ef9eae7902..e28fd28fb3 100755 --- a/core/io/io.factor +++ b/core/io/io.factor @@ -30,39 +30,52 @@ GENERIC: stream-write-table ( table-cells style stream -- ) [ 2dup (stream-copy) ] [ dispose dispose ] [ ] cleanup ; -! Default stream -SYMBOL: stdio +! Default streams +SYMBOL: input-stream +SYMBOL: output-stream +SYMBOL: error-stream -! Default error stream -SYMBOL: stderr +: readln ( -- str/f ) input-stream get stream-readln ; +: read1 ( -- ch/f ) input-stream get stream-read1 ; +: read ( n -- str/f ) input-stream get stream-read ; +: read-until ( seps -- str/f sep/f ) input-stream get stream-read-until ; -: readln ( -- str/f ) stdio get stream-readln ; -: read1 ( -- ch/f ) stdio get stream-read1 ; -: read ( n -- str/f ) stdio get stream-read ; -: read-until ( seps -- str/f sep/f ) stdio get stream-read-until ; +: write1 ( ch -- ) output-stream get stream-write1 ; +: write ( str -- ) output-stream get stream-write ; +: flush ( -- ) output-stream get stream-flush ; -: write1 ( ch -- ) stdio get stream-write1 ; -: write ( str -- ) stdio get stream-write ; -: flush ( -- ) stdio get stream-flush ; +: nl ( -- ) output-stream get stream-nl ; +: format ( str style -- ) output-stream get stream-format ; -: nl ( -- ) stdio get stream-nl ; -: format ( str style -- ) stdio get stream-format ; +: with-input-stream* ( stream quot -- ) + input-stream swap with-variable ; inline -: with-stream* ( stream quot -- ) - stdio swap with-variable ; inline +: with-input-stream ( stream quot -- ) + [ with-input-stream* ] curry with-disposal ; inline -: with-stream ( stream quot -- ) - [ with-stream* ] curry with-disposal ; inline +: with-output-stream* ( stream quot -- ) + output-stream swap with-variable ; inline + +: with-output-stream ( stream quot -- ) + [ with-output-stream* ] curry with-disposal ; inline + +: with-streams* ( input output quot -- ) + [ output-stream set input-stream set ] prepose with-scope ; inline + +: with-streams ( input output quot -- ) + [ [ with-streams* ] 3curry ] + [ [ drop dispose dispose ] 3curry ] 3bi + [ ] cleanup ; inline : tabular-output ( style quot -- ) - swap >r { } make r> stdio get stream-write-table ; inline + swap >r { } make r> output-stream get stream-write-table ; inline : with-row ( quot -- ) { } make , ; inline : with-cell ( quot -- ) - H{ } stdio get make-cell-stream - [ swap with-stream ] keep , ; inline + H{ } output-stream get make-cell-stream + [ swap with-output-stream ] keep , ; inline : write-cell ( str -- ) [ write ] with-cell ; inline @@ -71,13 +84,14 @@ SYMBOL: stderr swap dup assoc-empty? [ drop call ] [ - stdio get make-span-stream swap with-stream + output-stream get make-span-stream swap with-output-stream ] if ; inline : with-nesting ( style quot -- ) - >r stdio get make-block-stream r> with-stream ; inline + >r output-stream get make-block-stream + r> with-output-stream ; inline -: print ( string -- ) stdio get stream-print ; +: print ( string -- ) output-stream get stream-print ; : bl ( -- ) " " write ; @@ -85,9 +99,9 @@ SYMBOL: stderr presented associate format ; : lines ( stream -- seq ) - [ [ readln dup ] [ ] [ drop ] unfold ] with-stream ; + [ [ readln dup ] [ ] [ drop ] unfold ] with-input-stream ; : contents ( stream -- str ) [ [ 65536 read dup ] [ ] [ drop ] unfold concat f like - ] with-stream ; + ] with-input-stream ; diff --git a/core/io/streams/byte-array/byte-array-docs.factor b/core/io/streams/byte-array/byte-array-docs.factor index 741725af41..7b27621343 100644 --- a/core/io/streams/byte-array/byte-array-docs.factor +++ b/core/io/streams/byte-array/byte-array-docs.factor @@ -25,10 +25,10 @@ HELP: HELP: with-byte-reader { $values { "encoding" "an encoding descriptor" } { "quot" quotation } { "byte-array" byte-array } } -{ $description "Calls the quotation in a new dynamic scope with " { $link stdio } " rebound to an input stream for reading from a byte array using an encoding." } ; +{ $description "Calls the quotation in a new dynamic scope with " { $link input-stream } " rebound to an input stream for reading from a byte array using an encoding." } ; HELP: with-byte-writer { $values { "encoding" "an encoding descriptor" } { "quot" quotation } { "byte-array" byte-array } } -{ $description "Calls the quotation in a new dynamic scope with " { $link stdio } " rebound to an output stream writing data to a byte array using an encoding." } ; +{ $description "Calls the quotation in a new dynamic scope with " { $link output-stream } " rebound to an output stream writing data to a byte array using an encoding." } ; diff --git a/core/io/streams/byte-array/byte-array.factor b/core/io/streams/byte-array/byte-array.factor index 2a8441ff23..28d789d66f 100644 --- a/core/io/streams/byte-array/byte-array.factor +++ b/core/io/streams/byte-array/byte-array.factor @@ -1,16 +1,16 @@ USING: byte-arrays byte-vectors kernel io.encodings io.streams.string -sequences io namespaces io.encodings.private ; +sequences io namespaces io.encodings.private accessors ; IN: io.streams.byte-array : ( encoding -- stream ) 512 swap ; : with-byte-writer ( encoding quot -- byte-array ) - >r r> [ stdio get ] compose with-stream* - dup encoder? [ encoder-stream ] when >byte-array ; inline + >r r> [ output-stream get ] compose with-output-stream* + dup encoder? [ stream>> ] when >byte-array ; inline : ( byte-array encoding -- stream ) >r >byte-vector dup reverse-here r> ; : with-byte-reader ( byte-array encoding quot -- ) - >r r> with-stream ; inline + >r r> with-input-stream* ; inline diff --git a/core/io/streams/c/c.factor b/core/io/streams/c/c.factor index 372acbe0c1..91732f3211 100755 --- a/core/io/streams/c/c.factor +++ b/core/io/streams/c/c.factor @@ -2,7 +2,7 @@ ! See http://factorcode.org/license.txt for BSD license. USING: kernel kernel.private namespaces io io.encodings sequences math generic threads.private classes io.backend -io.streams.duplex io.files continuations byte-arrays ; +io.files continuations byte-arrays ; IN: io.streams.c TUPLE: c-writer handle ; diff --git a/core/io/streams/duplex/duplex-docs.factor b/core/io/streams/duplex/duplex-docs.factor deleted file mode 100755 index c9691af5ba..0000000000 --- a/core/io/streams/duplex/duplex-docs.factor +++ /dev/null @@ -1,19 +0,0 @@ -USING: help.markup help.syntax io continuations ; -IN: io.streams.duplex - -ARTICLE: "io.streams.duplex" "Duplex streams" -"Duplex streams combine an input stream and an output stream into a bidirectional stream." -{ $subsection duplex-stream } -{ $subsection } ; - -ABOUT: "io.streams.duplex" - -HELP: duplex-stream -{ $class-description "A bidirectional stream wrapping an input and output stream." } ; - -HELP: -{ $values { "in" "an input stream" } { "out" "an output stream" } { "stream" " a duplex stream" } } -{ $description "Creates a duplex stream. Writing to a duplex stream will write to " { $snippet "out" } ", and reading from a duplex stream will read from " { $snippet "in" } ". Closing a duplex stream closes both the input and output streams." } ; - -HELP: stream-closed-twice -{ $error-description "This error is thrown when performing an I/O operation on a " { $link duplex-stream } " which has been closed with " { $link dispose } "." } ; diff --git a/core/io/streams/string/string-docs.factor b/core/io/streams/string/string-docs.factor index 5b09baa56d..b87e5ca591 100644 --- a/core/io/streams/string/string-docs.factor +++ b/core/io/streams/string/string-docs.factor @@ -17,7 +17,7 @@ HELP: HELP: with-string-writer { $values { "quot" quotation } { "str" string } } -{ $description "Calls the quotation in a new dynamic scope with " { $link stdio } " rebound to a new string writer. The accumulated string is output when the quotation returns." } ; +{ $description "Calls the quotation in a new dynamic scope with " { $link output-stream } " rebound to a new string writer. The accumulated string is output when the quotation returns." } ; HELP: { $values { "str" string } { "stream" "an input stream" } } @@ -26,4 +26,4 @@ HELP: HELP: with-string-reader { $values { "str" string } { "quot" quotation } } -{ $description "Calls the quotation in a new dynamic scope with " { $link stdio } " rebound to an input stream reading " { $snippet "str" } " from beginning to end." } ; +{ $description "Calls the quotation in a new dynamic scope with " { $link input-stream } " rebound to an input stream reading " { $snippet "str" } " from beginning to end." } ; diff --git a/core/io/streams/string/string-tests.factor b/core/io/streams/string/string-tests.factor index ca117534da..3512ac871d 100644 --- a/core/io/streams/string/string-tests.factor +++ b/core/io/streams/string/string-tests.factor @@ -35,7 +35,7 @@ unit-test "J" read-until 2array , "i" read-until 2array , "X" read-until 2array , - ] with-stream + ] with-input-stream ] { } make ] unit-test diff --git a/core/io/streams/string/string.factor b/core/io/streams/string/string.factor index 531d0401b2..d43599776b 100755 --- a/core/io/streams/string/string.factor +++ b/core/io/streams/string/string.factor @@ -15,7 +15,7 @@ M: growable stream-flush drop ; 512 ; : with-string-writer ( quot -- str ) - swap [ stdio get ] compose with-stream* + swap [ output-stream get ] compose with-output-stream* >string ; inline M: growable stream-read1 dup empty? [ drop f ] [ pop ] if ; @@ -56,7 +56,7 @@ M: null decode-char drop stream-read1 ; >sbuf dup reverse-here null ; : with-string-reader ( str quot -- ) - >r r> with-stream ; inline + >r r> with-input-stream ; inline INSTANCE: growable plain-writer @@ -67,15 +67,14 @@ INSTANCE: growable plain-writer ] unless ; : map-last ( seq quot -- seq ) - swap dup length - [ zero? rot [ call ] keep swap ] 2map nip ; inline + >r dup length [ zero? ] r> compose 2map ; inline : format-table ( table -- seq ) flip [ format-column ] map-last flip [ " " join ] map ; M: plain-writer stream-write-table - [ drop format-table [ print ] each ] with-stream* ; + [ drop format-table [ print ] each ] with-output-stream* ; M: plain-writer make-cell-stream 2drop ; diff --git a/core/listener/listener-docs.factor b/core/listener/listener-docs.factor index 755c79ac68..beea9005b4 100755 --- a/core/listener/listener-docs.factor +++ b/core/listener/listener-docs.factor @@ -32,14 +32,14 @@ HELP: listener-hook HELP: read-quot { $values { "quot/f" "a parsed quotation, or " { $link f } " indicating end of file" } } -{ $description "Reads a Factor expression which possibly spans more than one line from " { $link stdio } " stream. Additional lines of input are read while the parser stack height is greater than one. Since structural parsing words push partial quotations on the stack, this will keep on reading input until all delimited parsing words are terminated." } ; +{ $description "Reads a Factor expression which possibly spans more than one line from " { $link input-stream } ". Additional lines of input are read while the parser stack height is greater than one. Since structural parsing words push partial quotations on the stack, this will keep on reading input until all delimited parsing words are terminated." } ; HELP: listen -{ $description "Prompts for an expression on the " { $link stdio } " stream and evaluates it. On end of file, " { $link quit-flag } " is set to terminate the listener loop." } -{ $errors "If the expression input by the user throws an error, the error is printed to the " { $link stdio } " stream and the word returns normally." } ; +{ $description "Prompts for an expression on " { $link input-stream } " and evaluates it. On end of file, " { $link quit-flag } " is set to terminate the listener loop." } +{ $errors "If the expression input by the user throws an error, the error is printed to " { $link output-stream } " and the word returns normally." } ; HELP: listener -{ $description "Prompts for expressions on the " { $link stdio } " stream and evaluates them until end of file is reached." } ; +{ $description "Prompts for expressions on " { $link input-stream } " and evaluates them until end of file is reached." } ; HELP: bye { $description "Exits the current listener." } diff --git a/core/listener/listener-tests.factor b/core/listener/listener-tests.factor index 2c05c049a7..24449049e0 100755 --- a/core/listener/listener-tests.factor +++ b/core/listener/listener-tests.factor @@ -51,6 +51,6 @@ IN: listener.tests [ [ ] [ "IN: listener.tests : hello\n\"world\" ;" parse-interactive - drop + drop ] unit-test ] with-file-vocabs diff --git a/core/listener/listener.factor b/core/listener/listener.factor index ddb29bb768..cc4580c2cf 100755 --- a/core/listener/listener.factor +++ b/core/listener/listener.factor @@ -2,8 +2,8 @@ ! See http://factorcode.org/license.txt for BSD license. USING: arrays hashtables io kernel math math.parser memory namespaces parser sequences strings io.styles -io.streams.duplex vectors words generic system combinators -continuations debugger definitions compiler.units accessors ; +vectors words generic system combinators continuations debugger +definitions compiler.units accessors ; IN: listener SYMBOL: quit-flag @@ -35,10 +35,7 @@ GENERIC: stream-read-quot ( stream -- quot/f ) M: object stream-read-quot V{ } clone read-quot-loop ; -M: duplex-stream stream-read-quot - duplex-stream-in stream-read-quot ; - -: read-quot ( -- quot/f ) stdio get stream-read-quot ; +: read-quot ( -- quot/f ) input-stream get stream-read-quot ; : bye ( -- ) quit-flag on ; @@ -46,9 +43,11 @@ M: duplex-stream stream-read-quot "( " in get " )" 3append H{ { background { 1 0.7 0.7 1 } } } format bl flush ; +SYMBOL: error-hook + : listen ( -- ) listener-hook get call prompt. - [ read-quot [ try ] [ bye ] if* ] + [ read-quot [ [ error-hook get call ] recover ] [ bye ] if* ] [ dup parse-error? [ error-hook get call diff --git a/core/math/parser/parser-tests.factor b/core/math/parser/parser-tests.factor index baa6634a9f..15234ee310 100755 --- a/core/math/parser/parser-tests.factor +++ b/core/math/parser/parser-tests.factor @@ -98,3 +98,9 @@ unit-test [ 1 1 >base ] must-fail [ 1 0 >base ] must-fail [ 1 -1 >base ] must-fail + +[ "0.0/0.0" ] [ 0.0 0.0 / number>string ] unit-test + +[ "1.0/0.0" ] [ 1.0 0.0 / number>string ] unit-test + +[ "-1.0/0.0" ] [ -1.0 0.0 / number>string ] unit-test diff --git a/core/math/parser/parser.factor b/core/math/parser/parser.factor index 1a1a080564..d1b8e6fd37 100755 --- a/core/math/parser/parser.factor +++ b/core/math/parser/parser.factor @@ -140,9 +140,9 @@ M: ratio >base M: float >base drop { + { [ dup fp-nan? ] [ drop "0.0/0.0" ] } { [ dup 1.0/0.0 = ] [ drop "1.0/0.0" ] } { [ dup -1.0/0.0 = ] [ drop "-1.0/0.0" ] } - { [ dup fp-nan? ] [ drop "0.0/0.0" ] } [ float>string fix-float ] } cond ; diff --git a/core/parser/parser-docs.factor b/core/parser/parser-docs.factor index b69985fb1d..418278baee 100755 --- a/core/parser/parser-docs.factor +++ b/core/parser/parser-docs.factor @@ -5,7 +5,7 @@ quotations namespaces compiler.units assocs ; IN: parser ARTICLE: "vocabulary-search-shadow" "Shadowing word names" -"If adding a vocabulary to the search path results in a word in another vocabulary becoming inaccessible due to the new vocabulary defining a word with the same name, a message is printed to the " { $link stdio } " stream. Except when debugging suspected name clashes, these messages can be ignored." +"If adding a vocabulary to the search path results in a word in another vocabulary becoming inaccessible due to the new vocabulary defining a word with the same name, we say that the old word has been " { $emphasis "shadowed" } "." $nl "Here is an example where shadowing occurs:" { $code @@ -13,18 +13,18 @@ $nl "USING: sequences io ;" "" ": append" - " \"foe::append calls sequences::append\" print append ;" + " \"foe::append calls sequences:append\" print append ;" "" "IN: fee" "" ": append" - " \"fee::append calls fee::append\" print append ;" + " \"fee::append calls fee:append\" print append ;" "" "IN: fox" "USE: foe" "" ": append" - " \"fox::append calls foe::append\" print append ;" + " \"fox::append calls foe:append\" print append ;" "" "\"1234\" \"5678\" append print" "" @@ -33,12 +33,13 @@ $nl } "When placed in a source file and run, the above code produces the following output:" { $code - "foe::append calls sequences::append" + "foe:append calls sequences:append" "12345678" - "fee::append calls foe::append" - "foe::append calls sequences::append" + "fee:append calls foe:append" + "foe:append calls sequences:append" "12345678" -} ; +} +"The " { $vocab-link "qualified" } " vocabulary contains some tools for helping with shadowing." ; ARTICLE: "vocabulary-search-errors" "Word lookup errors" "If the parser cannot not find a word in the current vocabulary search path, it attempts to look for the word in all loaded vocabularies. Then, one of three things happen:" @@ -215,7 +216,7 @@ HELP: save-location { $description "Saves the location of a definition and associates this definition with the current source file." } ; HELP: parser-notes -{ $var-description "A boolean controlling whether the parser will print various notes and warnings. Switched on by default. If a source file is being run for its effect on the " { $link stdio } " stream, this variable should be switched off, to prevent parser notes from polluting the output." } ; +{ $var-description "A boolean controlling whether the parser will print various notes and warnings. Switched on by default. If a source file is being run for its effect on " { $link output-stream } ", this variable should be switched off, to prevent parser notes from polluting the output." } ; HELP: parser-notes? { $values { "?" "a boolean" } } @@ -506,7 +507,7 @@ HELP: bootstrap-file HELP: eval>string { $values { "str" string } { "output" string } } -{ $description "Evaluates the Factor code in " { $snippet "str" } " with the " { $link stdio } " stream rebound to a string output stream, then outputs the resulting string." } ; +{ $description "Evaluates the Factor code in " { $snippet "str" } " with " { $link output-stream } " rebound to a string output stream, then outputs the resulting string." } ; HELP: staging-violation { $values { "word" word } } diff --git a/core/prettyprint/prettyprint-docs.factor b/core/prettyprint/prettyprint-docs.factor index 2933c8ee6f..f7f0f7ee44 100755 --- a/core/prettyprint/prettyprint-docs.factor +++ b/core/prettyprint/prettyprint-docs.factor @@ -135,7 +135,7 @@ ARTICLE: "prettyprint" "The prettyprinter" $nl "Prettyprinter words are found in the " { $vocab-link "prettyprint" } " vocabulary." $nl -"The key words to print an object to the " { $link stdio } " stream; the first two emit a trailing newline, the second two do not:" +"The key words to print an object to " { $link output-stream } "; the first two emit a trailing newline, the second two do not:" { $subsection . } { $subsection short. } { $subsection pprint } @@ -161,17 +161,17 @@ ABOUT: "prettyprint" HELP: with-pprint { $values { "obj" object } { "quot" quotation } } -{ $description "Sets up the prettyprinter and calls the quotation in a new scope. The quotation should add sections to the top-level block. When the quotation returns, the top-level block is printed to the " { $link stdio } " stream." } ; +{ $description "Sets up the prettyprinter and calls the quotation in a new scope. The quotation should add sections to the top-level block. When the quotation returns, the top-level block is printed to " { $link output-stream } "." } ; HELP: pprint { $values { "obj" object } } -{ $description "Prettyprints an object to the " { $link stdio } " stream. Output is influenced by many variables; see " { $link "prettyprint-variables" } "." } ; +{ $description "Prettyprints an object to " { $link output-stream } ". Output is influenced by many variables; see " { $link "prettyprint-variables" } "." } ; { pprint pprint* with-pprint } related-words HELP: . { $values { "obj" object } } -{ $description "Prettyprints an object to the " { $link stdio } " stream with a trailing line break. Output is influenced by many variables; see " { $link "prettyprint-variables" } "." } ; +{ $description "Prettyprints an object to " { $link output-stream } " with a trailing line break. Output is influenced by many variables; see " { $link "prettyprint-variables" } "." } ; HELP: unparse { $values { "obj" object } { "str" "Factor source string" } } @@ -179,11 +179,11 @@ HELP: unparse HELP: pprint-short { $values { "obj" object } } -{ $description "Prettyprints an object to the " { $link stdio } " stream. This word rebinds printer control variables to enforce ``shorter'' output. See " { $link "prettyprint-variables" } "." } ; +{ $description "Prettyprints an object to " { $link output-stream } ". This word rebinds printer control variables to enforce ``shorter'' output. See " { $link "prettyprint-variables" } "." } ; HELP: short. { $values { "obj" object } } -{ $description "Prettyprints an object to the " { $link stdio } " stream with a trailing line break. This word rebinds printer control variables to enforce ``shorter'' output." } ; +{ $description "Prettyprints an object to " { $link output-stream } " with a trailing line break. This word rebinds printer control variables to enforce ``shorter'' output." } ; HELP: .b { $values { "n" "an integer" } } diff --git a/core/prettyprint/sections/sections-docs.factor b/core/prettyprint/sections/sections-docs.factor index ceb37c2fe4..842a36a13b 100755 --- a/core/prettyprint/sections/sections-docs.factor +++ b/core/prettyprint/sections/sections-docs.factor @@ -15,7 +15,7 @@ HELP: line-limit? HELP: do-indent -{ $description "Outputs the current indent nesting to the " { $link stdio } " stream." } ; +{ $description "Outputs the current indent nesting to " { $link output-stream } "." } ; HELP: fresh-line { $values { "n" "the current column position" } } diff --git a/core/sequences/sequences.factor b/core/sequences/sequences.factor index a63e6d2835..f39bf08e58 100755 --- a/core/sequences/sequences.factor +++ b/core/sequences/sequences.factor @@ -670,9 +670,15 @@ PRIVATE> : unclip ( seq -- rest first ) [ rest ] [ first ] bi ; +: unclip-last ( seq -- butfirst last ) + [ 1 head* ] [ peek ] bi ; + : unclip-slice ( seq -- rest first ) [ rest-slice ] [ first ] bi ; +: unclip-last-slice ( seq -- butfirst last ) + [ 1 head-slice* ] [ peek ] bi ; + : ( seq -- slice ) dup slice? [ { } like ] when 0 over length rot ; inline diff --git a/core/splitting/splitting.factor b/core/splitting/splitting.factor index eb10b9fe4a..62c5121e50 100755 --- a/core/splitting/splitting.factor +++ b/core/splitting/splitting.factor @@ -1,42 +1,72 @@ -! Copyright (C) 2005, 2007 Slava Pestov. +! Copyright (C) 2005, 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: kernel math namespaces strings arrays vectors sequences -sets math.order ; +sets math.order accessors ; IN: splitting -TUPLE: groups seq n sliced? ; +TUPLE: abstract-groups seq n ; -: check-groups 0 <= [ "Invalid group count" throw ] when ; +: check-groups dup 0 <= [ "Invalid group count" throw ] when ; inline + +: construct-groups ( seq n class -- groups ) + >r check-groups r> boa ; inline + +GENERIC: group@ ( n groups -- from to seq ) + +M: abstract-groups nth group@ subseq ; + +M: abstract-groups set-nth group@ 0 swap copy ; + +M: abstract-groups like drop { } like ; + +INSTANCE: abstract-groups sequence + +TUPLE: groups < abstract-groups ; : ( seq n -- groups ) - dup check-groups f groups boa ; inline - -: ( seq n -- groups ) - t over set-groups-sliced? ; + groups construct-groups ; inline M: groups length - dup groups-seq length swap groups-n [ + 1- ] keep /i ; + [ seq>> length ] [ n>> ] bi [ + 1- ] keep /i ; M: groups set-length - [ groups-n * ] keep groups-seq set-length ; + [ n>> * ] [ seq>> ] bi set-length ; -: group@ ( n groups -- from to seq ) - [ groups-n [ * dup ] keep + ] keep - groups-seq [ length min ] keep ; +M: groups group@ + [ n>> [ * dup ] keep + ] [ seq>> ] bi [ length min ] keep ; -M: groups nth - [ group@ ] keep - groups-sliced? [ ] [ subseq ] if ; +TUPLE: sliced-groups < groups ; -M: groups set-nth - group@ 0 swap copy ; +: ( seq n -- groups ) + sliced-groups construct-groups ; inline -M: groups like drop { } like ; +M: sliced-groups nth group@ ; -INSTANCE: groups sequence +TUPLE: clumps < abstract-groups ; + +: ( seq n -- groups ) + clumps construct-groups ; inline + +M: clumps length + [ seq>> length ] [ n>> ] bi - 1+ ; + +M: clumps set-length + [ n>> + 1- ] [ seq>> ] bi set-length ; + +M: clumps group@ + [ n>> over + ] [ seq>> ] bi ; + +TUPLE: sliced-clumps < groups ; + +: ( seq n -- groups ) + sliced-clumps construct-groups ; inline + +M: sliced-clumps nth group@ ; : group ( seq n -- array ) { } like ; +: clump ( seq n -- array ) { } like ; + : ?head ( seq begin -- newseq ? ) 2dup head? [ length tail t ] [ drop f ] if ; diff --git a/core/threads/threads-docs.factor b/core/threads/threads-docs.factor index 3f9ff54ac8..7d8791d493 100755 --- a/core/threads/threads-docs.factor +++ b/core/threads/threads-docs.factor @@ -116,10 +116,13 @@ $nl "Other threads may interrupt the sleep by calling " { $link interrupt } "." } ; HELP: sleep -{ $values { "ms" "a non-negative integer" } } -{ $description "Suspends the current thread for " { $snippet "ms" } " milliseconds." +{ $values { "dt" "a duration" } } +{ $description "Suspends the current thread for the given duration." $nl -"Other threads may interrupt the sleep by calling " { $link interrupt } "." } ; +"Other threads may interrupt the sleep by calling " { $link interrupt } "." } +{ $examples + { $code "USING: threads calendar ;" "10 seconds sleep" } +} ; HELP: interrupt { $values { "thread" thread } } diff --git a/core/threads/threads.factor b/core/threads/threads.factor index 8b89cd5732..cbca7ac029 100755 --- a/core/threads/threads.factor +++ b/core/threads/threads.factor @@ -93,7 +93,7 @@ PRIVATE> r check-registered dup r> sleep-queue heap-push* >>sleep-entry drop ; @@ -153,7 +153,7 @@ M: integer sleep-until M: f sleep-until drop [ drop ] "interrupt" suspend drop ; -GENERIC: sleep ( ms -- ) +GENERIC: sleep ( dt -- ) M: real sleep millis + >integer sleep-until ; diff --git a/extra/asn1/asn1-tests.factor b/extra/asn1/asn1-tests.factor index 329ba8256d..1908e28d39 100755 --- a/extra/asn1/asn1-tests.factor +++ b/extra/asn1/asn1-tests.factor @@ -1,16 +1,16 @@ USING: asn1 asn1.ldap io io.streams.string tools.test ; [ 6 ] [ - "\u000002\u000001\u000006" [ asn-syntax read-ber ] with-stream + "\u000002\u000001\u000006" [ asn-syntax read-ber ] with-input-stream ] unit-test [ "testing" ] [ - "\u000004\u000007testing" [ asn-syntax read-ber ] with-stream + "\u000004\u000007testing" [ asn-syntax read-ber ] with-input-stream ] unit-test [ { 1 { 3 "Administrator" "ad_is_bogus" } } ] [ "0$\u000002\u000001\u000001`\u00001f\u000002\u000001\u000003\u000004\rAdministrator\u000080\u00000bad_is_bogus" - [ asn-syntax read-ber ] with-stream + [ asn-syntax read-ber ] with-input-stream ] unit-test [ diff --git a/extra/asn1/asn1.factor b/extra/asn1/asn1.factor index 32e3602f8f..50102d1929 100644 --- a/extra/asn1/asn1.factor +++ b/extra/asn1/asn1.factor @@ -98,7 +98,7 @@ DEFER: read-ber SYMBOL: end -: (read-array) ( stream -- ) +: (read-array) ( -- ) elements get element-id [ elements get element-syntax read-ber dup end = [ drop ] [ , (read-array) ] if @@ -106,7 +106,7 @@ SYMBOL: end : read-array ( -- array ) [ (read-array) ] { } make ; -: set-case ( -- ) +: set-case ( -- object ) elements get element-newobj elements get element-objtype { { "boolean" [ "\0" = not ] } diff --git a/extra/benchmark/reverse-complement/reverse-complement.factor b/extra/benchmark/reverse-complement/reverse-complement.factor index d83b720187..5fdaf49d8f 100755 --- a/extra/benchmark/reverse-complement/reverse-complement.factor +++ b/extra/benchmark/reverse-complement/reverse-complement.factor @@ -32,13 +32,11 @@ HINTS: do-line vector string ; readln [ do-line (reverse-complement) ] [ show-seq ] if* ; : reverse-complement ( infile outfile -- ) - ascii [ - swap ascii [ - swap [ - 500000 (reverse-complement) - ] with-stream - ] with-disposal - ] with-disposal ; + ascii [ + ascii [ + 500000 (reverse-complement) + ] with-file-reader + ] with-file-writer ; : reverse-complement-in "reverse-complement-in.txt" temp-file ; diff --git a/extra/benchmark/sockets/sockets.factor b/extra/benchmark/sockets/sockets.factor index 25212c7264..1c33bfc4dc 100755 --- a/extra/benchmark/sockets/sockets.factor +++ b/extra/benchmark/sockets/sockets.factor @@ -1,6 +1,6 @@ USING: io.sockets io kernel math threads io.encodings.ascii -debugger tools.time prettyprint concurrency.count-downs -namespaces arrays continuations ; +io.streams.duplex debugger tools.time prettyprint +concurrency.count-downs namespaces arrays continuations ; IN: benchmark.sockets SYMBOL: counter @@ -30,17 +30,17 @@ SYMBOL: counter ] ignore-errors ; : simple-client ( -- ) - server-addr ascii [ + server-addr ascii [ CHAR: b write1 flush number-of-requests [ CHAR: a dup write1 flush read1 assert= ] times counter get count-down - ] with-stream ; + ] with-client ; : stop-server ( -- ) - server-addr ascii [ + server-addr ascii [ CHAR: x write1 - ] with-stream ; + ] with-client ; : clients ( n -- ) dup pprint " clients: " write [ diff --git a/extra/builder/util/util.factor b/extra/builder/util/util.factor index 3b0834b190..c40efaaa04 100644 --- a/extra/builder/util/util.factor +++ b/extra/builder/util/util.factor @@ -16,7 +16,7 @@ IN: builder.util : minutes>ms ( min -- ms ) 60 * 1000 * ; -: file>string ( file -- string ) utf8 [ stdio get contents ] with-file-reader ; +: file>string ( file -- string ) utf8 file-contents ; ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -107,5 +107,5 @@ USE: prettyprint ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! : git-id ( -- id ) - { "git" "show" } utf8 [ readln ] with-stream + { "git" "show" } utf8 [ readln ] with-input-stream " " split second ; diff --git a/extra/checksums/md5/md5.factor b/extra/checksums/md5/md5.factor index 78494a40c0..a385f6d04f 100755 --- a/extra/checksums/md5/md5.factor +++ b/extra/checksums/md5/md5.factor @@ -180,4 +180,4 @@ SINGLETON: md5 INSTANCE: md5 checksum M: md5 checksum-stream ( stream -- byte-array ) - drop [ initialize-md5 stream>md5 get-md5 ] with-stream ; + drop [ initialize-md5 stream>md5 get-md5 ] with-input-stream ; diff --git a/extra/checksums/sha1/sha1.factor b/extra/checksums/sha1/sha1.factor index 2efab873bc..6427e0e8eb 100755 --- a/extra/checksums/sha1/sha1.factor +++ b/extra/checksums/sha1/sha1.factor @@ -111,7 +111,7 @@ SINGLETON: sha1 INSTANCE: sha1 checksum M: sha1 checksum-stream ( stream -- sha1 ) - drop [ initialize-sha1 stream>sha1 get-sha1 ] with-stream ; + drop [ initialize-sha1 stream>sha1 get-sha1 ] with-input-stream ; : sha1-interleave ( string -- seq ) [ zero? ] left-trim diff --git a/extra/concurrency/distributed/distributed.factor b/extra/concurrency/distributed/distributed.factor index 6704272305..c637f4baa3 100755 --- a/extra/concurrency/distributed/distributed.factor +++ b/extra/concurrency/distributed/distributed.factor @@ -3,7 +3,7 @@ USING: serialize sequences concurrency.messaging threads io io.server qualified arrays namespaces kernel io.encodings.binary accessors ; -QUALIFIED: io.sockets +FROM: io.sockets => host-name with-client ; IN: concurrency.distributed SYMBOL: local-node @@ -23,7 +23,7 @@ SYMBOL: local-node : start-node ( port -- ) [ internet-server ] - [ io.sockets:host-name swap io.sockets: ] bi + [ host-name swap ] bi (start-node) ; TUPLE: remote-process id node ; @@ -31,8 +31,7 @@ TUPLE: remote-process id node ; C: remote-process : send-remote-message ( message node -- ) - binary io.sockets: - [ serialize ] with-stream ; + binary [ serialize ] with-client ; M: remote-process send ( message thread -- ) [ id>> 2array ] [ node>> ] bi diff --git a/extra/contributors/contributors.factor b/extra/contributors/contributors.factor index 868e968169..4b7acb468c 100755 --- a/extra/contributors/contributors.factor +++ b/extra/contributors/contributors.factor @@ -7,7 +7,7 @@ IN: contributors : changelog ( -- authors ) image parent-directory [ - "git-log --pretty=format:%an" lines + "git-log --pretty=format:%an" lines ] with-directory ; : patch-counts ( authors -- assoc ) diff --git a/extra/cpu/8080/test/test.factor b/extra/cpu/8080/test/test.factor index 85f27d7e40..f88db2935f 100755 --- a/extra/cpu/8080/test/test.factor +++ b/extra/cpu/8080/test/test.factor @@ -1,5 +1,5 @@ USING: kernel cpu.8080 cpu.8080.emulator math math io -tools.time combinators sequences io.files ; +tools.time combinators sequences io.files io.encodings.ascii ; IN: cpu.8080.test : step ( cpu -- ) @@ -29,7 +29,7 @@ IN: cpu.8080.test : >ppm ( cpu filename -- cpu ) #! Dump the current screen image to a ppm image file with the given name. - [ + ascii [ "P3" print "256 224" print "1" print @@ -45,7 +45,7 @@ IN: cpu.8080.test ] each-8bit drop ] each drop nl ] each - ] with-stream ; + ] with-file-writer ; : time-test ( -- ) test-cpu [ 1000000 run-n drop ] time ; diff --git a/extra/crypto/hmac/hmac.factor b/extra/crypto/hmac/hmac.factor index fe77aa8969..6e30f19775 100755 --- a/extra/crypto/hmac/hmac.factor +++ b/extra/crypto/hmac/hmac.factor @@ -30,7 +30,7 @@ MEMO: opad ( -- seq ) 64 HEX: 5c ; ipad seq-bitxor ; : stream>sha1-hmac ( K stream -- hmac ) - [ init-hmac sha1-hmac ] with-stream ; + [ init-hmac sha1-hmac ] with-input-stream ; : file>sha1-hmac ( K path -- hmac ) binary stream>sha1-hmac ; @@ -39,7 +39,7 @@ MEMO: opad ( -- seq ) 64 HEX: 5c ; binary stream>sha1-hmac ; : stream>md5-hmac ( K stream -- hmac ) - [ init-hmac md5-hmac ] with-stream ; + [ init-hmac md5-hmac ] with-input-stream ; : file>md5-hmac ( K path -- hmac ) binary stream>md5-hmac ; diff --git a/extra/csv/csv.factor b/extra/csv/csv.factor index b1953f5b57..8ba0832b29 100644 --- a/extra/csv/csv.factor +++ b/extra/csv/csv.factor @@ -61,11 +61,11 @@ VAR: delimiter : csv-row ( stream -- row ) init-vars - [ row nip ] with-stream ; + [ row nip ] with-input-stream ; : csv ( stream -- rows ) init-vars - [ [ (csv) ] { } make ] with-stream ; + [ [ (csv) ] { } make ] with-input-stream ; : with-delimiter ( char quot -- ) delimiter swap with-variable ; inline diff --git a/extra/delegate/protocols/protocols.factor b/extra/delegate/protocols/protocols.factor index f1ad068fe2..c1d7e1e4ab 100755 --- a/extra/delegate/protocols/protocols.factor +++ b/extra/delegate/protocols/protocols.factor @@ -1,7 +1,7 @@ ! Copyright (C) 2007 Daniel Ehrenberg ! See http://factorcode.org/license.txt for BSD license. USING: delegate sequences.private sequences assocs prettyprint.sections -io definitions kernel continuations ; +io definitions kernel continuations listener ; IN: delegate.protocols PROTOCOL: sequence-protocol @@ -12,8 +12,10 @@ PROTOCOL: assoc-protocol at* assoc-size >alist set-at assoc-clone-like { assoc-find 1 } delete-at clear-assoc new-assoc assoc-like ; -PROTOCOL: stream-protocol - stream-read1 stream-read stream-read-until dispose +PROTOCOL: input-stream-protocol + stream-read1 stream-read stream-read-until stream-read-quot ; + +PROTOCOL: output-stream-protocol stream-flush stream-write1 stream-write stream-format stream-nl make-span-stream make-block-stream stream-readln make-cell-stream stream-write-table ; diff --git a/extra/destructors/destructors.factor b/extra/destructors/destructors.factor index c3914e9c93..6fc7ab249f 100755 --- a/extra/destructors/destructors.factor +++ b/extra/destructors/destructors.factor @@ -1,7 +1,7 @@ ! Copyright (C) 2007 Doug Coleman. ! See http://factorcode.org/license.txt for BSD license. -USING: continuations io.backend libc kernel namespaces -sequences system vectors ; +USING: continuations io.backend io.nonblocking libc kernel +namespaces sequences system vectors ; IN: destructors SYMBOL: error-destructors @@ -59,10 +59,8 @@ TUPLE: handle-destructor alien ; C: handle-destructor -HOOK: destruct-handle io-backend ( obj -- ) - M: handle-destructor dispose ( obj -- ) - handle-destructor-alien destruct-handle ; + handle-destructor-alien close-handle ; : close-always ( handle -- ) add-always-destructor ; diff --git a/extra/editors/jedit/jedit.factor b/extra/editors/jedit/jedit.factor index e4f19781ef..fe9abc0e76 100755 --- a/extra/editors/jedit/jedit.factor +++ b/extra/editors/jedit/jedit.factor @@ -25,11 +25,11 @@ IN: editors.jedit ] with-byte-writer ; : send-jedit-request ( request -- ) - jedit-server-info "localhost" rot binary [ + jedit-server-info "localhost" rot binary [ 4 >be write dup length 2 >be write write - ] with-stream ; + ] with-client ; : jedit-location ( file line -- ) number>string "+line:" prepend 2array diff --git a/extra/gap-buffer/tags.txt b/extra/gap-buffer/tags.txt index fd3a2d285a..b5e4471134 100644 --- a/extra/gap-buffer/tags.txt +++ b/extra/gap-buffer/tags.txt @@ -1,2 +1,2 @@ collections -collections sequences +sequences diff --git a/core/io/streams/duplex/authors.txt b/extra/geo-ip/authors.txt similarity index 100% rename from core/io/streams/duplex/authors.txt rename to extra/geo-ip/authors.txt diff --git a/extra/geo-ip/geo-ip.factor b/extra/geo-ip/geo-ip.factor new file mode 100644 index 0000000000..5926dd596d --- /dev/null +++ b/extra/geo-ip/geo-ip.factor @@ -0,0 +1,46 @@ +USING: kernel sequences io.files io.launcher io.encodings.ascii +io.streams.string http.client sequences.lib combinators +math.parser math.vectors math.intervals interval-maps memoize +csv accessors assocs strings math splitting ; +IN: geo-ip + +: db-path "IpToCountry.csv" temp-file ; + +: db-url "http://software77.net/cgi-bin/ip-country/geo-ip.pl?action=download" ; + +: download-db ( -- path ) + db-path dup exists? [ + db-url over ".gz" append download-to + { "gunzip" } over ".gz" append (normalize-path) suffix try-process + ] unless ; + +TUPLE: ip-entry from to registry assigned city cntry country ; + +: parse-ip-entry ( row -- ip-entry ) + 7 firstn { + [ string>number ] + [ string>number ] + [ ] + [ ] + [ ] + [ ] + [ ] + } spread ip-entry boa ; + +MEMO: ip-db ( -- seq ) + download-db ascii file-lines + [ "#" head? not ] filter "\n" join csv + [ parse-ip-entry ] map ; + +MEMO: ip-intervals ( -- interval-map ) + ip-db [ [ [ from>> ] [ to>> ] bi [a,b] ] keep ] { } map>assoc + ; + +GENERIC: lookup-ip ( ip -- ip-entry ) + +M: string lookup-ip + "." split [ string>number ] map + { HEX: 1000000 HEX: 10000 HEX: 100 1 } v. + lookup-ip ; + +M: integer lookup-ip ip-intervals interval-at ; diff --git a/extra/geo-ip/summary.txt b/extra/geo-ip/summary.txt new file mode 100644 index 0000000000..402d3230f1 --- /dev/null +++ b/extra/geo-ip/summary.txt @@ -0,0 +1 @@ +IP address geolocation using database from http://software77.net/cgi-bin/ip-country/ diff --git a/extra/geo-ip/tags.txt b/extra/geo-ip/tags.txt new file mode 100644 index 0000000000..0aef4feca8 --- /dev/null +++ b/extra/geo-ip/tags.txt @@ -0,0 +1 @@ +enterprise diff --git a/extra/gesture-logger/gesture-logger.factor b/extra/gesture-logger/gesture-logger.factor index 1977efd3f9..b9de7c1b74 100644 --- a/extra/gesture-logger/gesture-logger.factor +++ b/extra/gesture-logger/gesture-logger.factor @@ -15,13 +15,13 @@ TUPLE: gesture-logger stream ; M: gesture-logger handle-gesture* drop dup T{ button-down } = [ over request-focus ] when - swap gesture-logger-stream [ . ] with-stream* + swap gesture-logger-stream [ . ] with-output-stream* t ; M: gesture-logger user-input* gesture-logger-stream [ "User input: " write print - ] with-stream* t ; + ] with-output-stream* t ; : gesture-logger ( -- ) [ diff --git a/extra/help/cookbook/cookbook.factor b/extra/help/cookbook/cookbook.factor index 995b8540f5..c2e12469c5 100755 --- a/extra/help/cookbook/cookbook.factor +++ b/extra/help/cookbook/cookbook.factor @@ -205,8 +205,8 @@ ARTICLE: "cookbook-io" "Input and output cookbook" } "Send some bytes to a remote host:" { $code - "\"myhost\" 1033 " - "[ { 12 17 102 } >string write ] with-stream" + "\"myhost\" 1033 " + "[ { 12 17 102 } >string write ] with-client" } { $references { } diff --git a/extra/help/handbook/handbook.factor b/extra/help/handbook/handbook.factor index a9e94466c4..a8271a0e3b 100755 --- a/extra/help/handbook/handbook.factor +++ b/extra/help/handbook/handbook.factor @@ -31,7 +31,7 @@ $nl { { $snippet "set-" { $emphasis "foo" } } { "sets " { $snippet "foo" } " to a new value" } { $links set-length } } { { $snippet { $emphasis "foo" } "-" { $emphasis "bar" } } { "(tuple accessors) outputs the value of the " { $snippet "bar" } " slot of the " { $snippet "foo" } " at the top of the stack" } { } } { { $snippet "set-" { $emphasis "foo" } "-" { $emphasis "bar" } } { "(tuple mutators) sets the value of the " { $snippet "bar" } " slot of the " { $snippet "foo" } " at the top of the stack" } { } } - { { $snippet "with-" { $emphasis "foo" } } { "performs some kind of initialization and cleanup related to " { $snippet "foo" } ", usually in a new dynamic scope" } { $links with-scope with-stream } } + { { $snippet "with-" { $emphasis "foo" } } { "performs some kind of initialization and cleanup related to " { $snippet "foo" } ", usually in a new dynamic scope" } { $links with-scope with-input-stream with-output-stream } } { { $snippet "$" { $emphasis "foo" } } { "help markup" } { $links $heading $emphasis } } } { $heading "Stack effect conventions" } @@ -193,17 +193,19 @@ ARTICLE: "io" "Input and output" "Utilities:" { $subsection "stream-binary" } { $subsection "styles" } -{ $heading "Files" } -{ $subsection "io.files" } -{ $subsection "io.mmap" } -{ $subsection "io.monitors" } { $heading "Encodings" } { $subsection "encodings-introduction" } { $subsection "io.encodings" } { $subsection "io.encodings.string" } -{ $heading "Other features" } +{ $heading "Files" } +{ $subsection "io.files" } +{ $subsection "io.mmap" } +{ $subsection "io.monitors" } +{ $heading "Communications" } { $subsection "network-streams" } { $subsection "io.launcher" } +{ $subsection "io.pipes" } +{ $heading "Other features" } { $subsection "io.timeouts" } { $subsection "checksums" } ; diff --git a/extra/help/help-docs.factor b/extra/help/help-docs.factor index d4981751e2..f20ce89263 100755 --- a/extra/help/help-docs.factor +++ b/extra/help/help-docs.factor @@ -126,7 +126,7 @@ HELP: $title HELP: help { $values { "topic" "an article name or a word" } } { $description - "Displays a help article or documentation associated to a word on the " { $link stdio } " stream." + "Displays a help article or documentation associated to a word on " { $link output-stream } "." } ; HELP: about @@ -151,7 +151,7 @@ HELP: $index HELP: ($index) { $values { "articles" "a sequence of help articles" } } -{ $description "Writes a list of " { $link $subsection } " elements to the " { $link stdio } " stream." } ; +{ $description "Writes a list of " { $link $subsection } " elements to " { $link output-stream } "." } ; HELP: xref-help { $description "Update help cross-referencing. Usually this is done automatically." } ; @@ -168,11 +168,11 @@ HELP: $predicate HELP: print-element { $values { "element" "a markup element" } } -{ $description "Prints a markup element to the " { $link stdio } " stream." } ; +{ $description "Prints a markup element to " { $link output-stream } "." } ; HELP: print-content { $values { "element" "a markup element" } } -{ $description "Prints a top-level markup element to the " { $link stdio } " stream." } ; +{ $description "Prints a top-level markup element to " { $link output-stream } "." } ; HELP: simple-element { $class-description "Class of simple elements, which are just arrays of elements." } ; diff --git a/extra/help/tutorial/tutorial.factor b/extra/help/tutorial/tutorial.factor index fffcda69b6..cafa758c7e 100755 --- a/extra/help/tutorial/tutorial.factor +++ b/extra/help/tutorial/tutorial.factor @@ -135,7 +135,7 @@ $nl { $code "[ Letter? ] filter >lower" } "This code starts with a string on the stack, removes non-alphabetical characters, and converts the result to lower case, leaving a new string on the stack. We put this code in a new word, and add the new word to " { $snippet "palindrome.factor" } ":" { $code ": normalize ( str -- newstr ) [ Letter? ] filter >lower ;" } -"You will need to add " { $vocab-link "unicode.categories" } " to the vocabulary search path, so that " { $link Letter? } " can be used in the source file." +"You will need to add " { $vocab-link "unicode.case" } " and " { $vocab-link "unicode.categories" } " to the vocabulary search path, so that " { $link Letter? } " can be used in the source file." $nl "We modify " { $snippet "palindrome?" } " to first apply " { $snippet "normalize" } " to its input:" { $code ": palindrome? ( str -- ? ) normalize dup reverse = ;" } diff --git a/extra/html/html-tests.factor b/extra/html/html-tests.factor index ce320ca75b..9f1ce6b689 100644 --- a/extra/html/html-tests.factor +++ b/extra/html/html-tests.factor @@ -24,7 +24,7 @@ IN: html.tests ] unit-test [ "<" ] [ - [ "<" H{ } stdio get format-html-span ] make-html-string + [ "<" H{ } output-stream get format-html-span ] make-html-string ] unit-test TUPLE: funky town ; diff --git a/extra/html/html.factor b/extra/html/html.factor index 7a0fa17c9a..c154c35223 100755 --- a/extra/html/html.factor +++ b/extra/html/html.factor @@ -44,7 +44,7 @@ TUPLE: html-sub-stream style stream ; rot html-sub-stream-stream ; : delegate-write ( string -- ) - stdio get delegate stream-write ; + output-stream get delegate stream-write ; : object-link-tag ( style quot -- ) presented pick at [ @@ -101,7 +101,7 @@ TUPLE: html-sub-stream style stream ; : format-html-span ( string style stream -- ) [ [ [ drop delegate-write ] span-tag ] object-link-tag - ] with-stream* ; + ] with-output-stream* ; TUPLE: html-span-stream ; @@ -134,7 +134,7 @@ M: html-span-stream dispose : format-html-div ( string style stream -- ) [ [ [ delegate-write ] div-tag ] object-link-tag - ] with-stream* ; + ] with-output-stream* ; TUPLE: html-block-stream ; @@ -184,17 +184,17 @@ M: html-stream stream-write-table ( grid style stream -- ) ] with each ] with each - ] with-stream* ; + ] with-output-stream* ; M: html-stream make-cell-stream ( style stream -- stream' ) (html-sub-stream) ; M: html-stream stream-nl ( stream -- ) - dup test-last-div? [ drop ] [ [
] with-stream* ] if ; + dup test-last-div? [ drop ] [ [
] with-output-stream* ] if ; ! Utilities : with-html-stream ( quot -- ) - stdio get swap with-stream* ; inline + output-stream get swap with-output-stream* ; inline : xhtml-preamble "" write-html diff --git a/extra/http/client/client.factor b/extra/http/client/client.factor index 7762b01843..17882277a3 100755 --- a/extra/http/client/client.factor +++ b/extra/http/client/client.factor @@ -3,7 +3,8 @@ USING: assocs http kernel math math.parser namespaces sequences io io.sockets io.streams.string io.files io.timeouts strings splitting calendar continuations accessors vectors math.order -io.encodings.8-bit io.encodings.binary fry debugger inspector ; +io.encodings.8-bit io.encodings.binary io.streams.duplex +fry debugger inspector ; IN: http.client : max-redirects 10 ; @@ -26,73 +27,56 @@ DEFER: http-request : store-path ( request path -- request ) "?" split1 >r >>path r> dup [ query>assoc ] when >>query ; -: request-with-url ( url request -- request ) - swap parse-url >r >r store-path r> >>host r> >>port ; - -! This is all pretty complex because it needs to handle -! HTTP redirects, which might be absolute or relative -: absolute-redirect ( url -- request ) - request get request-with-url ; - -: relative-redirect ( path -- request ) - request get swap store-path ; +: request-with-url ( request url -- request ) + parse-url >r >r store-path r> >>host r> >>port ; SYMBOL: redirects : absolute-url? ( url -- ? ) [ "http://" head? ] [ "https://" head? ] bi or ; -: do-redirect ( response -- response stream ) - dup response-code 300 399 between? [ - stdio get dispose +: do-redirect ( response data -- response data ) + over code>> 300 399 between? [ + drop redirects inc redirects get max-redirects < [ - header>> "location" swap at - dup absolute-url? [ - absolute-redirect - ] [ - relative-redirect - ] if "GET" >>method http-request + request get + swap "location" header dup absolute-url? + [ request-with-url ] [ store-path ] if + "GET" >>method http-request ] [ too-many-redirects ] if - ] [ - stdio get - ] if ; - -: close-on-error ( stream quot -- ) - '[ , with-stream* ] [ ] pick '[ , dispose ] cleanup ; inline + ] when ; PRIVATE> -: http-request ( request -- response stream ) - dup request [ - dup request-addr latin1 - 1 minutes over set-timeout - [ - write-request flush - read-response - do-redirect - ] close-on-error - ] with-variable ; - : read-chunks ( -- ) read-crlf ";" split1 drop hex> dup { f 0 } member? [ drop ] [ read % read-crlf "" assert= read-chunks ] if ; -: do-chunked-encoding ( response stream -- response stream/string ) - over "transfer-encoding" header "chunked" = [ - [ [ read-chunks ] "" make ] with-stream - ] when ; +: read-response-body ( response -- response data ) + dup "transfer-encoding" header "chunked" = + [ [ read-chunks ] "" make ] [ input-stream get contents ] if ; + +: http-request ( request -- response data ) + dup request [ + dup request-addr latin1 [ + 1 minutes timeouts + write-request + read-response + read-response-body + ] with-client + do-redirect + ] with-variable ; : ( url -- request ) - request-with-url "GET" >>method ; + + swap request-with-url + "GET" >>method ; -: string-or-contents ( stream/string -- string ) - dup string? [ contents ] unless ; - -: http-get-stream ( url -- response stream/string ) - http-request do-chunked-encoding ; +: http-get* ( url -- response data ) + http-request ; : success? ( code -- ? ) 200 = ; @@ -112,29 +96,24 @@ M: download-failed error. over code>> success? [ nip ] [ download-failed ] if ; : http-get ( url -- string ) - http-get-stream string-or-contents check-response ; + http-get* check-response ; : download-name ( url -- name ) file-name "?" split1 drop "/" ?tail drop ; : download-to ( url file -- ) #! Downloads the contents of a URL to a file. - swap http-get-stream check-response - dup string? [ - latin1 [ write ] with-file-writer - ] [ - [ swap latin1 stream-copy ] with-disposal - ] if ; + >r http-get r> latin1 [ write ] with-file-writer ; : download ( url -- ) dup download-name download-to ; : ( content-type content url -- request ) - request-with-url - "POST" >>method - swap >>post-data - swap >>post-data-type ; + "POST" >>method + swap request-with-url + swap >>post-data + swap >>post-data-type ; -: http-post ( content-type content url -- response string ) - http-request do-chunked-encoding string-or-contents ; +: http-post ( content-type content url -- response data ) + http-request ; diff --git a/extra/http/http-tests.factor b/extra/http/http-tests.factor index 76c48d38f1..07b34f17c3 100755 --- a/extra/http/http-tests.factor +++ b/extra/http/http-tests.factor @@ -31,6 +31,7 @@ IN: http.tests [ H{ { "a" { "b" "c" } } } ] [ "a=b&a=c" query>assoc ] unit-test [ "a=3" ] [ { { "a" 3 } } assoc>query ] unit-test + : lf>crlf "\n" split "\r\n" join ; STRING: read-request-test-1 @@ -183,12 +184,12 @@ test-db [ ! Try with a slightly malformed request [ t ] [ - "localhost" 1237 ascii [ + "localhost" 1237 ascii [ "GET nested HTTP/1.0\r\n" write flush "\r\n" write flush read-crlf drop read-header - ] with-stream "location" swap at "/" head? + ] with-client "location" swap at "/" head? ] unit-test [ "http://localhost:1237/redirect-loop" http-get ] diff --git a/extra/http/http.factor b/extra/http/http.factor index 98c1d8e74c..786210123d 100755 --- a/extra/http/http.factor +++ b/extra/http/http.factor @@ -472,7 +472,7 @@ M: string write-response-body* write ; M: callable write-response-body* call ; -M: object write-response-body* stdio get stream-copy ; +M: object write-response-body* output-stream get stream-copy ; : write-response-body ( response -- response ) dup body>> write-response-body* ; diff --git a/extra/http/server/auth/admin/admin.factor b/extra/http/server/auth/admin/admin.factor index e762103d7b..21e1a6181b 100644 --- a/extra/http/server/auth/admin/admin.factor +++ b/extra/http/server/auth/admin/admin.factor @@ -82,10 +82,8 @@ IN: http.server.auth.admin same-password-twice - user new "username" value >>username select-tuple [ - user-exists? on - validation-failed - ] when + user new "username" value >>username select-tuple + [ user-exists ] when "username" value "realname" value >>realname diff --git a/extra/http/server/cgi/cgi.factor b/extra/http/server/cgi/cgi.factor index 509943faa8..20eb7318d0 100755 --- a/extra/http/server/cgi/cgi.factor +++ b/extra/http/server/cgi/cgi.factor @@ -1,7 +1,7 @@ ! Copyright (C) 2007, 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: namespaces kernel assocs io.files combinators -arrays io.launcher io http.server.static http.server +USING: namespaces kernel assocs io.files io.streams.duplex +combinators arrays io.launcher io http.server.static http.server http accessors sequences strings math.parser fry ; IN: http.server.cgi @@ -51,9 +51,9 @@ IN: http.server.cgi 200 >>code "CGI output follows" >>message swap '[ - , stdio get swap [ + , output-stream get swap [ post? [ request get post-data>> write flush ] when - stdio get swap (stream-copy) + input-stream get swap (stream-copy) ] with-stream ] >>body ; diff --git a/extra/http/server/server.factor b/extra/http/server/server.factor index f6dd6c57bb..70c1e9a1f5 100755 --- a/extra/http/server/server.factor +++ b/extra/http/server/server.factor @@ -260,15 +260,13 @@ SYMBOL: exit-continuation bi ] recover ; -: default-timeout 1 minutes stdio get set-timeout ; - : ?refresh-all ( -- ) development-mode get-global [ global [ refresh-all ] bind ] when ; : handle-client ( -- ) [ - default-timeout + 1 minutes timeouts ?refresh-all read-request do-request diff --git a/extra/http/server/static/static.factor b/extra/http/server/static/static.factor index 2ecc347d76..b9a8e9d46e 100755 --- a/extra/http/server/static/static.factor +++ b/extra/http/server/static/static.factor @@ -36,7 +36,7 @@ TUPLE: file-responder root hook special allow-listings ; [ size>> "content-length" set-header ] [ modified>> "last-modified" set-header ] bi ] - [ '[ , binary stdio get stream-copy ] >>body ] bi + [ '[ , binary output-stream get stream-copy ] >>body ] bi ] ; : serve-static ( filename mime-type -- response ) diff --git a/extra/interval-maps/authors.txt b/extra/interval-maps/authors.txt new file mode 100755 index 0000000000..504363d316 --- /dev/null +++ b/extra/interval-maps/authors.txt @@ -0,0 +1 @@ +Daniel Ehrenberg diff --git a/extra/interval-maps/interval-maps-docs.factor b/extra/interval-maps/interval-maps-docs.factor new file mode 100755 index 0000000000..1a862fbe2d --- /dev/null +++ b/extra/interval-maps/interval-maps-docs.factor @@ -0,0 +1,29 @@ +USING: help.markup help.syntax ; +IN: interval-maps + +HELP: interval-at* +{ $values { "key" "an object" } { "map" "an interval map" } { "value" "the value for the key, or f" } { "?" "whether the key is present" } } +{ $description "Looks up a key in an interval map, returning the corresponding value if the item is in an interval in the map, and a boolean flag. The operation takes O(log n) time." } ; + +HELP: interval-at +{ $values { "key" "an object" } { "map" "an interval map" } { "value" "the value for the key, or f" } } +{ $description "Looks up a key in an interval map, returning the value of the corresponding interval, or f if the interval is not present in the map." } ; + +HELP: interval-key? +{ $values { "key" "an object" } { "map" "an interval map" } { "?" "a boolean" } } +{ $description "Tests whether an object is in an interval in the interval map, returning t if the object is present." } ; + +HELP: +{ $values { "specification" "an assoc" } { "map" "an interval map" } } +{ $description "From a specification, produce an interval tree. The specification is an assoc where the keys are intervals, or pairs of numbers to represent intervals, or individual numbers to represent singleton intervals. The values are the values int he interval map. Construction time is O(n log n)." } ; + +ARTICLE: "interval-maps" "Interval maps" +"Interval maps are a mechanism, similar to assocs, where a set of closed intervals of keys are associated with values. As such, interval maps do not conform to the assoc protocol, because intervals of floats, for example, can be used, and it is impossible to get a list of keys in between." +"The following operations are used to query interval maps:" +{ $subsection interval-at* } +{ $subsection interval-at } +{ $subsection interval-key? } +"Use the following to construct interval maps" +{ $subsection } ; + +ABOUT: "interval-maps" diff --git a/extra/interval-maps/interval-maps-tests.factor b/extra/interval-maps/interval-maps-tests.factor new file mode 100755 index 0000000000..54d2e9d26b --- /dev/null +++ b/extra/interval-maps/interval-maps-tests.factor @@ -0,0 +1,13 @@ +USING: kernel namespaces interval-maps tools.test ; +IN: interval-maps.test + +SYMBOL: test + +[ ] [ { { { 4 8 } 3 } { 1 2 } } test set ] unit-test +[ 3 ] [ 5 test get interval-at ] unit-test +[ 3 ] [ 8 test get interval-at ] unit-test +[ 3 ] [ 4 test get interval-at ] unit-test +[ f ] [ 9 test get interval-at ] unit-test +[ 2 ] [ 1 test get interval-at ] unit-test +[ f ] [ 2 test get interval-at ] unit-test +[ f ] [ 0 test get interval-at ] unit-test diff --git a/extra/interval-maps/interval-maps.factor b/extra/interval-maps/interval-maps.factor new file mode 100755 index 0000000000..bc23d0d346 --- /dev/null +++ b/extra/interval-maps/interval-maps.factor @@ -0,0 +1,41 @@ +USING: kernel sequences arrays math.intervals accessors +math.order sorting math assocs ; +IN: interval-maps + +TUPLE: interval-map array ; + +> from>> first <=> ] binsearch ; + +GENERIC: >interval ( object -- interval ) +M: number >interval [a,a] ; +M: sequence >interval first2 [a,b] ; +M: interval >interval ; + +: all-intervals ( sequence -- intervals ) + [ >r >interval r> ] assoc-map ; + +: ensure-disjoint ( intervals -- intervals ) + dup keys [ interval-intersect not ] monotonic? + [ "Intervals are not disjoint" throw ] unless ; +PRIVATE> + +: interval-at* ( key map -- value ? ) + array>> [ find-interval ] 2keep swapd nth + [ nip value>> ] [ interval>> interval-contains? ] 2bi + fixup-value ; + +: interval-at ( key map -- value ) interval-at* drop ; +: interval-key? ( key map -- ? ) interval-at* nip ; + +: ( specification -- map ) + all-intervals ensure-disjoint + [ [ first to>> ] compare ] sort + [ interval-node boa ] { } assoc>map + interval-map boa ; diff --git a/extra/interval-maps/summary.txt b/extra/interval-maps/summary.txt new file mode 100755 index 0000000000..d25263260e --- /dev/null +++ b/extra/interval-maps/summary.txt @@ -0,0 +1 @@ +Interval maps for disjoint closed ranges diff --git a/extra/interval-maps/tags.txt b/extra/interval-maps/tags.txt new file mode 100755 index 0000000000..5e9549f425 --- /dev/null +++ b/extra/interval-maps/tags.txt @@ -0,0 +1 @@ +collections diff --git a/extra/io/launcher/launcher-docs.factor b/extra/io/launcher/launcher-docs.factor index dadb627fc0..45bbec20e3 100755 --- a/extra/io/launcher/launcher-docs.factor +++ b/extra/io/launcher/launcher-docs.factor @@ -1,7 +1,7 @@ ! Copyright (C) 2007, 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: help.markup help.syntax quotations kernel io math -calendar ; +USING: help.markup help.syntax quotations kernel io io.files +math calendar ; IN: io.launcher ARTICLE: "io.launcher.command" "Specifying a command" @@ -26,10 +26,10 @@ $nl "To specify redirection, set the " { $snippet "stdin" } ", " { $snippet "stdout" } " and " { $snippet "stderr" } " slots of a " { $link process } " to one of the following values:" { $list { { $link f } " - default value; the stream is either inherited from the current process, or is a " { $link } " pipe" } - { { $link +inherit+ } " - the stream is inherited from the current process, overriding a " { $link } " pipe" } { { $link +closed+ } " - the stream is closed; reads will return end of file and writes will fails" } { { $link +stdout+ } " - a special value for the " { $snippet "stderr" } " slot only, indicating that the standard output and standard error streams should be merged" } { "a path name - the stream is sent to the given file, which must exist for input and is created automatically on output" } + { "an " { $link appender } " wrapping a path name - output is sent to the end given file, as with " { $link } } { "a file stream or a socket - the stream is connected to the given Factor stream, which cannot be used again from within Factor and must be closed after the process has been started" } } ; @@ -47,12 +47,16 @@ ARTICLE: "io.launcher.priority" "Setting process priority" HELP: +closed+ { $description "Possible value for the " { $snippet "stdin" } ", " { $snippet "stdout" } ", and " { $snippet "stderr" } " slots of a " { $link process } "." } ; -HELP: +inherit+ -{ $description "Possible value for the " { $snippet "stdin" } ", " { $snippet "stdout" } ", and " { $snippet "stderr" } " slots of a " { $link process } "." } ; - HELP: +stdout+ { $description "Possible value for the " { $snippet "stderr" } " slot of a " { $link process } "." } ; +HELP: appender +{ $class-description "An object representing a file to append to. Instances are created with " { $link } "." } ; + +HELP: +{ $values { "path" "a pathname string" } { "appender" appender } } +{ $description "Creates an object which may be stored in the " { $snippet "stdout" } " or " { $snippet "stderr" } " slot of a " { $link process } " instance." } ; + HELP: +prepend-environment+ { $description "Possible value of " { $snippet "environment-mode" } " slot of a " { $link process } "." $nl @@ -138,13 +142,6 @@ HELP: { "stream" "a bidirectional stream" } } { $description "Launches a process and redirects its input and output via a pair of pipes which may be read and written as a stream of the given encoding." } ; -HELP: with-process-stream -{ $values - { "desc" "a launch descriptor" } - { "quot" quotation } - { "status" "an exit code" } } -{ $description "Calls " { $snippet "quot" } " in a dynamic scope where " { $link stdio } " is rebound to a process stream. After the quotation returns, waits for the process to end and outputs the exit code." } ; - HELP: wait-for-process { $values { "process" process } { "status" integer } } { $description "If the process is still running, waits for it to exit, otherwise outputs the exit code immediately. Can be called multiple times on the same process." } ; @@ -175,8 +172,9 @@ ARTICLE: "io.launcher.launch" "Launching processes" { $subsection try-process } { $subsection run-detached } "Redirecting standard input and output to a pipe:" -{ $subsection } -{ $subsection with-process-stream } ; +{ $subsection } +{ $subsection } +{ $subsection } ; ARTICLE: "io.launcher.examples" "Launcher examples" "Starting a command and waiting for it to finish:" @@ -212,7 +210,7 @@ ARTICLE: "io.launcher.examples" "Launcher examples" " " " swap >>stderr" " \"report\" >>command" - " ascii lines sort reverse [ print ] each" + " ascii lines sort reverse [ print ] each" "] with-disposal" } ; diff --git a/extra/io/launcher/launcher-tests.factor b/extra/io/launcher/launcher-tests.factor index bacb8eb5a9..003f382020 100755 --- a/extra/io/launcher/launcher-tests.factor +++ b/extra/io/launcher/launcher-tests.factor @@ -2,3 +2,5 @@ IN: io.launcher.tests USING: tools.test io.launcher ; \ must-infer +\ must-infer +\ must-infer diff --git a/extra/io/launcher/launcher.factor b/extra/io/launcher/launcher.factor index 6ee8660528..286febd589 100755 --- a/extra/io/launcher/launcher.factor +++ b/extra/io/launcher/launcher.factor @@ -1,9 +1,10 @@ ! Copyright (C) 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: io io.backend io.timeouts system kernel namespaces -strings hashtables sequences assocs combinators vocabs.loader -init threads continuations math io.encodings io.streams.duplex -io.nonblocking accessors concurrency.flags ; +USING: io io.backend io.timeouts io.pipes system kernel +namespaces strings hashtables sequences assocs combinators +vocabs.loader init threads continuations math io.encodings +io.streams.duplex io.nonblocking io.streams.duplex accessors +concurrency.flags destructors ; IN: io.launcher TUPLE: process < identity-tuple @@ -26,9 +27,12 @@ handle status killed ; SYMBOL: +closed+ -SYMBOL: +inherit+ SYMBOL: +stdout+ +TUPLE: appender path ; + +: ( path -- appender ) appender boa ; + SYMBOL: +prepend-environment+ SYMBOL: +replace-environment+ SYMBOL: +append-environment+ @@ -145,20 +149,67 @@ M: process set-timeout set-process-timeout ; M: process timed-out kill-process ; -HOOK: (process-stream) io-backend ( process -- handle in out ) +M: object pipeline-element-quot + [ + >process + swap >>stdout + swap >>stdin + run-detached + ] curry ; -: ( desc encoding -- stream process ) - >r >process dup dup (process-stream) - r> -roll - process-started ; +M: process wait-for-pipeline-element wait-for-process ; + +: ( process encoding -- process stream ) + [ + >r (pipe) { + [ add-error-destructor ] + [ + swap >process + [ swap out>> or ] change-stdout + run-detached + ] + [ out>> close-handle ] + [ in>> ] + } cleave r> + ] with-destructors ; + +: ( desc encoding -- stream ) + nip ; inline + +: ( process encoding -- process stream ) + [ + >r (pipe) { + [ add-error-destructor ] + [ + swap >process + [ swap in>> or ] change-stdout + run-detached + ] + [ in>> close-handle ] + [ out>> ] + } cleave r> + ] with-destructors ; + +: ( desc encoding -- stream ) + nip ; inline + +: ( process encoding -- process stream ) + [ + >r (pipe) (pipe) { + [ [ add-error-destructor ] bi@ ] + [ + rot >process + [ swap out>> or ] change-stdout + [ swap in>> or ] change-stdin + run-detached + ] + [ [ in>> close-handle ] [ out>> close-handle ] bi* ] + [ [ in>> ] [ out>> ] bi* ] + } 2cleave r> + ] with-destructors ; : ( desc encoding -- stream ) - drop ; inline - -: with-process-stream ( desc quot -- status ) - swap >r - [ swap with-stream ] keep - r> wait-for-process ; inline + nip ; inline : notify-exit ( process status -- ) >>status @@ -168,9 +219,9 @@ HOOK: (process-stream) io-backend ( process -- handle in out ) GENERIC: underlying-handle ( stream -- handle ) -M: port underlying-handle port-handle ; +M: port underlying-handle handle>> ; M: duplex-stream underlying-handle - dup duplex-stream-in underlying-handle - swap duplex-stream-out underlying-handle tuck = - [ "Invalid duplex stream" throw ] when ; + [ in>> underlying-handle ] + [ out>> underlying-handle ] bi + [ = [ "Invalid duplex stream" throw ] when ] keep ; diff --git a/extra/io/nonblocking/nonblocking.factor b/extra/io/nonblocking/nonblocking.factor index fc8ade5758..d25d4b7050 100755 --- a/extra/io/nonblocking/nonblocking.factor +++ b/extra/io/nonblocking/nonblocking.factor @@ -1,9 +1,9 @@ ! Copyright (C) 2005, 2008 Slava Pestov, Doug Coleman ! See http://factorcode.org/license.txt for BSD license. USING: math kernel io sequences io.buffers io.timeouts generic -byte-vectors system io.streams.duplex io.encodings math.order -io.backend continuations debugger classes byte-arrays namespaces -splitting dlists assocs io.encodings.binary inspector accessors ; +byte-vectors system io.encodings math.order io.backend +continuations debugger classes byte-arrays namespaces splitting +dlists assocs io.encodings.binary inspector accessors ; IN: io.nonblocking SYMBOL: default-buffer-size diff --git a/extra/io/pipes/pipes-docs.factor b/extra/io/pipes/pipes-docs.factor new file mode 100644 index 0000000000..d51ae94bc7 --- /dev/null +++ b/extra/io/pipes/pipes-docs.factor @@ -0,0 +1,47 @@ +USING: help.markup help.syntax continuations io ; +IN: io.pipes + +HELP: pipe +{ $class-description "A low-level pipe. Instances are created by calling " { $link (pipe) } " and closed by calling " { $link dispose } "." } ; + +HELP: (pipe) +{ $values { "pipe" pipe } } +{ $description "Opens a new pipe. This is a low-level word; the " { $link } " and " { $link run-pipeline } " words can be used in most cases instead." } ; + +HELP: +{ $values { "encoding" "an encoding specifier" } { "stream" "a bidirectional stream" } } +{ $description "Opens a new pipe and wraps it in a stream. Data written from the stream can be read back from the same stream instance." } +{ $notes "Pipe streams must be disposed by calling " { $link dispose } " or " { $link with-disposal } " to avoid resource leaks." } ; + +HELP: run-pipeline +{ $values { "seq" "a sequence of pipeline components" } { "results" "a sequence of pipeline results" } } +{ $description + "Creates a pipe between each pipeline component, with the output of each component becoming the input of the next." + $nl + "The first component reads input from " { $link input-stream } " and the last component writes output to " { $link output-stream } "." + $nl + "Each component runs in its own thread, and the word returns when all components finish executing. Each component outputs a result value." + $nl + "Pipeline components must be one of the following:" + { $list + { "A quotation. The quotation is called with both " { $link input-stream } " and " { $link output-stream } " rebound, except for the first and last pipeline components, and it must output a single value." } + { "A process launch descriptor. See " { $link "io.launcher.descriptors" } "." } + } +} +{ $examples + "Print the lines of a log file which contain the string ``error'', sort them and filter out duplicates, using Unix shell commands only:" + { $code "{ \"cat log.txt\" \"grep error\" \"sort\" \"uniq\" } run-pipeline" } +} ; + +ARTICLE: "io.pipes" "Pipes" +"A " { $emphasis "pipe" } " is a unidirectional channel for transfer of bytes. Data written to one end of the pipe can be read from the other. Pipes can be used to pass data between processes; they can also be used within a single process to implement communication between coroutines." +$nl +"Low-level pipes:" +{ $subsection pipe } +{ $subsection (pipe) } +"High-level pipe streams:" +{ $subsection } +"Pipelines of coroutines and processes:" +{ $subsection run-pipeline } ; + +ABOUT: "io.pipes" diff --git a/extra/io/pipes/pipes-tests.factor b/extra/io/pipes/pipes-tests.factor new file mode 100755 index 0000000000..c1b37f6efc --- /dev/null +++ b/extra/io/pipes/pipes-tests.factor @@ -0,0 +1,26 @@ +USING: io io.pipes io.streams.string io.encodings.utf8 +io.streams.duplex io.encodings namespaces continuations +tools.test kernel ; +IN: io.pipes.tests + +[ "Hello" ] [ + utf8 [ + "Hello" print flush + readln + ] with-stream +] unit-test + +[ { } ] [ { } run-pipeline ] unit-test +[ { f } ] [ { [ f ] } run-pipeline ] unit-test +[ { "Hello" } ] [ + "Hello" [ + { [ input-stream [ utf8 ] change readln ] } run-pipeline + ] with-string-reader +] unit-test + +[ { f "Hello" } ] [ + { + [ output-stream [ utf8 ] change "Hello" print flush f ] + [ input-stream [ utf8 ] change readln ] + } run-pipeline +] unit-test diff --git a/extra/io/pipes/pipes.factor b/extra/io/pipes/pipes.factor new file mode 100644 index 0000000000..3e91c5e48e --- /dev/null +++ b/extra/io/pipes/pipes.factor @@ -0,0 +1,56 @@ +! Copyright (C) 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: io.encodings io.backend io.nonblocking io.streams.duplex +io splitting sequences sequences.lib namespaces kernel +destructors math concurrency.combinators accessors +arrays continuations quotations ; +IN: io.pipes + +TUPLE: pipe in out ; + +M: pipe dispose ( pipe -- ) + [ in>> close-handle ] [ out>> close-handle ] bi ; + +HOOK: (pipe) io-backend ( -- pipe ) + +: ( encoding -- stream ) + [ + >r (pipe) + [ add-error-destructor ] + [ in>> ] + [ out>> ] + tri + r> + ] with-destructors ; + +: with-fds ( input-fd output-fd quot -- ) + >r >r [ dup add-always-destructor ] [ input-stream get ] if* r> r> [ + >r [ dup add-always-destructor ] [ output-stream get ] if* r> + with-output-stream* + ] 2curry with-input-stream* ; inline + +: ( n -- pipes ) + [ (pipe) dup add-always-destructor ] replicate + f f pipe boa [ prefix ] [ suffix ] bi + 2 ; + +: with-pipe-fds ( seq -- results ) + [ + [ length dup zero? [ drop { } ] [ 1- ] if ] keep + [ >r [ first in>> ] [ second out>> ] bi r> 2curry ] 2map + [ call ] parallel-map + ] with-destructors ; + +GENERIC: pipeline-element-quot ( obj -- quot ) + +M: callable pipeline-element-quot + [ with-fds ] curry ; + +GENERIC: wait-for-pipeline-element ( obj -- result ) + +M: object wait-for-pipeline-element ; + +: run-pipeline ( seq -- results ) + [ pipeline-element-quot ] map + with-pipe-fds + [ wait-for-pipeline-element ] map ; diff --git a/extra/io/server/server-docs.factor b/extra/io/server/server-docs.factor index 7eda48f747..50f38cb146 100755 --- a/extra/io/server/server-docs.factor +++ b/extra/io/server/server-docs.factor @@ -3,8 +3,8 @@ IN: io.server HELP: with-server { $values { "seq" "a sequence of address specifiers" } { "service" "a string or " { $link f } } { "encoding" "an encoding to use for client connections" } { "quot" "a quotation" } } -{ $description "Starts a TCP/IP server. The quotation is called in a new thread for each client connection, with the client connection being the " { $link stdio } " stream. Client connections are logged to the " { $link stdio } " stream at the time the server was started." } ; +{ $description "Starts a TCP/IP server. The quotation is called in a new thread for each client connection, with the client connection being both the " { $link input-stream } " and " { $link output-stream } "." } ; HELP: with-datagrams { $values { "seq" "a sequence of address specifiers" } { "service" "a string or " { $link f } } { "quot" "a quotation" } } -{ $description "Starts a UDP/IP server. The quotation is called for each datagram packet received. Datagram packets are logged to the " { $link stdio } " stream at the time the server was started." } ; +{ $description "Starts a UDP/IP server. The quotation is called for each datagram packet received." } ; diff --git a/extra/io/server/server.factor b/extra/io/server/server.factor index 45e3b1de66..1d626a9e15 100755 --- a/extra/io/server/server.factor +++ b/extra/io/server/server.factor @@ -1,8 +1,8 @@ ! Copyright (C) 2003, 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: io io.sockets io.files logging continuations kernel -math math.parser namespaces parser sequences strings -prettyprint debugger quotations calendar +USING: io io.sockets io.files io.streams.duplex logging +continuations kernel math math.parser namespaces parser +sequences strings prettyprint debugger quotations calendar threads concurrency.combinators assocs ; IN: io.server diff --git a/extra/io/sockets/sockets-docs.factor b/extra/io/sockets/sockets-docs.factor index ad78b4631c..ee3cb3aa7b 100755 --- a/extra/io/sockets/sockets-docs.factor +++ b/extra/io/sockets/sockets-docs.factor @@ -14,6 +14,7 @@ ARTICLE: "network-addressing" "Address specifiers" ARTICLE: "network-connection" "Connection-oriented networking" "Network connections can be established with this word:" { $subsection } +{ $subsection with-client } "Connection-oriented network servers are implemented by first opening a server socket, then waiting for connections:" { $subsection } { $subsection accept } diff --git a/extra/io/sockets/sockets.factor b/extra/io/sockets/sockets.factor index 859dcb4cdc..f835f0beb2 100755 --- a/extra/io/sockets/sockets.factor +++ b/extra/io/sockets/sockets.factor @@ -1,7 +1,8 @@ ! Copyright (C) 2007, 2008 Slava Pestov, Daniel Ehrenberg. ! See http://factorcode.org/license.txt for BSD license. USING: generic kernel io.backend namespaces continuations -sequences arrays io.encodings io.nonblocking accessors ; +sequences arrays io.encodings io.nonblocking io.streams.duplex +accessors ; IN: io.sockets TUPLE: local path ; @@ -30,6 +31,9 @@ M: object (client) ((client)) ; : ( addrspec encoding -- stream ) >r (client) r> ; +: with-client ( addrspec encoding quot -- ) + >r r> with-stream ; inline + HOOK: (server) io-backend ( addrspec -- handle ) : ( addrspec encoding -- server ) diff --git a/extra/io/streams/duplex/authors.txt b/extra/io/streams/duplex/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/extra/io/streams/duplex/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/extra/io/streams/duplex/duplex-docs.factor b/extra/io/streams/duplex/duplex-docs.factor new file mode 100755 index 0000000000..15d401ad68 --- /dev/null +++ b/extra/io/streams/duplex/duplex-docs.factor @@ -0,0 +1,39 @@ +USING: help.markup help.syntax io continuations quotations ; +IN: io.streams.duplex + +ARTICLE: "io.streams.duplex" "Duplex streams" +"Duplex streams combine an input stream and an output stream into a bidirectional stream." +{ $subsection duplex-stream } +{ $subsection } +"A pair of combinators for rebinding both default streams at once:" +{ $subsection with-stream } +{ $subsection with-stream* } ; + +ABOUT: "io.streams.duplex" + +HELP: duplex-stream +{ $class-description "A bidirectional stream wrapping an input and output stream." } ; + +HELP: +{ $values { "in" "an input stream" } { "out" "an output stream" } { "stream" " a duplex stream" } } +{ $description "Creates a duplex stream. Writing to a duplex stream will write to " { $snippet "out" } ", and reading from a duplex stream will read from " { $snippet "in" } ". Closing a duplex stream closes both the input and output streams." } ; + +HELP: stream-closed-twice +{ $error-description "This error is thrown when performing an I/O operation on a " { $link duplex-stream } " which has been closed with " { $link dispose } "." } ; + +HELP: with-stream +{ $values { "stream" duplex-stream } { "quot" quotation } } +{ $description "Calls the quotation in a new dynamic scope, with both " { $link input-stream } " and " { $link output-stream } " rebound to " { $snippet "stream" } ". The stream is closed if the quotation returns or throws an error." } ; + +HELP: with-stream* +{ $values { "stream" duplex-stream } { "quot" quotation } } +{ $description "Calls the quotation in a new dynamic scope, with both " { $link input-stream } " and " { $link output-stream } " rebound to " { $snippet "stream" } "." } +{ $notes "This word does not close the stream. Compare with " { $link with-stream } "." } ; + +HELP: +{ $values { "stream-in" "an input stream" } + { "stream-out" "an output stream" } + { "encoding" "an encoding descriptor" } + { "duplex" "an encoded duplex stream" } } +{ $description "Wraps the given streams in an encoder or decoder stream, and puts them together in a duplex stream for input and output. If either input stream is already encoded, that encoding is stripped off before it is reencoded. The encoding descriptor must conform to the " { $link "encodings-protocol" } "." } +$low-level-note ; diff --git a/core/io/streams/duplex/duplex-tests.factor b/extra/io/streams/duplex/duplex-tests.factor similarity index 100% rename from core/io/streams/duplex/duplex-tests.factor rename to extra/io/streams/duplex/duplex-tests.factor diff --git a/core/io/streams/duplex/duplex.factor b/extra/io/streams/duplex/duplex.factor similarity index 51% rename from core/io/streams/duplex/duplex.factor rename to extra/io/streams/duplex/duplex.factor index 40f0cb6e73..cb96d8017a 100755 --- a/core/io/streams/duplex/duplex.factor +++ b/extra/io/streams/duplex/duplex.factor @@ -1,6 +1,8 @@ ! Copyright (C) 2005, 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: kernel continuations io accessors ; +USING: kernel continuations io io.encodings io.encodings.private +io.timeouts debugger inspector listener accessors delegate +delegate.protocols ; IN: io.streams.duplex ! We ensure that the stream can only be closed once, to preserve @@ -13,6 +15,9 @@ TUPLE: duplex-stream in out closed ; ERROR: stream-closed-twice ; +M: stream-closed-twice summary + drop "Attempt to perform I/O on closed stream" ; + -M: duplex-stream stream-flush - out stream-flush ; +CONSULT: input-stream-protocol duplex-stream in ; -M: duplex-stream stream-readln - in stream-readln ; +CONSULT: output-stream-protocol duplex-stream out ; -M: duplex-stream stream-read1 - in stream-read1 ; - -M: duplex-stream stream-read-until - in stream-read-until ; - -M: duplex-stream stream-read-partial - in stream-read-partial ; - -M: duplex-stream stream-read - in stream-read ; - -M: duplex-stream stream-write1 - out stream-write1 ; - -M: duplex-stream stream-write - out stream-write ; - -M: duplex-stream stream-nl - out stream-nl ; - -M: duplex-stream stream-format - out stream-format ; - -M: duplex-stream make-span-stream - out make-span-stream ; - -M: duplex-stream make-block-stream - out make-block-stream ; - -M: duplex-stream make-cell-stream - out make-cell-stream ; - -M: duplex-stream stream-write-table - out stream-write-table ; +M: duplex-stream set-timeout + [ in set-timeout ] [ out set-timeout ] 2bi ; M: duplex-stream dispose #! The output stream is closed first, in case both streams @@ -75,3 +45,12 @@ M: duplex-stream dispose [ dup out>> dispose ] [ dup in>> dispose ] [ ] cleanup ] unless drop ; + +: ( stream-in stream-out encoding -- duplex ) + tuck reencode >r redecode r> ; + +: with-stream* ( stream quot -- ) + >r [ in>> ] [ out>> ] bi r> with-streams* ; inline + +: with-stream ( stream quot -- ) + >r [ in>> ] [ out>> ] bi r> with-streams ; inline diff --git a/core/io/streams/duplex/summary.txt b/extra/io/streams/duplex/summary.txt similarity index 100% rename from core/io/streams/duplex/summary.txt rename to extra/io/streams/duplex/summary.txt diff --git a/extra/io/streams/null/null.factor b/extra/io/streams/null/null.factor index eee66239be..384a3806b8 100755 --- a/extra/io/streams/null/null.factor +++ b/extra/io/streams/null/null.factor @@ -1,25 +1,38 @@ ! Copyright (C) 2007 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. IN: io.streams.null -USING: kernel io io.timeouts continuations ; +USING: kernel io io.timeouts io.streams.duplex continuations ; TUPLE: null-stream ; M: null-stream dispose drop ; M: null-stream set-timeout 2drop ; -M: null-stream stream-readln drop f ; -M: null-stream stream-read1 drop f ; -M: null-stream stream-read-until 2drop f f ; -M: null-stream stream-read 2drop f ; -M: null-stream stream-write1 2drop ; -M: null-stream stream-write 2drop ; -M: null-stream stream-nl drop ; -M: null-stream stream-flush drop ; -M: null-stream stream-format 3drop ; -M: null-stream make-span-stream nip ; -M: null-stream make-block-stream nip ; -M: null-stream make-cell-stream nip ; -M: null-stream stream-write-table 3drop ; + +TUPLE: null-reader < null-stream ; + +M: null-reader stream-readln drop f ; +M: null-reader stream-read1 drop f ; +M: null-reader stream-read-until 2drop f f ; +M: null-reader stream-read 2drop f ; + +TUPLE: null-writer < null-stream ; + +M: null-writer stream-write1 2drop ; +M: null-writer stream-write 2drop ; +M: null-writer stream-nl drop ; +M: null-writer stream-flush drop ; +M: null-writer stream-format 3drop ; +M: null-writer make-span-stream nip ; +M: null-writer make-block-stream nip ; +M: null-writer make-cell-stream nip ; +M: null-writer stream-write-table 3drop ; + +: with-null-reader ( quot -- ) + T{ null-reader } swap with-input-stream* ; inline + +: with-null-writer ( quot -- ) + T{ null-writer } swap with-output-stream* ; inline : with-null-stream ( quot -- ) - T{ null-stream } swap with-stream* ; inline + T{ duplex-stream f T{ null-reader } T{ null-writer } } + swap with-stream* ; inline diff --git a/extra/io/timeouts/timeouts.factor b/extra/io/timeouts/timeouts.factor index f1031e98e2..f9ffd5e98f 100755 --- a/extra/io/timeouts/timeouts.factor +++ b/extra/io/timeouts/timeouts.factor @@ -1,20 +1,16 @@ ! Copyright (C) 2008 Slava Pestov, Doug Coleman ! See http://factorcode.org/license.txt for BSD license. -USING: kernel calendar alarms io.streams.duplex io.encodings ; +USING: kernel calendar alarms io io.encodings accessors +namespaces ; IN: io.timeouts ! Won't need this with new slot accessors GENERIC: timeout ( obj -- dt/f ) GENERIC: set-timeout ( dt/f obj -- ) -M: duplex-stream set-timeout - 2dup - duplex-stream-in set-timeout - duplex-stream-out set-timeout ; +M: decoder set-timeout stream>> set-timeout ; -M: decoder set-timeout decoder-stream set-timeout ; - -M: encoder set-timeout encoder-stream set-timeout ; +M: encoder set-timeout stream>> set-timeout ; GENERIC: timed-out ( obj -- ) @@ -29,3 +25,7 @@ M: object timed-out drop ; ] [ 2drop call ] if ; inline + +: timeouts ( dt -- ) + [ input-stream get set-timeout ] + [ output-stream get set-timeout ] bi ; diff --git a/extra/io/unix/backend/backend.factor b/extra/io/unix/backend/backend.factor index ba4e587d13..08ff526f14 100644 --- a/extra/io/unix/backend/backend.factor +++ b/extra/io/unix/backend/backend.factor @@ -1,10 +1,10 @@ ! Copyright (C) 2004, 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: alien generic assocs kernel kernel.private math -io.nonblocking sequences strings structs sbufs -threads unix vectors io.buffers io.backend io.encodings -io.streams.duplex math.parser continuations system libc -qualified namespaces io.timeouts io.encodings.utf8 accessors ; +io.nonblocking sequences strings structs sbufs threads unix +vectors io.buffers io.backend io.encodings math.parser +continuations system libc qualified namespaces io.timeouts +io.encodings.utf8 accessors ; QUALIFIED: io IN: io.unix.backend @@ -78,7 +78,8 @@ M: integer init-handle ( fd -- ) #! since on OS X 10.3, this operation fails from init-io #! when running the Factor.app (presumably because fd 0 and #! 1 are closed). - F_SETFL O_NONBLOCK fcntl drop ; + [ F_SETFL O_NONBLOCK fcntl drop ] + [ F_SETFD FD_CLOEXEC fcntl drop ] bi ; M: integer close-handle ( fd -- ) close ; diff --git a/extra/io/unix/launcher/launcher-tests.factor b/extra/io/unix/launcher/launcher-tests.factor index 7e527196be..97ffc5287f 100755 --- a/extra/io/unix/launcher/launcher-tests.factor +++ b/extra/io/unix/launcher/launcher-tests.factor @@ -31,16 +31,7 @@ accessors kernel sequences io.encodings.utf8 ; "cat" "launcher-test-1" temp-file 2array - ascii contents -] unit-test - -[ f ] [ - - "cat" - "launcher-test-1" temp-file - 2array >>command - +inherit+ >>stdout - ascii contents + ascii contents ] unit-test [ ] [ @@ -59,7 +50,7 @@ accessors kernel sequences io.encodings.utf8 ; "cat" "launcher-test-1" temp-file 2array - ascii contents + ascii contents ] unit-test [ ] [ @@ -77,14 +68,14 @@ accessors kernel sequences io.encodings.utf8 ; "cat" "launcher-test-1" temp-file 2array - ascii contents + ascii contents ] unit-test [ t ] [ "env" >>command { { "A" "B" } } >>environment - ascii lines + ascii lines "A=B" swap member? ] unit-test @@ -93,7 +84,7 @@ accessors kernel sequences io.encodings.utf8 ; "env" >>command { { "A" "B" } } >>environment +replace-environment+ >>environment-mode - ascii lines + ascii lines ] unit-test [ "hi\n" ] [ @@ -107,3 +98,15 @@ accessors kernel sequences io.encodings.utf8 ; temp-directory "aloha" append-path utf8 file-contents ] unit-test + +[ ] [ "append-test" temp-file delete-file ] unit-test + +[ "hi\nhi\n" ] [ + 2 [ + + "echo hi" >>command + "append-test" temp-file >>stdout + try-process + ] times + "append-test" temp-file utf8 file-contents +] unit-test diff --git a/extra/io/unix/launcher/launcher.factor b/extra/io/unix/launcher/launcher.factor index 2c1e6261c0..043b2bd73e 100755 --- a/extra/io/unix/launcher/launcher.factor +++ b/extra/io/unix/launcher/launcher.factor @@ -1,10 +1,12 @@ ! Copyright (C) 2007, 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: io io.backend io.launcher io.nonblocking io.unix.backend -io.unix.files io.nonblocking sequences kernel namespaces math -system alien.c-types debugger continuations arrays assocs -combinators unix.process strings threads unix -io.unix.launcher.parser accessors io.files io.files.private ; +USING: kernel namespaces math system sequences debugger +continuations arrays assocs combinators alien.c-types strings +threads accessors +io io.backend io.launcher io.nonblocking io.files +io.files.private io.unix.files io.unix.backend +io.unix.launcher.parser +unix unix.process ; IN: io.unix.launcher ! Search unix first @@ -34,7 +36,8 @@ USE: unix : reset-fd ( fd -- ) #! We drop the error code because on *BSD, fcntl of #! /dev/null fails. - F_SETFL 0 fcntl drop ; + [ F_SETFL 0 fcntl drop ] + [ F_SETFD 0 fcntl drop ] bi ; : redirect-inherit ( obj mode fd -- ) 2nip reset-fd ; @@ -43,19 +46,20 @@ USE: unix >r >r normalize-path r> file-mode open dup io-error r> redirect-fd ; +: redirect-file-append ( obj mode fd -- ) + >r drop path>> normalize-path open-append r> redirect-fd ; + : redirect-closed ( obj mode fd -- ) >r >r drop "/dev/null" r> r> redirect-file ; -: redirect-stream ( obj mode fd -- ) - >r drop underlying-handle dup reset-fd r> redirect-fd ; - : redirect ( obj mode fd -- ) { { [ pick not ] [ redirect-inherit ] } { [ pick string? ] [ redirect-file ] } + { [ pick appender? ] [ redirect-file-append ] } { [ pick +closed+ eq? ] [ redirect-closed ] } - { [ pick +inherit+ eq? ] [ redirect-closed ] } - [ redirect-stream ] + { [ pick integer? ] [ >r drop dup reset-fd r> redirect-fd ] } + [ >r >r underlying-handle r> r> redirect ] } cond ; : ?closed dup +closed+ eq? [ drop "/dev/null" ] when ; @@ -90,27 +94,10 @@ M: unix run-process* ( process -- pid ) M: unix kill-process* ( pid -- ) SIGTERM kill io-error ; -: open-pipe ( -- pair ) - 2 "int" dup pipe zero? - [ 2 c-int-array> ] [ drop f ] if ; - -: setup-stdio-pipe ( stdin stdout -- ) - 2dup first close second close - >r first 0 dup2 drop r> second 1 dup2 drop ; - -M: unix (process-stream) - >r open-pipe open-pipe r> - [ >r setup-stdio-pipe r> spawn-process ] curry - [ -rot 2dup second close first close ] - with-fork - first swap second ; - : find-process ( handle -- process ) processes get swap [ nip swap handle>> = ] curry assoc-find 2drop ; -! Inefficient process wait polling, used on Linux and Solaris. -! On BSD and Mac OS X, we use kqueue() which scales better. M: unix wait-for-processes ( -- ? ) -1 0 tuck WNOHANG waitpid dup 0 <= [ diff --git a/extra/io/unix/pipes/pipes-tests.factor b/extra/io/unix/pipes/pipes-tests.factor new file mode 100644 index 0000000000..8ff9ba61c8 --- /dev/null +++ b/extra/io/unix/pipes/pipes-tests.factor @@ -0,0 +1,16 @@ +USING: tools.test io.pipes io.unix.pipes io.encodings.utf8 +io.encodings io namespaces sequences ; +IN: io.unix.pipes.tests + +[ { 0 0 } ] [ { "ls" "grep x" } run-pipeline ] unit-test + +[ { 0 f 0 } ] [ + { + "ls" + [ + input-stream [ utf8 ] change + input-stream get lines reverse [ print ] each f + ] + "grep x" + } run-pipeline +] unit-test diff --git a/extra/io/unix/pipes/pipes.factor b/extra/io/unix/pipes/pipes.factor new file mode 100644 index 0000000000..4fc5acf634 --- /dev/null +++ b/extra/io/unix/pipes/pipes.factor @@ -0,0 +1,12 @@ +! Copyright (C) 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: system alien.c-types kernel unix math sequences +qualified io.unix.backend io.nonblocking ; +IN: io.unix.pipes +QUALIFIED: io.pipes + +M: unix io.pipes:(pipe) ( -- pair ) + 2 "int" + dup pipe io-error + 2 c-int-array> first2 + [ [ init-handle ] bi@ ] [ io.pipes:pipe boa ] 2bi ; diff --git a/extra/io/unix/unix-tests.factor b/extra/io/unix/unix-tests.factor index ff315bc529..61a667b70f 100755 --- a/extra/io/unix/unix-tests.factor +++ b/extra/io/unix/unix-tests.factor @@ -1,6 +1,7 @@ USING: io.files io.sockets io kernel threads namespaces tools.test continuations strings byte-arrays -sequences prettyprint system io.encodings.binary io.encodings.ascii ; +sequences prettyprint system io.encodings.binary io.encodings.ascii +io.streams.duplex ; IN: io.unix.tests ! Unix domain stream sockets @@ -24,12 +25,11 @@ yield [ { "Hello world" "FOO" } ] [ [ - socket-server ascii - [ + socket-server ascii [ readln , "XYZ" print flush readln , - ] with-stream + ] with-client ] { } make ] unit-test @@ -125,16 +125,16 @@ datagram-client delete-file ! Invalid parameter tests [ - image binary [ stdio get accept ] with-file-reader + image binary [ input-stream get accept ] with-file-reader ] must-fail [ - image binary [ stdio get receive ] with-file-reader + image binary [ input-stream get receive ] with-file-reader ] must-fail [ image binary [ B{ 1 2 } datagram-server - stdio get send + input-stream get send ] with-file-reader ] must-fail diff --git a/extra/io/unix/unix.factor b/extra/io/unix/unix.factor index 1e5638fb4a..e8e7135e1a 100755 --- a/extra/io/unix/unix.factor +++ b/extra/io/unix/unix.factor @@ -1,5 +1,6 @@ -USING: io.unix.backend io.unix.files io.unix.sockets io.timeouts -io.unix.launcher io.unix.mmap io.backend combinators namespaces -system vocabs.loader sequences words init ; +USING: io.unix.backend io.unix.files io.unix.sockets +io.unix.launcher io.unix.mmap io.unix.pipes io.timeouts +io.backend combinators namespaces system vocabs.loader +sequences words init ; "io.unix." os word-name append require diff --git a/extra/io/windows/launcher/launcher.factor b/extra/io/windows/launcher/launcher.factor index 670ea18f5e..a5d7338cd6 100755 --- a/extra/io/windows/launcher/launcher.factor +++ b/extra/io/windows/launcher/launcher.factor @@ -2,7 +2,7 @@ ! See http://factorcode.org/license.txt for BSD license. USING: alien alien.c-types arrays continuations io io.windows io.windows.nt.pipes libc io.nonblocking -io.streams.duplex windows.types math windows.kernel32 +windows.types math windows.kernel32 namespaces io.launcher kernel sequences windows.errors splitting system threads init strings combinators io.backend accessors concurrency.flags io.files assocs diff --git a/extra/io/windows/nt/files/files.factor b/extra/io/windows/nt/files/files.factor index c9f17147d3..8839410d91 100755 --- a/extra/io/windows/nt/files/files.factor +++ b/extra/io/windows/nt/files/files.factor @@ -52,6 +52,10 @@ M: winnt CreateFile-flags ( DWORD -- DWORD ) M: winnt FileArgs-overlapped ( port -- overlapped ) make-overlapped ; +M: winnt open-append + [ dup file-info size>> ] [ drop 0 ] recover + >r (open-append) r> ; + : update-file-ptr ( n port -- ) port-handle dup win32-file-ptr [ diff --git a/extra/io/windows/nt/launcher/launcher-tests.factor b/extra/io/windows/nt/launcher/launcher-tests.factor index 8b13b9b3b9..c5c0e6dec2 100755 --- a/extra/io/windows/nt/launcher/launcher-tests.factor +++ b/extra/io/windows/nt/launcher/launcher-tests.factor @@ -1,7 +1,7 @@ IN: io.windows.launcher.nt.tests USING: io.launcher tools.test calendar accessors namespaces kernel system arrays io io.files io.encodings.ascii -sequences parser assocs hashtables math ; +sequences parser assocs hashtables math continuations ; [ ] [ @@ -77,7 +77,7 @@ sequences parser assocs hashtables math ; vm "-script" "stderr.factor" 3array >>command "err2.txt" temp-file >>stderr - ascii lines first + ascii lines first ] with-directory ] unit-test @@ -89,7 +89,7 @@ sequences parser assocs hashtables math ; "extra/io/windows/nt/launcher/test" resource-path [ vm "-script" "env.factor" 3array >>command - ascii contents + ascii contents ] with-directory eval os-envs = @@ -101,7 +101,7 @@ sequences parser assocs hashtables math ; vm "-script" "env.factor" 3array >>command +replace-environment+ >>environment-mode os-envs >>environment - ascii contents + ascii contents ] with-directory eval os-envs = @@ -112,7 +112,7 @@ sequences parser assocs hashtables math ; vm "-script" "env.factor" 3array >>command { { "A" "B" } } >>environment - ascii contents + ascii contents ] with-directory eval "A" swap at @@ -124,7 +124,7 @@ sequences parser assocs hashtables math ; vm "-script" "env.factor" 3array >>command { { "HOME" "XXX" } } >>environment +prepend-environment+ >>environment-mode - ascii contents + ascii contents ] with-directory eval "HOME" swap at "XXX" = @@ -140,3 +140,18 @@ sequences parser assocs hashtables math ; [ ] [ "dir.txt" temp-file delete-file ] unit-test ] times + +[ "append-test" temp-file delete-file ] ignore-errors + +[ "Hello appender\r\nHello appender\r\n" ] [ + 2 [ + "resource:extra/io/windows/nt/launcher/test" [ + + vm "-script" "append.factor" 3array >>command + "append-test" temp-file >>stdout + try-process + ] with-directory + ] times + + "append-test" temp-file ascii file-contents +] unit-test diff --git a/extra/io/windows/nt/launcher/launcher.factor b/extra/io/windows/nt/launcher/launcher.factor index f57902608f..39edd931b1 100755 --- a/extra/io/windows/nt/launcher/launcher.factor +++ b/extra/io/windows/nt/launcher/launcher.factor @@ -1,7 +1,7 @@ ! Copyright (C) 2007, 2008 Doug Coleman, Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: alien alien.c-types arrays continuations destructors io -io.windows libc io.nonblocking io.streams.duplex windows.types +io.windows libc io.nonblocking io.pipes windows.types math windows.kernel32 windows namespaces io.launcher kernel sequences windows.errors assocs splitting system strings io.windows.launcher io.windows.nt.pipes io.backend io.files @@ -19,15 +19,25 @@ IN: io.windows.nt.launcher DuplicateHandle win32-error=0/f ] keep *void* ; +! /dev/null simulation +: null-input ( -- pipe ) + (pipe) [ in>> handle>> ] [ out>> close-handle ] bi ; + +: null-output ( -- pipe ) + (pipe) [ in>> close-handle ] [ out>> handle>> ] bi ; + +: null-pipe ( mode -- pipe ) + { + { GENERIC_READ [ null-input ] } + { GENERIC_WRITE [ null-output ] } + } case ; + ! The below code is based on the example given in ! http://msdn2.microsoft.com/en-us/library/ms682499.aspx : redirect-default ( default obj access-mode create-mode -- handle ) 3drop ; -: redirect-inherit ( default obj access-mode create-mode -- handle ) - 4drop f ; - : redirect-closed ( default obj access-mode create-mode -- handle ) drop 2nip null-pipe ; @@ -41,25 +51,34 @@ IN: io.windows.nt.launcher f ! template file CreateFile dup invalid-handle? dup close-always ; +: redirect-append ( default path access-mode create-mode -- handle ) + >r >r path>> r> r> + drop OPEN_ALWAYS + redirect-file + dup 0 FILE_END set-file-pointer ; + : set-inherit ( handle ? -- ) >r HANDLE_FLAG_INHERIT r> >BOOLEAN SetHandleInformation win32-error=0/f ; -: redirect-stream ( default stream access-mode create-mode -- handle ) +: redirect-handle ( default handle access-mode create-mode -- handle ) 2drop nip - underlying-handle win32-file-handle - duplicate-handle dup t set-inherit ; + handle>> duplicate-handle dup t set-inherit ; + +: redirect-stream ( default stream access-mode create-mode -- handle ) + >r >r underlying-handle r> r> redirect-handle ; : redirect ( default obj access-mode create-mode -- handle ) { { [ pick not ] [ redirect-default ] } - { [ pick +inherit+ eq? ] [ redirect-inherit ] } { [ pick +closed+ eq? ] [ redirect-closed ] } { [ pick string? ] [ redirect-file ] } + { [ pick appender? ] [ redirect-append ] } + { [ pick win32-file? ] [ redirect-handle ] } [ redirect-stream ] } cond ; : default-stdout ( args -- handle ) - stdout-pipe>> dup [ pipe-out ] when ; + stdout-pipe>> dup [ out>> ] when ; : redirect-stdout ( process args -- handle ) default-stdout @@ -85,7 +104,7 @@ IN: io.windows.nt.launcher ] if ; : default-stdin ( args -- handle ) - stdin-pipe>> dup [ pipe-in ] when ; + stdin-pipe>> dup [ in>> ] when ; : redirect-stdin ( process args -- handle ) default-stdin @@ -95,46 +114,8 @@ IN: io.windows.nt.launcher redirect STD_INPUT_HANDLE GetStdHandle or ; -: add-pipe-dtors ( pipe -- ) - dup - in>> close-later - out>> close-later ; - -: fill-stdout-pipe ( args -- args ) - - dup add-pipe-dtors - dup pipe-in f set-inherit - >>stdout-pipe ; - -: fill-stdin-pipe ( args -- args ) - - dup add-pipe-dtors - dup pipe-out f set-inherit - >>stdin-pipe ; - M: winnt fill-redirection ( process args -- ) [ 2dup redirect-stdout ] keep lpStartupInfo>> set-STARTUPINFO-hStdOutput [ 2dup redirect-stderr ] keep lpStartupInfo>> set-STARTUPINFO-hStdError [ 2dup redirect-stdin ] keep lpStartupInfo>> set-STARTUPINFO-hStdInput 2drop ; - -M: winnt (process-stream) - [ - current-directory get (normalize-path) cd - - dup make-CreateProcess-args - - fill-stdout-pipe - fill-stdin-pipe - - tuck fill-redirection - - dup call-CreateProcess - - dup stdin-pipe>> pipe-in CloseHandle drop - dup stdout-pipe>> pipe-out CloseHandle drop - - dup lpProcessInformation>> - over stdout-pipe>> in>> f - rot stdin-pipe>> out>> f - ] with-destructors ; diff --git a/extra/io/windows/nt/launcher/test/append.factor b/extra/io/windows/nt/launcher/test/append.factor new file mode 100755 index 0000000000..4c1de0c5f9 --- /dev/null +++ b/extra/io/windows/nt/launcher/test/append.factor @@ -0,0 +1,2 @@ +USE: io +"Hello appender" print diff --git a/extra/io/windows/nt/launcher/test/stderr.factor b/extra/io/windows/nt/launcher/test/stderr.factor index 0b97387cf7..f22f50e406 100755 --- a/extra/io/windows/nt/launcher/test/stderr.factor +++ b/extra/io/windows/nt/launcher/test/stderr.factor @@ -2,4 +2,4 @@ USE: io USE: namespaces "output" write flush -"error" stderr get stream-write stderr get stream-flush +"error" error-stream get stream-write error-stream get stream-flush diff --git a/extra/io/windows/nt/monitors/monitors.factor b/extra/io/windows/nt/monitors/monitors.factor index 2397d207b9..37784c673c 100755 --- a/extra/io/windows/nt/monitors/monitors.factor +++ b/extra/io/windows/nt/monitors/monitors.factor @@ -3,9 +3,9 @@ USING: alien alien.c-types libc destructors locals kernel math assocs namespaces continuations sequences hashtables sorting arrays combinators math.bitfields strings system -accessors threads -io.backend io.windows io.windows.nt.backend io.monitors -io.nonblocking io.buffers io.files io.timeouts io +accessors threads splitting +io.backend io.windows io.windows.nt.backend io.windows.nt.files +io.monitors io.nonblocking io.buffers io.files io.timeouts io windows windows.kernel32 windows.types ; IN: io.windows.nt.monitors @@ -79,9 +79,12 @@ TUPLE: win32-monitor < monitor port ; : file-notify-records ( buffer -- seq ) [ (file-notify-records) drop ] { } make ; -: parse-notify-records ( monitor buffer -- ) - file-notify-records - [ parse-notify-record rot queue-change ] with each ; +:: parse-notify-records ( monitor buffer -- ) + buffer file-notify-records [ + parse-notify-record + [ monitor path>> prepend-path normalize-path ] dip + monitor queue-change + ] each ; : fill-queue ( monitor -- ) dup port>> check-closed diff --git a/extra/io/windows/nt/pipes/pipes.factor b/extra/io/windows/nt/pipes/pipes.factor index b164d5872b..aa565b52e8 100755 --- a/extra/io/windows/nt/pipes/pipes.factor +++ b/extra/io/windows/nt/pipes/pipes.factor @@ -1,16 +1,16 @@ ! Copyright (C) 2007, 2008 Doug Coleman, Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: alien alien.c-types arrays destructors io io.windows libc -windows.types math windows.kernel32 windows namespaces kernel -sequences windows.errors assocs math.parser system random -combinators accessors ; +windows.types math.bitfields windows.kernel32 windows namespaces +kernel sequences windows.errors assocs math.parser system random +combinators accessors io.pipes io.nonblocking ; IN: io.windows.nt.pipes ! This code is based on ! http://twistedmatrix.com/trac/browser/trunk/twisted/internet/iocpreactor/process.py -: create-named-pipe ( name mode -- handle ) - FILE_FLAG_OVERLAPPED bitor +: create-named-pipe ( name -- handle ) + { PIPE_ACCESS_INBOUND FILE_FLAG_OVERLAPPED } flags PIPE_TYPE_BYTE 1 4096 @@ -19,37 +19,20 @@ IN: io.windows.nt.pipes security-attributes-inherit CreateNamedPipe dup win32-error=0/f - dup add-completion ; + dup add-completion + f ; -: open-other-end ( name mode -- handle ) - FILE_SHARE_READ FILE_SHARE_WRITE bitor +: open-other-end ( name -- handle ) + GENERIC_WRITE + { FILE_SHARE_READ FILE_SHARE_WRITE } flags security-attributes-inherit OPEN_EXISTING FILE_FLAG_OVERLAPPED f CreateFile dup win32-error=0/f - dup add-completion ; - -TUPLE: pipe in out ; - -: ( name in-mode out-mode -- pipe ) - [ - >r over >r create-named-pipe dup close-later - r> r> open-other-end dup close-later - pipe boa - ] with-destructors ; - -: close-pipe ( pipe -- ) - dup - in>> CloseHandle drop - out>> CloseHandle drop ; - -: ( name -- pipe ) - PIPE_ACCESS_INBOUND GENERIC_WRITE ; - -: ( name -- pipe ) - PIPE_ACCESS_DUPLEX GENERIC_READ ; + dup add-completion + f ; : unique-pipe-name ( -- string ) [ @@ -61,25 +44,10 @@ TUPLE: pipe in out ; millis # ] "" make ; -: ( -- pipe ) - unique-pipe-name ; - -: ( -- pipe ) - unique-pipe-name ; - -! /dev/null simulation -: null-input ( -- pipe ) - - dup out>> CloseHandle drop - in>> ; - -: null-output ( -- pipe ) - - dup in>> CloseHandle drop - out>> ; - -: null-pipe ( mode -- pipe ) - { - { [ dup GENERIC_READ = ] [ drop null-input ] } - { [ dup GENERIC_WRITE = ] [ drop null-output ] } - } cond ; +M: winnt (pipe) ( -- pipe ) + [ + unique-pipe-name + [ create-named-pipe dup close-later ] + [ open-other-end dup close-later ] + bi pipe boa + ] with-destructors ; diff --git a/extra/io/windows/windows.factor b/extra/io/windows/windows.factor index 772ad9124f..85c448bdbd 100755 --- a/extra/io/windows/windows.factor +++ b/extra/io/windows/windows.factor @@ -2,14 +2,12 @@ ! See http://factorcode.org/license.txt for BSD license. USING: alien alien.c-types arrays destructors io io.backend io.buffers io.files io.nonblocking io.sockets io.binary -io.sockets.impl windows.errors strings io.streams.duplex +io.sockets.impl windows.errors strings kernel math namespaces sequences windows windows.kernel32 windows.shell32 windows.types windows.winsock splitting continuations math.bitfields system accessors ; IN: io.windows -M: windows destruct-handle CloseHandle drop ; - M: windows destruct-socket closesocket drop ; TUPLE: win32-file handle ptr ; @@ -43,7 +41,10 @@ M: win32-file init-handle ( handle -- ) drop ; M: win32-file close-handle ( handle -- ) - win32-file-handle CloseHandle drop ; + win32-file-handle close-handle ; + +M: alien close-handle ( handle -- ) + CloseHandle drop ; ! Clean up resources (open handle) if add-completion fails : open-file ( path access-mode create-mode flags -- handle ) @@ -85,15 +86,13 @@ M: win32-file close-handle ( handle -- ) f CreateFileW dup win32-error=0/f GetLastError ERROR_ALREADY_EXISTS = not ; -: set-file-pointer ( handle length -- ) - dupd d>w/w FILE_BEGIN SetFilePointer +: set-file-pointer ( handle length method -- ) + >r dupd d>w/w r> SetFilePointer INVALID_SET_FILE_POINTER = [ CloseHandle "SetFilePointer failed" throw ] when drop ; -: open-append ( path -- handle length ) - [ dup file-info size>> ] [ drop 0 ] recover - >r (open-append) r> 2dup set-file-pointer ; +HOOK: open-append os ( path -- handle length ) TUPLE: FileArgs hFile lpBuffer nNumberOfBytesToRead diff --git a/extra/logging/server/server.factor b/extra/logging/server/server.factor index 7601d1cc2e..3bc8637f90 100755 --- a/extra/logging/server/server.factor +++ b/extra/logging/server/server.factor @@ -48,7 +48,7 @@ SYMBOL: log-files : (log-message) ( msg -- ) #! msg: { msg word-name level service } - first4 log-stream [ write-message flush ] with-stream* ; + first4 log-stream [ write-message flush ] with-output-stream* ; : try-dispose ( stream -- ) [ dispose ] curry [ error. ] recover ; diff --git a/extra/morse/morse-docs.factor b/extra/morse/morse-docs.factor index f31b741c85..e35967d3e9 100644 --- a/extra/morse/morse-docs.factor +++ b/extra/morse/morse-docs.factor @@ -24,6 +24,10 @@ HELP: morse> { $description "Translates morse code into ASCII text" } { $see-also >morse morse>ch } ; -HELP: play-as-morse +HELP: play-as-morse* { $values { "str" "A string of ascii characters which can be translated into morse code" } { "unit-length" "The length of a dot" } } { $description "Plays a string as morse code" } ; + +HELP: play-as-morse +{ $values { "str" "A string of ascii characters which can be translated into morse code" } } +{ $description "Plays a string as morse code" } ; diff --git a/extra/opengl/opengl-docs.factor b/extra/opengl/opengl-docs.factor index 2788ebdfc2..b168f4cad1 100644 --- a/extra/opengl/opengl-docs.factor +++ b/extra/opengl/opengl-docs.factor @@ -7,7 +7,7 @@ HELP: gl-color { $description "Wrapper for " { $link glColor4d } " taking a color specifier." } ; HELP: gl-error -{ $description "If the most recent OpenGL call resulted in an error, print the error to the " { $link stdio } " stream." } ; +{ $description "If the most recent OpenGL call resulted in an error, print the error to " { $link output-stream } "." } ; HELP: do-state { diff --git a/extra/pack/pack-tests.factor b/extra/pack/pack-tests.factor index 510e44d34e..d58ccbd0f2 100755 --- a/extra/pack/pack-tests.factor +++ b/extra/pack/pack-tests.factor @@ -38,7 +38,7 @@ USING: io io.streams.string kernel namespaces pack strings tools.test ; [ 2 ] [ [ 2 "int" b, ] B{ } make - [ "int" read-native ] with-stream + [ "int" read-native ] with-input-stream ] unit-test [ "FRAM" ] [ "FRAM\0" [ read-c-string ] with-string-reader ] unit-test diff --git a/extra/pack/pack.factor b/extra/pack/pack.factor index 65912244dd..5320583df0 100755 --- a/extra/pack/pack.factor +++ b/extra/pack/pack.factor @@ -154,13 +154,12 @@ MACRO: (pack) ( seq str -- quot ) MACRO: (unpack) ( str -- quot ) [ - \ , [ [ unpack-table at , \ , , ] each ] [ ] make 1quotation [ { } make ] append 1quotation % - \ with-stream , + \ with-string-reader , ] [ ] make ; : unpack-native ( seq str -- seq ) diff --git a/extra/random/unix/unix.factor b/extra/random/unix/unix.factor index 6016a6e9cb..7fda7c5d1d 100644 --- a/extra/random/unix/unix.factor +++ b/extra/random/unix/unix.factor @@ -9,7 +9,7 @@ C: unix-random : file-read-unbuffered ( n path -- bytes ) over default-buffer-size [ - binary [ read ] with-stream + binary [ read ] with-file-reader ] with-variable ; M: unix-random random-bytes* ( n tuple -- byte-array ) diff --git a/extra/size-of/size-of.factor b/extra/size-of/size-of.factor index 5b6f26acea..a2b47fc0aa 100644 --- a/extra/size-of/size-of.factor +++ b/extra/size-of/size-of.factor @@ -36,4 +36,4 @@ VAR: headers { "gcc" c-file "-o" exe } to-strings [ "Error compiling generated C program" print ] run-or-bail - exe ascii contents string>number ; \ No newline at end of file + exe ascii contents string>number ; \ No newline at end of file diff --git a/extra/smtp/server/server.factor b/extra/smtp/server/server.factor index 737a887f9f..f23ee138d5 100755 --- a/extra/smtp/server/server.factor +++ b/extra/smtp/server/server.factor @@ -1,7 +1,8 @@ ! Copyright (C) 2007 Elie CHAFTARI ! See http://factorcode.org/license.txt for BSD license. USING: combinators kernel prettyprint io io.timeouts io.server -sequences namespaces io.sockets continuations calendar io.encodings.ascii ; +sequences namespaces io.sockets continuations calendar +io.encodings.ascii io.streams.duplex ; IN: smtp.server ! Mock SMTP server for testing purposes. @@ -65,7 +66,7 @@ SYMBOL: data-mode "Starting SMTP server on port " write dup . flush "127.0.0.1" swap ascii [ accept drop [ - 1 minutes stdio get set-timeout + 1 minutes timeouts "220 hello\r\n" write flush process global [ flush ] bind diff --git a/extra/smtp/smtp.factor b/extra/smtp/smtp.factor index 4d548738d2..8fdc0e07a4 100755 --- a/extra/smtp/smtp.factor +++ b/extra/smtp/smtp.factor @@ -17,11 +17,11 @@ LOG: log-smtp-connection NOTICE ( addrspec -- ) : with-smtp-connection ( quot -- ) smtp-server get dup log-smtp-connection - ascii [ + ascii [ smtp-domain [ host-name or ] change - read-timeout get stdio get set-timeout + read-timeout get timeouts call - ] with-stream ; inline + ] with-client ; inline : crlf "\r\n" write ; diff --git a/extra/state-parser/state-parser.factor b/extra/state-parser/state-parser.factor index 17d5377259..b41d7f5023 100644 --- a/extra/state-parser/state-parser.factor +++ b/extra/state-parser/state-parser.factor @@ -152,8 +152,8 @@ M: not-enough-characters summary ( obj -- str ) read1 set-next next ; : state-parse ( stream quot -- ) - ! with-stream implicitly creates a new scope which we use - swap [ init-parser call ] with-stream ; inline + ! with-input-stream implicitly creates a new scope which we use + swap [ init-parser call ] with-input-stream ; inline : string-parse ( input quot -- ) >r r> state-parse ; inline diff --git a/extra/tar/tar.factor b/extra/tar/tar.factor index 9b3d2ae79f..b5d01b6ed2 100755 --- a/extra/tar/tar.factor +++ b/extra/tar/tar.factor @@ -1,7 +1,6 @@ -USING: combinators io io.files io.streams.duplex -io.streams.string kernel math math.parser continuations -namespaces pack prettyprint sequences strings system -hexdump io.encodings.binary inspector accessors ; +USING: combinators io io.files io.streams.string kernel math +math.parser continuations namespaces pack prettyprint sequences +strings system hexdump io.encodings.binary inspector accessors ; IN: tar : zero-checksum 256 ; @@ -61,9 +60,7 @@ SYMBOL: filename ] if* ; : read-data-blocks ( tar-header out -- ) - >r stdio get r> [ - (read-data-blocks) - ] with-stream* ; + [ (read-data-blocks) ] with-output-stream* ; : parse-tar-header ( seq -- obj ) [ header-checksum ] keep over zero-checksum = [ diff --git a/extra/tools/deploy/backend/backend.factor b/extra/tools/deploy/backend/backend.factor index d4fbf1de78..ed466b6965 100755 --- a/extra/tools/deploy/backend/backend.factor +++ b/extra/tools/deploy/backend/backend.factor @@ -4,7 +4,7 @@ USING: namespaces continuations.private kernel.private init assocs kernel vocabs words sequences memory io system arrays continuations math definitions mirrors splitting parser classes inspector layouts vocabs.loader prettyprint.config prettyprint -debugger io.streams.c io.streams.duplex io.files io.backend +debugger io.streams.c io.files io.backend quotations io.launcher words.private tools.deploy.config bootstrap.image io.encodings.utf8 accessors ; IN: tools.deploy.backend @@ -31,10 +31,9 @@ IN: tools.deploy.backend +stdout+ >>stderr +closed+ >>stdin +low-priority+ >>priority - utf8 - >r copy-lines r> wait-for-process zero? [ - "Deployment failed" throw - ] unless ; + utf8 + copy-lines + wait-for-process zero? [ "Deployment failed" throw ] unless ; : make-boot-image ( -- ) #! If stage1 image doesn't exist, create one. diff --git a/extra/tools/deploy/shaker/shaker.factor b/extra/tools/deploy/shaker/shaker.factor index d507357590..86c50387b5 100755 --- a/extra/tools/deploy/shaker/shaker.factor +++ b/extra/tools/deploy/shaker/shaker.factor @@ -120,8 +120,9 @@ IN: tools.deploy.shaker io.thread:io-thread libc.private:mallocs source-files:source-files - stderr - stdio + input-stream + output-stream + error-stream } % deploy-threads? [ diff --git a/extra/tools/profiler/profiler-docs.factor b/extra/tools/profiler/profiler-docs.factor index 89e84bbc86..50bbc527d1 100755 --- a/extra/tools/profiler/profiler-docs.factor +++ b/extra/tools/profiler/profiler-docs.factor @@ -27,7 +27,7 @@ HELP: counters HELP: counters. { $values { "assoc" "an association list mapping words to integers" } } -{ $description "Prints an association list of call counts to the " { $link stdio } " stream." } ; +{ $description "Prints an association list of call counts to " { $link output-stream } "." } ; HELP: profile { $values { "quot" quotation } } diff --git a/extra/tools/test/test-docs.factor b/extra/tools/test/test-docs.factor index a605543bda..4b2521d19c 100755 --- a/extra/tools/test/test-docs.factor +++ b/extra/tools/test/test-docs.factor @@ -91,4 +91,4 @@ HELP: run-all-tests HELP: test-failures. { $values { "assoc" "an association list of unit test failures" } } -{ $description "Prints unit test failures output by " { $link run-tests } " or " { $link run-all-tests } " to the " { $link stdio } " stream." } ; +{ $description "Prints unit test failures output by " { $link run-tests } " or " { $link run-all-tests } " to " { $link output-stream } "." } ; diff --git a/extra/tools/test/ui/ui.factor b/extra/tools/test/ui/ui.factor index 9b32bc9e10..8825cffa4d 100755 --- a/extra/tools/test/ui/ui.factor +++ b/extra/tools/test/ui/ui.factor @@ -2,7 +2,7 @@ USING: dlists ui.gadgets kernel ui namespaces io.streams.string io ; IN: tools.test.ui -! We can't print to stdio here because that might be a pane +! We can't print to output-stream here because that might be a pane ! stream, and our graft-queue rebinding here would be captured ! by code adding children to the pane... : with-grafted-gadget ( gadget quot -- ) diff --git a/extra/tools/vocabs/monitor/monitor.factor b/extra/tools/vocabs/monitor/monitor.factor index 563cd04e3e..ee5198a8f4 100755 --- a/extra/tools/vocabs/monitor/monitor.factor +++ b/extra/tools/vocabs/monitor/monitor.factor @@ -13,9 +13,9 @@ IN: tools.vocabs.monitor dup ".factor" tail? [ parent-directory ] when ; : chop-vocab-root ( path -- path' ) - "resource:" prepend-path (normalize-path) + "resource:" prepend-path normalize-path dup vocab-roots get - [ (normalize-path) ] map + [ normalize-path ] map [ head? ] with find nip ?head drop ; @@ -29,17 +29,17 @@ IN: tools.vocabs.monitor reset-cache monitor-loop ; -: add-monitor-for-path ( path -- ) - normalize-path dup exists? [ t my-mailbox (monitor) ] when drop ; - +: add-monitor-for-path ( path -- ) + dup exists? [ t my-mailbox (monitor) ] when drop ; + : monitor-thread ( -- ) [ [ vocab-roots get prune [ add-monitor-for-path ] each - + H{ } clone changed-vocabs set-global vocabs [ changed-vocab ] each - + monitor-loop ] with-monitors ] ignore-errors ; diff --git a/extra/trees/avl/avl-tests.factor b/extra/trees/avl/avl-tests.factor old mode 100644 new mode 100755 index 570125cb45..5cb6606ce4 --- a/extra/trees/avl/avl-tests.factor +++ b/extra/trees/avl/avl-tests.factor @@ -2,85 +2,79 @@ USING: kernel tools.test trees trees.avl math random sequences assocs ; IN: trees.avl.tests [ "key1" 0 "key2" 0 ] [ - T{ avl-node T{ node f "key1" f f T{ avl-node T{ node f "key2" } 1 } } 2 } + T{ avl-node f "key1" f f T{ avl-node f "key2" f f 1 } 2 } [ single-rotate ] go-left [ node-left dup node-key swap avl-node-balance ] keep dup node-key swap avl-node-balance ] unit-test [ "key1" 0 "key2" 0 ] [ - T{ avl-node T{ node f "key1" f f T{ avl-node T{ node f "key2" } 1 } } 2 } + T{ avl-node f "key1" f f T{ avl-node f "key2" f f f 1 } 2 } [ select-rotate ] go-left [ node-left dup node-key swap avl-node-balance ] keep dup node-key swap avl-node-balance ] unit-test [ "key1" 0 "key2" 0 ] [ - T{ avl-node T{ node f "key1" f T{ avl-node T{ node f "key2" } -1 } } -2 } + T{ avl-node f "key1" f T{ avl-node f "key2" f f f -1 } f -2 } [ single-rotate ] go-right [ node-right dup node-key swap avl-node-balance ] keep dup node-key swap avl-node-balance ] unit-test [ "key1" 0 "key2" 0 ] [ - T{ avl-node T{ node f "key1" f T{ avl-node T{ node f "key2" } -1 } } -2 } + T{ avl-node f "key1" f T{ avl-node f "key2" f f f -1 } f -2 } [ select-rotate ] go-right [ node-right dup node-key swap avl-node-balance ] keep dup node-key swap avl-node-balance ] unit-test [ "key1" -1 "key2" 0 "key3" 0 ] -[ T{ avl-node T{ node f "key1" f f - T{ avl-node T{ node f "key2" f - T{ avl-node T{ node f "key3" } 1 } } - -1 } } - 2 } [ double-rotate ] go-left +[ T{ avl-node f "key1" f f + T{ avl-node f "key2" f + T{ avl-node f "key3" f f f 1 } f -1 } 2 } + [ double-rotate ] go-left [ node-left dup node-key swap avl-node-balance ] keep [ node-right dup node-key swap avl-node-balance ] keep dup node-key swap avl-node-balance ] unit-test [ "key1" 0 "key2" 0 "key3" 0 ] -[ T{ avl-node T{ node f "key1" f f - T{ avl-node T{ node f "key2" f - T{ avl-node T{ node f "key3" } 0 } } - -1 } } - 2 } [ double-rotate ] go-left +[ T{ avl-node f "key1" f f + T{ avl-node f "key2" f + T{ avl-node f "key3" f f f 0 } f -1 } 2 } + [ double-rotate ] go-left [ node-left dup node-key swap avl-node-balance ] keep [ node-right dup node-key swap avl-node-balance ] keep dup node-key swap avl-node-balance ] unit-test [ "key1" 0 "key2" 1 "key3" 0 ] -[ T{ avl-node T{ node f "key1" f f - T{ avl-node T{ node f "key2" f - T{ avl-node T{ node f "key3" } -1 } } - -1 } } - 2 } [ double-rotate ] go-left +[ T{ avl-node f "key1" f f + T{ avl-node f "key2" f + T{ avl-node f "key3" f f f -1 } f -1 } 2 } + [ double-rotate ] go-left [ node-left dup node-key swap avl-node-balance ] keep [ node-right dup node-key swap avl-node-balance ] keep dup node-key swap avl-node-balance ] unit-test [ "key1" 1 "key2" 0 "key3" 0 ] -[ T{ avl-node T{ node f "key1" f - T{ avl-node T{ node f "key2" f f - T{ avl-node T{ node f "key3" } -1 } } - 1 } } - -2 } [ double-rotate ] go-right +[ T{ avl-node f "key1" f + T{ avl-node f "key2" f f + T{ avl-node f "key3" f f f -1 } 1 } f -2 } + [ double-rotate ] go-right [ node-right dup node-key swap avl-node-balance ] keep [ node-left dup node-key swap avl-node-balance ] keep dup node-key swap avl-node-balance ] unit-test [ "key1" 0 "key2" 0 "key3" 0 ] -[ T{ avl-node T{ node f "key1" f - T{ avl-node T{ node f "key2" f f - T{ avl-node T{ node f "key3" } 0 } } - 1 } } - -2 } [ double-rotate ] go-right +[ T{ avl-node f "key1" f + T{ avl-node f "key2" f f + T{ avl-node f "key3" f f f 0 } 1 } f -2 } + [ double-rotate ] go-right [ node-right dup node-key swap avl-node-balance ] keep [ node-left dup node-key swap avl-node-balance ] keep dup node-key swap avl-node-balance ] unit-test [ "key1" 0 "key2" -1 "key3" 0 ] -[ T{ avl-node T{ node f "key1" f - T{ avl-node T{ node f "key2" f f - T{ avl-node T{ node f "key3" } 1 } } - 1 } } - -2 } [ double-rotate ] go-right +[ T{ avl-node f "key1" f + T{ avl-node f "key2" f f + T{ avl-node f "key3" f f f 1 } 1 } f -2 } + [ double-rotate ] go-right [ node-right dup node-key swap avl-node-balance ] keep [ node-left dup node-key swap avl-node-balance ] keep dup node-key swap avl-node-balance ] unit-test diff --git a/extra/trees/avl/avl.factor b/extra/trees/avl/avl.factor index 3a37ec5fc7..866e035a21 100755 --- a/extra/trees/avl/avl.factor +++ b/extra/trees/avl/avl.factor @@ -1,33 +1,34 @@ ! Copyright (C) 2007 Alex Chapman ! See http://factorcode.org/license.txt for BSD license. -USING: combinators kernel generic math math.functions math.parser -namespaces io prettyprint.backend sequences trees assocs parser -math.order ; +USING: combinators kernel generic math math.functions +math.parser namespaces io prettyprint.backend sequences trees +assocs parser accessors math.order ; IN: trees.avl -TUPLE: avl ; - -INSTANCE: avl tree-mixin +TUPLE: avl < tree ; : ( -- tree ) - avl construct-tree ; + avl new-tree ; -TUPLE: avl-node balance ; +TUPLE: avl-node < node balance ; : ( key value -- node ) - swap 0 avl-node boa tuck set-delegate ; + avl-node new-node + 0 >>balance ; -: change-balance ( node amount -- ) - over avl-node-balance + swap set-avl-node-balance ; +: increase-balance ( node amount -- ) + swap [ + ] change-balance drop ; : rotate ( node -- node ) - dup node+link dup node-link pick set-node+link tuck set-node-link ; + dup node+link dup node-link pick set-node+link + tuck set-node-link ; : single-rotate ( node -- node ) - 0 over set-avl-node-balance 0 over node+link set-avl-node-balance rotate ; + 0 over (>>balance) 0 over node+link + (>>balance) rotate ; : pick-balances ( a node -- balance balance ) - avl-node-balance { + balance>> { { [ dup zero? ] [ 2drop 0 0 ] } { [ over = ] [ neg 0 ] } [ 0 swap ] @@ -36,18 +37,22 @@ TUPLE: avl-node balance ; : double-rotate ( node -- node ) [ node+link [ - node-link current-side get neg over pick-balances rot 0 swap set-avl-node-balance - ] keep set-avl-node-balance - ] keep tuck set-avl-node-balance - dup node+link [ rotate ] with-other-side over set-node+link rotate ; + node-link current-side get neg + over pick-balances rot 0 swap (>>balance) + ] keep (>>balance) + ] keep swap >>balance + dup node+link [ rotate ] with-other-side + over set-node+link rotate ; : select-rotate ( node -- node ) - dup node+link avl-node-balance current-side get = [ double-rotate ] [ single-rotate ] if ; + dup node+link balance>> current-side get = + [ double-rotate ] [ single-rotate ] if ; : balance-insert ( node -- node taller? ) dup avl-node-balance { { [ dup zero? ] [ drop f ] } - { [ dup abs 2 = ] [ sgn neg [ select-rotate ] with-side f ] } + { [ dup abs 2 = ] + [ sgn neg [ select-rotate ] with-side f ] } { [ drop t ] [ t ] } ! balance is -1 or 1, tree is taller } cond ; @@ -57,7 +62,8 @@ DEFER: avl-set 2dup node-key before? left right ? [ [ node-link avl-set ] keep swap >r tuck set-node-link r> - [ dup current-side get change-balance balance-insert ] [ f ] if + [ dup current-side get increase-balance balance-insert ] + [ f ] if ] with-side ; : (avl-set) ( value key node -- node taller? ) @@ -66,10 +72,10 @@ DEFER: avl-set ] [ avl-insert ] if ; : avl-set ( value key node -- node taller? ) - [ (avl-set) ] [ t ] if* ; + [ (avl-set) ] [ swap t ] if* ; M: avl set-at ( value key node -- node ) - [ avl-set drop ] change-root ; + [ avl-set drop ] change-root drop ; : delete-select-rotate ( node -- node shorter? ) dup node+link avl-node-balance zero? [ @@ -87,10 +93,10 @@ M: avl set-at ( value key node -- node ) } cond ; : balance-delete ( node -- node shorter? ) - current-side get over avl-node-balance { + current-side get over balance>> { { [ dup zero? ] [ drop neg over set-avl-node-balance f ] } - { [ dupd = ] [ drop 0 over set-avl-node-balance t ] } - [ dupd neg change-balance rebalance-delete ] + { [ dupd = ] [ drop 0 >>balance t ] } + [ dupd neg increase-balance rebalance-delete ] } cond ; : avl-replace-with-extremity ( to-replace node -- node shorter? ) @@ -135,12 +141,12 @@ M: avl-node avl-delete ( key node -- node shorter? deleted? ) ] if ; M: avl delete-at ( key node -- ) - [ avl-delete 2drop ] change-root ; + [ avl-delete 2drop ] change-root drop ; M: avl new-assoc 2drop ; : >avl ( assoc -- avl ) - T{ avl T{ tree f f 0 } } assoc-clone-like ; + T{ avl f f 0 } assoc-clone-like ; M: avl assoc-like drop dup avl? [ >avl ] unless ; diff --git a/extra/trees/splay/splay.factor b/extra/trees/splay/splay.factor old mode 100644 new mode 100755 index 8931db3a10..ef5fcf8ca6 --- a/extra/trees/splay/splay.factor +++ b/extra/trees/splay/splay.factor @@ -4,12 +4,10 @@ USING: arrays kernel math namespaces sequences assocs parser prettyprint.backend trees generic math.order ; IN: trees.splay -TUPLE: splay ; +TUPLE: splay < tree ; : ( -- tree ) - \ splay construct-tree ; - -INSTANCE: splay tree-mixin + \ splay new-tree ; : rotate-right ( node -- node ) dup node-left @@ -131,7 +129,7 @@ M: splay new-assoc 2drop ; : >splay ( assoc -- tree ) - T{ splay T{ tree f f 0 } } assoc-clone-like ; + T{ splay f f 0 } assoc-clone-like ; : SPLAY{ \ } [ >splay ] parse-literal ; parsing diff --git a/extra/trees/trees.factor b/extra/trees/trees.factor index 3cad81e447..3b0ab01666 100755 --- a/extra/trees/trees.factor +++ b/extra/trees/trees.factor @@ -5,23 +5,25 @@ prettyprint.private kernel.private assocs random combinators parser prettyprint.backend math.order accessors ; IN: trees -MIXIN: tree-mixin - TUPLE: tree root count ; +: new-tree ( class -- tree ) + new + f >>root + 0 >>count ; inline + : ( -- tree ) - f 0 tree boa ; + tree new-tree ; -: construct-tree ( class -- tree ) - new over set-delegate ; inline - -INSTANCE: tree tree-mixin - -INSTANCE: tree-mixin assoc +INSTANCE: tree assoc TUPLE: node key value left right ; + +: new-node ( key value class -- node ) + new swap >>value swap >>key ; + : ( key value -- node ) - f f node boa ; + node new-node ; SYMBOL: current-side @@ -57,9 +59,6 @@ SYMBOL: current-side : go-left ( quot -- ) left swap with-side ; inline : go-right ( quot -- ) right swap with-side ; inline -: change-root ( tree quot -- ) - swap [ root>> swap call ] keep set-tree-root ; inline - : leaf? ( node -- ? ) [ left>> ] [ right>> ] bi or not ; @@ -91,7 +90,7 @@ M: tree at* ( key tree -- value ? ) ] if ; M: tree set-at ( value key tree -- ) - [ [ node-set ] [ swap ] if* ] change-root ; + [ [ node-set ] [ swap ] if* ] change-root drop ; : valid-node? ( node -- ? ) [ @@ -117,10 +116,10 @@ M: tree set-at ( value key tree -- ) [ >r right>> r> find-node ] } cond ; inline -M: tree-mixin assoc-find ( tree quot -- key value ? ) +M: tree assoc-find ( tree quot -- key value ? ) >r root>> r> find-node ; -M: tree-mixin clear-assoc +M: tree clear-assoc 0 >>count f >>root drop ; @@ -182,7 +181,7 @@ DEFER: delete-node ] if ; M: tree delete-at - [ delete-bst-node ] change-root ; + [ delete-bst-node ] change-root drop ; M: tree new-assoc 2drop ; @@ -192,14 +191,12 @@ M: tree clone dup assoc-clone-like ; : >tree ( assoc -- tree ) T{ tree f f 0 } assoc-clone-like ; -M: tree-mixin assoc-like drop dup tree? [ >tree ] unless ; +M: tree assoc-like drop dup tree? [ >tree ] unless ; : TREE{ \ } [ >tree ] parse-literal ; parsing - + M: tree pprint-delims drop \ TREE{ \ } ; - -M: tree-mixin assoc-size count>> ; -M: tree-mixin clone dup assoc-clone-like ; -M: tree-mixin >pprint-sequence >alist ; -M: tree-mixin pprint-narrow? drop t ; +M: tree assoc-size count>> ; +M: tree >pprint-sequence >alist ; +M: tree pprint-narrow? drop t ; diff --git a/extra/ui/gadgets/gadgets-tests.factor b/extra/ui/gadgets/gadgets-tests.factor index dbe06ec8cd..f88b207603 100755 --- a/extra/ui/gadgets/gadgets-tests.factor +++ b/extra/ui/gadgets/gadgets-tests.factor @@ -124,7 +124,7 @@ M: mock-gadget ungraft* dup mock-gadget-ungraft-called 1+ swap set-mock-gadget-ungraft-called ; -! We can't print to stdio here because that might be a pane +! We can't print to output-stream here because that might be a pane ! stream, and our graft-queue rebinding here would be captured ! by code adding children to the pane... [ diff --git a/extra/ui/gadgets/panes/panes-docs.factor b/extra/ui/gadgets/panes/panes-docs.factor index a684153b98..99f8b2e82a 100755 --- a/extra/ui/gadgets/panes/panes-docs.factor +++ b/extra/ui/gadgets/panes/panes-docs.factor @@ -23,7 +23,7 @@ HELP: print-gadget HELP: gadget. { $values { "gadget" gadget } } -{ $description "Writes a gadget followed by a newline to the " { $link stdio } " stream." } +{ $description "Writes a gadget followed by a newline to " { $link output-stream } "." } { $notes "Not all streams support this operation." } ; HELP: ?nl @@ -32,11 +32,11 @@ HELP: ?nl HELP: with-pane { $values { "pane" pane } { "quot" quotation } } -{ $description "Clears the pane and calls the quotation in a new scope where " { $link stdio } " is rebound to a " { $link pane-stream } " writing to the pane." } ; +{ $description "Clears the pane and calls the quotation in a new scope where " { $link output-stream } " is rebound to a " { $link pane-stream } " writing to the pane." } ; HELP: make-pane { $values { "quot" quotation } { "gadget" "a new " { $link gadget } } } -{ $description "Calls the quotation in a new scope where " { $link stdio } " is rebound to a " { $link pane-stream } " writing to a new pane. The output area of the new pane is output on the stack after the quotation returns. The pane itself is not output." } ; +{ $description "Calls the quotation in a new scope where " { $link output-stream } " is rebound to a " { $link pane-stream } " writing to a new pane. The output area of the new pane is output on the stack after the quotation returns. The pane itself is not output." } ; HELP: { $values { "pane" "a new " { $link pane } } } diff --git a/extra/ui/gadgets/panes/panes-tests.factor b/extra/ui/gadgets/panes/panes-tests.factor index 0263b15d71..31bb4233bf 100755 --- a/extra/ui/gadgets/panes/panes-tests.factor +++ b/extra/ui/gadgets/panes/panes-tests.factor @@ -11,7 +11,7 @@ help.stylesheet splitting tools.test.ui models math inspector ; [ ] [ #children "num-children" set ] unit-test [ ] [ - "pane" get [ 10000 [ . ] each ] with-stream* + "pane" get [ 10000 [ . ] each ] with-output-stream* ] unit-test [ t ] [ #children "num-children" get = ] unit-test diff --git a/extra/ui/gadgets/panes/panes.factor b/extra/ui/gadgets/panes/panes.factor index bff0ca10ad..533a6c42b7 100755 --- a/extra/ui/gadgets/panes/panes.factor +++ b/extra/ui/gadgets/panes/panes.factor @@ -6,7 +6,7 @@ ui.gadgets.paragraphs ui.gadgets.incremental ui.gadgets.packs ui.gadgets.theme ui.clipboards ui.gestures ui.traverse ui.render hashtables io kernel namespaces sequences io.styles strings quotations math opengl combinators math.vectors -io.streams.duplex sorting splitting io.streams.nested assocs +sorting splitting io.streams.nested assocs ui.gadgets.presentations ui.gadgets.slots ui.gadgets.grids ui.gadgets.grid-lines classes.tuple models continuations ; IN: ui.gadgets.panes @@ -113,14 +113,11 @@ GENERIC: write-gadget ( gadget stream -- ) M: pane-stream write-gadget pane-stream-pane pane-current add-gadget ; -M: duplex-stream write-gadget - duplex-stream-out write-gadget ; - : print-gadget ( gadget stream -- ) tuck write-gadget stream-nl ; : gadget. ( gadget -- ) - stdio get print-gadget ; + output-stream get print-gadget ; : ?nl ( stream -- ) dup pane-stream-pane pane-current gadget-children empty? @@ -129,7 +126,7 @@ M: duplex-stream write-gadget : with-pane ( pane quot -- ) over scroll>top over pane-clear >r r> - over >r with-stream* r> ?nl ; inline + over >r with-output-stream* r> ?nl ; inline : make-pane ( quot -- gadget ) [ swap with-pane ] keep smash-pane ; inline diff --git a/extra/ui/tools/interactor/interactor.factor b/extra/ui/tools/interactor/interactor.factor index 6c8b77d1f2..4f5090fda2 100755 --- a/extra/ui/tools/interactor/interactor.factor +++ b/extra/ui/tools/interactor/interactor.factor @@ -71,7 +71,7 @@ M: interactor model-changed : interactor-input. ( string interactor -- ) interactor-output [ dup string? [ dup write-input nl ] [ short. ] if - ] with-stream* ; + ] with-output-stream* ; : add-interactor-history ( str interactor -- ) over empty? [ 2drop ] [ interactor-history push-new ] if ; diff --git a/extra/ui/tools/listener/listener.factor b/extra/ui/tools/listener/listener.factor index d96270075f..484b000861 100755 --- a/extra/ui/tools/listener/listener.factor +++ b/extra/ui/tools/listener/listener.factor @@ -1,7 +1,7 @@ ! Copyright (C) 2005, 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: inspector ui.tools.interactor ui.tools.inspector -ui.tools.workspace help.markup io io.streams.duplex io.styles +ui.tools.workspace help.markup io io.styles kernel models namespaces parser quotations sequences ui.commands ui.gadgets ui.gadgets.editors ui.gadgets.labelled ui.gadgets.panes ui.gadgets.buttons ui.gadgets.scrollers @@ -16,10 +16,8 @@ TUPLE: listener-gadget input output stack ; g-> set-listener-gadget-output "Output" 1 track, ; -: listener-stream ( listener -- stream ) - dup listener-gadget-input - swap listener-gadget-output - ; +: listener-streams ( listener -- input output ) + [ input>> ] [ output>> ] bi ; : ( listener -- gadget ) listener-gadget-output ; @@ -130,7 +128,7 @@ TUPLE: stack-display ; stack-display new g workspace-listener swap [ dup f track, - listener-gadget-stack [ stack. ] + stack>> [ [ stack. ] curry try ] t "Data stack" 1 track, ] { 0 1 } build-track ; @@ -148,13 +146,15 @@ M: stack-display tool-scroller swap show-tool inspect-object ; : listener-thread ( listener -- ) - dup listener-stream [ - dup [ ui-listener-hook ] curry listener-hook set - dup [ ui-error-hook ] curry error-hook set - [ ui-inspector-hook ] curry inspector-hook set - welcome. - listener - ] with-stream* ; + dup listener-streams [ + [ + [ [ ui-listener-hook ] curry listener-hook set ] + [ [ ui-error-hook ] curry error-hook set ] + [ [ ui-inspector-hook ] curry inspector-hook set ] tri + welcome. + listener + ] with-input-stream* + ] with-output-stream* ; : start-listener-thread ( listener -- ) [ listener-thread ] curry "Listener" spawn drop ; diff --git a/extra/unicode/breaks/breaks.factor b/extra/unicode/breaks/breaks.factor index d8e4f8c24e..9ee65c0018 100644 --- a/extra/unicode/breaks/breaks.factor +++ b/extra/unicode/breaks/breaks.factor @@ -105,9 +105,6 @@ VALUE: grapheme-table : string-reverse ( str -- rts ) >graphemes reverse concat ; -: unclip-last-slice ( seq -- beginning last ) - dup 1 head-slice* swap peek ; - : last-grapheme ( str -- i ) unclip-last-slice grapheme-class swap [ grapheme-class dup rot grapheme-break? ] find-last-index ?1+ nip ; diff --git a/extra/unix/bsd/bsd.factor b/extra/unix/bsd/bsd.factor index d80db44348..158dbeaddb 100755 --- a/extra/unix/bsd/bsd.factor +++ b/extra/unix/bsd/bsd.factor @@ -21,7 +21,9 @@ IN: unix : SO_SNDTIMEO HEX: 1005 ; inline : SO_RCVTIMEO HEX: 1006 ; inline +: F_SETFD 2 ; inline : F_SETFL 4 ; inline +: FD_CLOEXEC 1 ; inline : O_NONBLOCK 4 ; inline C-STRUCT: sockaddr-in diff --git a/extra/unix/linux/linux.factor b/extra/unix/linux/linux.factor index 11db6cc862..74195fae36 100755 --- a/extra/unix/linux/linux.factor +++ b/extra/unix/linux/linux.factor @@ -24,6 +24,9 @@ USING: alien.syntax ; : SO_SNDTIMEO HEX: 15 ; inline : SO_RCVTIMEO HEX: 14 ; inline +: F_SETFD 2 ; inline +: FD_CLOEXEC 1 ; inline + : F_SETFL 4 ; inline : O_NONBLOCK HEX: 800 ; inline diff --git a/extra/xml/xml-docs.factor b/extra/xml/xml-docs.factor index dd77d7c766..6a2ff1109e 100644 --- a/extra/xml/xml-docs.factor +++ b/extra/xml/xml-docs.factor @@ -42,17 +42,17 @@ HELP: xml-reprint HELP: write-xml { $values { "xml" "an XML document" } } -{ $description "prints the contents of an XML document (" { $link xml } ") to stdio" } +{ $description "prints the contents of an XML document (" { $link xml } ") to " { $link output-stream } "." } { $notes "does not preserve what type of quotes were used or what data was omitted from version declaration" } ; HELP: print-xml { $values { "xml" "an XML document" } } -{ $description "prints the contents of an XML document (" { $link xml } ") to stdio, followed by a newline" } +{ $description "prints the contents of an XML document (" { $link xml } ") to " { $link output-stream } ", followed by a newline" } { $notes "does not preserve what type of quotes were used or what data was omitted from version declaration" } ; HELP: pprint-xml { $values { "xml" "an XML document" } } -{ $description "prints the contents of an XML document (" { $link xml } ") to stdio in a prettyprinted form." } +{ $description "prints the contents of an XML document (" { $link xml } ") to " { $link output-stream } " in a prettyprinted form." } { $notes "does not preserve what type of quotes were used or what data was omitted from version declaration" } ; HELP: pprint-xml-but @@ -226,7 +226,7 @@ HELP: pull-xml HELP: { $values { "pull-xml" "a pull-xml tuple" } } -{ $description "creates an XML pull-based parser which reads from the " { $link stdio } " stream, executing all initial XML commands to set up the parser." } +{ $description "creates an XML pull-based parser which reads from " { $link input-stream } ", executing all initial XML commands to set up the parser." } { $see-also pull-xml pull-elem pull-event } ; HELP: pull-elem @@ -241,12 +241,12 @@ HELP: pull-event HELP: write-item { $values { "object" "an XML element" } } -{ $description "writes an XML element to the " { $link stdio } " stream." } +{ $description "writes an XML element to " { $link output-stream } "." } { $see-also write-chunk write-xml } ; HELP: write-chunk { $values { "seq" "an XML document fragment" } } -{ $description "writes an XML document fragment, ie a sequence of XML elements, to the " { $link stdio } " stream." } +{ $description "writes an XML document fragment, ie a sequence of XML elements, to " { $link output-stream } "." } { $see-also write-item write-xml } ; HELP: deep-tag-named diff --git a/extra/xml/xml.factor b/extra/xml/xml.factor index f45b27b030..4e2ad7a672 100644 --- a/extra/xml/xml.factor +++ b/extra/xml/xml.factor @@ -98,7 +98,7 @@ SYMBOL: text-now? TUPLE: pull-xml scope ; : ( -- pull-xml ) [ - stdio [ ] change ! bring stdio var in this scope + input-stream [ ] change ! bring var in this scope init-parser reset-prolog init-ns-stack text-now? on ] H{ } make-assoc diff --git a/extra/xmode/code2html/code2html.factor b/extra/xmode/code2html/code2html.factor index a13e412afe..f6df23b9b2 100755 --- a/extra/xmode/code2html/code2html.factor +++ b/extra/xmode/code2html/code2html.factor @@ -42,8 +42,7 @@ IN: xmode.code2html : htmlize-file ( path -- ) dup utf8 [ - stdio get - over ".html" append utf8 [ - htmlize-stream + dup ".html" append utf8 [ + input-stream get htmlize-stream ] with-file-writer ] with-file-reader ;