diff --git a/core/alien/alien-docs.factor b/core/alien/alien-docs.factor index 136af91bb2..7d13080e3c 100755 --- a/core/alien/alien-docs.factor +++ b/core/alien/alien-docs.factor @@ -78,7 +78,7 @@ $nl "<< \"freetype\" {" " { [ os macosx? ] [ \"libfreetype.6.dylib\" \"cdecl\" add-library ] }" " { [ os windows? ] [ \"freetype6.dll\" \"cdecl\" add-library ] }" - " { [ t ] [ drop ] }" + " [ drop ]" "} cond >>" } "Note the parse time evaluation with " { $link POSTPONE: << } "." } ; diff --git a/core/alien/compiler/compiler.factor b/core/alien/compiler/compiler.factor index 0f74f52d60..594c42268c 100755 --- a/core/alien/compiler/compiler.factor +++ b/core/alien/compiler/compiler.factor @@ -375,7 +375,7 @@ TUPLE: callback-context ; return>> { { [ dup "void" = ] [ drop [ ] ] } { [ dup large-struct? ] [ heap-size [ memcpy ] curry ] } - { [ t ] [ c-type c-type-prep ] } + [ c-type c-type-prep ] } cond ; : wrap-callback-quot ( node -- quot ) @@ -390,7 +390,7 @@ TUPLE: callback-context ; { { [ dup abi>> "stdcall" = ] [ alien-stack-frame ] } { [ dup return>> large-struct? ] [ drop 4 ] } - { [ t ] [ drop 0 ] } + [ drop 0 ] } cond ; : %callback-return ( node -- ) diff --git a/core/alien/syntax/syntax.factor b/core/alien/syntax/syntax.factor index 6e4b8b4e21..67ea30f379 100755 --- a/core/alien/syntax/syntax.factor +++ b/core/alien/syntax/syntax.factor @@ -68,7 +68,7 @@ M: alien pprint* { { [ dup expired? ] [ drop "( alien expired )" text ] } { [ dup pinned-c-ptr? not ] [ drop "( displaced alien )" text ] } - { [ t ] [ \ ALIEN: [ alien-address pprint* ] pprint-prefix ] } + [ \ ALIEN: [ alien-address pprint* ] pprint-prefix ] } cond ; M: dll pprint* dll-path dup "DLL\" " "\"" pprint-string ; diff --git a/core/classes/algebra/algebra.factor b/core/classes/algebra/algebra.factor index 4614e4c4ce..faf57fcd0d 100755 --- a/core/classes/algebra/algebra.factor +++ b/core/classes/algebra/algebra.factor @@ -84,7 +84,7 @@ C: anonymous-complement { [ dup anonymous-complement? ] [ class>> classes-intersect? not ] } { [ dup members ] [ right-union-class< ] } { [ over superclass ] [ superclass< ] } - { [ t ] [ 2drop f ] } + [ 2drop f ] } cond ; : anonymous-union-intersect? ( first second -- ? ) @@ -104,14 +104,14 @@ C: anonymous-complement { [ over tuple eq? ] [ 2drop t ] } { [ over builtin-class? ] [ 2drop f ] } { [ over tuple-class? ] [ [ class< ] [ swap class< ] 2bi or ] } - { [ t ] [ swap classes-intersect? ] } + [ swap classes-intersect? ] } cond ; : builtin-class-intersect? ( first second -- ? ) { { [ 2dup eq? ] [ 2drop t ] } { [ over builtin-class? ] [ 2drop f ] } - { [ t ] [ swap classes-intersect? ] } + [ swap classes-intersect? ] } cond ; : (classes-intersect?) ( first second -- ? ) @@ -154,7 +154,7 @@ C: anonymous-complement { [ over members ] [ left-union-and ] } { [ over anonymous-union? ] [ left-anonymous-union-and ] } { [ over anonymous-intersection? ] [ left-anonymous-intersection-and ] } - { [ t ] [ 2array ] } + [ 2array ] } cond ; : left-anonymous-union-or ( first second -- class ) @@ -169,7 +169,7 @@ C: anonymous-complement { [ 2dup swap class< ] [ drop ] } { [ dup anonymous-union? ] [ right-anonymous-union-or ] } { [ over anonymous-union? ] [ left-anonymous-union-or ] } - { [ t ] [ 2array ] } + [ 2array ] } cond ; : (class-not) ( class -- complement ) @@ -177,7 +177,7 @@ C: anonymous-complement { [ dup anonymous-complement? ] [ class>> ] } { [ dup object eq? ] [ drop null ] } { [ dup null eq? ] [ drop object ] } - { [ t ] [ ] } + [ ] } cond ; : largest-class ( seq -- n elt ) @@ -205,7 +205,7 @@ C: anonymous-complement { [ dup builtin-class? ] [ dup set ] } { [ dup members ] [ members [ (flatten-class) ] each ] } { [ dup superclass ] [ superclass (flatten-class) ] } - { [ t ] [ drop ] } + [ drop ] } cond ; : flatten-class ( class -- assoc ) diff --git a/core/classes/mixin/mixin.factor b/core/classes/mixin/mixin.factor index aefd522269..9bbe89d7d9 100755 --- a/core/classes/mixin/mixin.factor +++ b/core/classes/mixin/mixin.factor @@ -49,7 +49,7 @@ M: mixin-instance equal? { [ over mixin-instance? not ] [ f ] } { [ 2dup [ mixin-instance-class ] bi@ = not ] [ f ] } { [ 2dup [ mixin-instance-mixin ] bi@ = not ] [ f ] } - { [ t ] [ t ] } + [ t ] } cond 2nip ; M: mixin-instance hashcode* diff --git a/core/combinators/combinators-docs.factor b/core/combinators/combinators-docs.factor index f497fd20e5..54c62c44fa 100755 --- a/core/combinators/combinators-docs.factor +++ b/core/combinators/combinators-docs.factor @@ -64,9 +64,9 @@ HELP: alist>quot { $notes "This word is used to implement compile-time behavior for " { $link cond } ", and it is also used by the generic word system. Note that unlike " { $link cond } ", the constructed quotation performs the tests starting from the end and not the beginning." } ; HELP: cond -{ $values { "assoc" "a sequence of quotation pairs" } } +{ $values { "assoc" "a sequence of quotation pairs and an optional quotation" } } { $description - "Calls the second quotation in the first pair whose first quotation yields a true value." + "Calls the second quotation in the first pair whose first quotation yields a true value. A single quotation will always yield a true value." $nl "The following two phrases are equivalent:" { $code "{ { [ X ] [ Y ] } { [ Z ] [ T ] } } cond" } @@ -78,7 +78,7 @@ HELP: cond "{" " { [ dup 0 > ] [ \"positive\" ] }" " { [ dup 0 < ] [ \"negative\" ] }" - " { [ dup zero? ] [ \"zero\" ] }" + " [ \"zero\" ]" "} cond" } } ; @@ -88,9 +88,9 @@ HELP: no-cond { $error-description "Thrown by " { $link cond } " if none of the test quotations yield a true value. Some uses of " { $link cond } " include a default case where the test quotation is " { $snippet "[ t ]" } "; such a " { $link cond } " form will never throw this error." } ; HELP: case -{ $values { "obj" object } { "assoc" "a sequence of object/quotation pairs, with an optional quotation at the end" } } +{ $values { "obj" object } { "assoc" "a sequence of object/word,quotation pairs, with an optional quotation at the end" } } { $description - "Compares " { $snippet "obj" } " against the first element of every pair. If some pair matches, removes " { $snippet "obj" } " from the stack and calls the second element of that pair, which must be a quotation." + "Compares " { $snippet "obj" } " against the first element of every pair, first evaluating the first element if it is a word. If some pair matches, removes " { $snippet "obj" } " from the stack and calls the second element of that pair, which must be a quotation." $nl "If there is no case matching " { $snippet "obj" } ", the default case is taken. If the last element of " { $snippet "cases" } " is a quotation, the quotation is called with " { $snippet "obj" } " on the stack. Otherwise, a " { $link no-cond } " error is rasied." $nl diff --git a/core/combinators/combinators-tests.factor b/core/combinators/combinators-tests.factor index 8abc53e43f..b612669b71 100755 --- a/core/combinators/combinators-tests.factor +++ b/core/combinators/combinators-tests.factor @@ -1,7 +1,54 @@ -IN: combinators.tests USING: alien strings kernel math tools.test io prettyprint -namespaces combinators words ; +namespaces combinators words classes sequences ; +IN: combinators.tests +! Compiled +: cond-test-1 ( obj -- str ) + { + { [ dup 2 mod 0 = ] [ drop "even" ] } + { [ dup 2 mod 1 = ] [ drop "odd" ] } + } cond ; + +\ cond-test-1 must-infer + +[ "even" ] [ 2 cond-test-1 ] unit-test +[ "odd" ] [ 3 cond-test-1 ] unit-test + +: cond-test-2 ( obj -- str ) + { + { [ dup t = ] [ drop "true" ] } + { [ dup f = ] [ drop "false" ] } + [ drop "something else" ] + } cond ; + +\ cond-test-2 must-infer + +[ "true" ] [ t cond-test-2 ] unit-test +[ "false" ] [ f cond-test-2 ] unit-test +[ "something else" ] [ "ohio" cond-test-2 ] unit-test + +: cond-test-3 ( obj -- str ) + { + [ drop "something else" ] + { [ dup t = ] [ drop "true" ] } + { [ dup f = ] [ drop "false" ] } + } cond ; + +\ cond-test-3 must-infer + +[ "something else" ] [ t cond-test-3 ] unit-test +[ "something else" ] [ f cond-test-3 ] unit-test +[ "something else" ] [ "ohio" cond-test-3 ] unit-test + +: cond-test-4 ( -- ) + { + } cond ; + +\ cond-test-4 must-infer + +[ cond-test-4 ] [ class \ no-cond = ] must-fail-with + +! Interpreted [ "even" ] [ 2 { { [ dup 2 mod 0 = ] [ drop "even" ] } @@ -21,11 +68,66 @@ namespaces combinators words ; { [ dup string? ] [ drop "string" ] } { [ dup float? ] [ drop "float" ] } { [ dup alien? ] [ drop "alien" ] } - { [ t ] [ drop "neither" ] } + [ drop "neither" ] } cond ] unit-test -: case-test-1 +[ "neither" ] [ + 3 { + { [ dup string? ] [ drop "string" ] } + { [ dup float? ] [ drop "float" ] } + { [ dup alien? ] [ drop "alien" ] } + [ drop "neither" ] + } cond +] unit-test + +[ "neither" ] [ + 3 { + { [ dup string? ] [ drop "string" ] } + { [ dup float? ] [ drop "float" ] } + { [ dup alien? ] [ drop "alien" ] } + [ drop "neither" ] + } cond +] unit-test + +[ "early" ] [ + 2 { + { [ dup 2 mod 1 = ] [ drop "odd" ] } + [ drop "early" ] + { [ dup 2 mod 0 = ] [ drop "even" ] } + } cond +] unit-test + +[ "really early" ] [ + 2 { + [ drop "really early" ] + { [ dup 2 mod 1 = ] [ drop "odd" ] } + { [ dup 2 mod 0 = ] [ drop "even" ] } + } cond +] unit-test + +[ { } cond ] [ class \ no-cond = ] must-fail-with + +[ "early" ] [ + 2 { + { [ dup 2 mod 1 = ] [ drop "odd" ] } + [ drop "early" ] + { [ dup 2 mod 0 = ] [ drop "even" ] } + } cond +] unit-test + +[ "really early" ] [ + 2 { + [ drop "really early" ] + { [ dup 2 mod 1 = ] [ drop "odd" ] } + { [ dup 2 mod 0 = ] [ drop "even" ] } + } cond +] unit-test + +[ { } cond ] [ class \ no-cond = ] must-fail-with + +! Compiled +: case-test-1 ( obj -- obj' ) { { 1 [ "one" ] } { 2 [ "two" ] } @@ -33,6 +135,8 @@ namespaces combinators words ; { 4 [ "four" ] } } case ; +\ case-test-1 must-infer + [ "two" ] [ 2 case-test-1 ] unit-test ! Interpreted @@ -40,7 +144,7 @@ namespaces combinators words ; [ "x" case-test-1 ] must-fail -: case-test-2 +: case-test-2 ( obj -- obj' ) { { 1 [ "one" ] } { 2 [ "two" ] } @@ -49,12 +153,14 @@ namespaces combinators words ; [ sq ] } case ; +\ case-test-2 must-infer + [ 25 ] [ 5 case-test-2 ] unit-test ! Interpreted [ 25 ] [ 5 \ case-test-2 word-def call ] unit-test -: case-test-3 +: case-test-3 ( obj -- obj' ) { { 1 [ "one" ] } { 2 [ "two" ] } @@ -65,8 +171,122 @@ namespaces combinators words ; [ sq ] } case ; +\ case-test-3 must-infer + [ "an array" ] [ { 1 2 3 } case-test-3 ] unit-test +: case-const-1 1 ; +: case-const-2 2 ; inline + +! Compiled +: case-test-4 ( obj -- str ) + { + { case-const-1 [ "uno" ] } + { case-const-2 [ "dos" ] } + { 3 [ "tres" ] } + { 4 [ "cuatro" ] } + { 5 [ "cinco" ] } + [ drop "demasiado" ] + } case ; + +\ case-test-4 must-infer + +[ "uno" ] [ 1 case-test-4 ] unit-test +[ "dos" ] [ 2 case-test-4 ] unit-test +[ "tres" ] [ 3 case-test-4 ] unit-test +[ "demasiado" ] [ 100 case-test-4 ] unit-test + +: case-test-5 ( obj -- ) + { + { case-const-1 [ "uno" print ] } + { case-const-2 [ "dos" print ] } + { 3 [ "tres" print ] } + { 4 [ "cuatro" print ] } + { 5 [ "cinco" print ] } + [ drop "demasiado" print ] + } case ; + +\ case-test-5 must-infer + +[ ] [ 1 case-test-5 ] unit-test + +! Interpreted +[ "uno" ] [ + 1 { + { case-const-1 [ "uno" ] } + { case-const-2 [ "dos" ] } + { 3 [ "tres" ] } + { 4 [ "cuatro" ] } + { 5 [ "cinco" ] } + [ drop "demasiado" ] + } case +] unit-test + +[ "dos" ] [ + 2 { + { case-const-1 [ "uno" ] } + { case-const-2 [ "dos" ] } + { 3 [ "tres" ] } + { 4 [ "cuatro" ] } + { 5 [ "cinco" ] } + [ drop "demasiado" ] + } case +] unit-test + +[ "tres" ] [ + 3 { + { case-const-1 [ "uno" ] } + { case-const-2 [ "dos" ] } + { 3 [ "tres" ] } + { 4 [ "cuatro" ] } + { 5 [ "cinco" ] } + [ drop "demasiado" ] + } case +] unit-test + +[ "demasiado" ] [ + 100 { + { case-const-1 [ "uno" ] } + { case-const-2 [ "dos" ] } + { 3 [ "tres" ] } + { 4 [ "cuatro" ] } + { 5 [ "cinco" ] } + [ drop "demasiado" ] + } case +] unit-test + +: do-not-call "do not call" throw ; + +: test-case-6 + { + { \ do-not-call [ "do-not-call" ] } + { 3 [ "three" ] } + } case ; + +[ "three" ] [ 3 test-case-6 ] unit-test +[ "do-not-call" ] [ \ do-not-call test-case-6 ] unit-test + +[ "three" ] [ + 3 { + { \ do-not-call [ "do-not-call" ] } + { 3 [ "three" ] } + } case +] unit-test + +[ "do-not-call" ] [ + [ do-not-call ] first { + { \ do-not-call [ "do-not-call" ] } + { 3 [ "three" ] } + } case +] unit-test + +[ "do-not-call" ] [ + \ do-not-call { + { \ do-not-call [ "do-not-call" ] } + { 3 [ "three" ] } + } case +] unit-test + ! Interpreted [ "a hashtable" ] [ H{ } \ case-test-3 word-def call ] unit-test diff --git a/core/combinators/combinators.factor b/core/combinators/combinators.factor index 96c4009ba9..11ad8d60e7 100755 --- a/core/combinators/combinators.factor +++ b/core/combinators/combinators.factor @@ -3,7 +3,7 @@ IN: combinators USING: arrays sequences sequences.private math.private kernel kernel.private math assocs quotations vectors -hashtables sorting ; +hashtables sorting words ; : cleave ( x seq -- ) [ call ] with each ; @@ -34,13 +34,24 @@ hashtables sorting ; ERROR: no-cond ; : cond ( assoc -- ) - [ first call ] find nip dup [ second call ] [ no-cond ] if ; + [ dup callable? [ drop t ] [ first call ] if ] find nip + [ dup callable? [ call ] [ second call ] if ] + [ no-cond ] if* ; ERROR: no-case ; +: case-find ( obj assoc -- obj' ) + [ + dup array? [ + dupd first dup word? [ + execute + ] [ + dup wrapper? [ wrapped ] when + ] if = + ] [ quotation? ] if + ] find nip ; : case ( obj assoc -- ) - [ dup array? [ dupd first = ] [ quotation? ] if ] find nip - { + case-find { { [ dup array? ] [ nip second call ] } { [ dup quotation? ] [ call ] } { [ dup not ] [ no-case ] } @@ -73,11 +84,14 @@ M: hashtable hashcode* [ rot \ if 3array append [ ] like ] assoc-each ; : cond>quot ( assoc -- quot ) + [ dup callable? [ [ t ] swap 2array ] when ] map reverse [ no-cond ] swap alist>quot ; : linear-case-quot ( default assoc -- quot ) - [ >r [ dupd = ] curry r> \ drop prefix ] assoc-map - alist>quot ; + [ + [ 1quotation \ dup prefix \ = suffix ] + [ \ drop prefix ] bi* + ] assoc-map alist>quot ; : (distribute-buckets) ( buckets pair keys -- ) dup t eq? [ @@ -135,7 +149,9 @@ M: hashtable hashcode* dup empty? [ drop ] [ - dup length 4 <= [ + dup length 4 <= + over keys [ word? ] contains? or + [ linear-case-quot ] [ dup keys contiguous-range? [ diff --git a/core/compiler/tests/simple.factor b/core/compiler/tests/simple.factor index 09b0c190e6..dce2ec562a 100755 --- a/core/compiler/tests/simple.factor +++ b/core/compiler/tests/simple.factor @@ -187,7 +187,7 @@ DEFER: countdown-b { [ dup string? ] [ drop "string" ] } { [ dup float? ] [ drop "float" ] } { [ dup alien? ] [ drop "alien" ] } - { [ t ] [ drop "neither" ] } + [ drop "neither" ] } cond ] compile-call ] unit-test @@ -196,7 +196,7 @@ DEFER: countdown-b [ 3 { { [ dup fixnum? ] [ ] } - { [ t ] [ drop t ] } + [ drop t ] } cond ] compile-call ] unit-test diff --git a/core/continuations/continuations-docs.factor b/core/continuations/continuations-docs.factor index b3adb1b165..b1db09b6bc 100755 --- a/core/continuations/continuations-docs.factor +++ b/core/continuations/continuations-docs.factor @@ -90,7 +90,11 @@ ABOUT: "continuations" HELP: dispose { $values { "object" "a disposable object" } } -{ $contract "Releases operating system resources associated with a disposable object. No further operations can be performed on a disposable object after this call. Disposable objects include streams, memory mapped files, and so on." } +{ $contract "Releases operating system resources associated with a disposable object. Disposable objects include streams, memory mapped files, and so on." +$nl +"No further operations can be performed on a disposable object after this call." +$nl +"Disposing an object which has already been disposed should have no effect, and in particular it should not fail with an error." } { $notes "You must close disposable objects after you are finished working with them, to avoid leaking operating system resources. A convenient way to automate this is by using the " { $link with-disposal } " word." } ; HELP: with-disposal diff --git a/core/cpu/x86/32/32.factor b/core/cpu/x86/32/32.factor index 699670aecd..cc3fceff23 100755 --- a/core/cpu/x86/32/32.factor +++ b/core/cpu/x86/32/32.factor @@ -246,9 +246,8 @@ M: x86.32 %cleanup ( alien-node -- ) } { [ dup return>> large-struct? ] [ drop EAX PUSH ] - } { - [ t ] [ drop ] } + [ drop ] } cond ; M: x86.32 %unwind ( n -- ) %epilogue-later RET ; diff --git a/core/cpu/x86/assembler/assembler.factor b/core/cpu/x86/assembler/assembler.factor index a3ab256ea1..450aa8f980 100755 --- a/core/cpu/x86/assembler/assembler.factor +++ b/core/cpu/x86/assembler/assembler.factor @@ -189,7 +189,7 @@ UNION: operand register indirect ; { { [ dup register-128? ] [ drop operand-64? ] } { [ dup not ] [ drop operand-64? ] } - { [ t ] [ nip operand-64? ] } + [ nip operand-64? ] } cond and ; : rex.r diff --git a/core/debugger/debugger.factor b/core/debugger/debugger.factor index 071535a01e..dea1904e92 100755 --- a/core/debugger/debugger.factor +++ b/core/debugger/debugger.factor @@ -160,7 +160,7 @@ PREDICATE: kernel-error < array { { [ dup empty? ] [ drop f ] } { [ dup first "kernel-error" = not ] [ drop f ] } - { [ t ] [ second 0 15 between? ] } + [ second 0 15 between? ] } cond ; : kernel-errors diff --git a/core/dlists/dlists.factor b/core/dlists/dlists.factor index 56134f3b54..b4ae207455 100755 --- a/core/dlists/dlists.factor +++ b/core/dlists/dlists.factor @@ -126,7 +126,7 @@ PRIVATE> { { [ over front>> over eq? ] [ drop pop-front* ] } { [ over back>> over eq? ] [ drop pop-back* ] } - { [ t ] [ unlink-node dec-length ] } + [ unlink-node dec-length ] } cond ; : delete-node-if* ( dlist quot -- obj/f ? ) diff --git a/core/effects/effects.factor b/core/effects/effects.factor index aed4a64c6c..7da290992c 100755 --- a/core/effects/effects.factor +++ b/core/effects/effects.factor @@ -20,7 +20,7 @@ TUPLE: effect in out terminated? ; { [ dup effect-terminated? ] [ f ] } { [ 2dup [ effect-in length ] bi@ > ] [ f ] } { [ 2dup [ effect-height ] bi@ = not ] [ f ] } - { [ t ] [ t ] } + [ t ] } cond 2nip ; GENERIC: (stack-picture) ( obj -- str ) diff --git a/core/generator/fixup/fixup.factor b/core/generator/fixup/fixup.factor index 5cc0442464..3a5a6571b7 100755 --- a/core/generator/fixup/fixup.factor +++ b/core/generator/fixup/fixup.factor @@ -40,8 +40,8 @@ M: label fixup* M: word fixup* { - { %prologue-later [ dup [ %prologue ] if-stack-frame ] } - { %epilogue-later [ dup [ %epilogue ] if-stack-frame ] } + { \ %prologue-later [ dup [ %prologue ] if-stack-frame ] } + { \ %epilogue-later [ dup [ %epilogue ] if-stack-frame ] } } case ; SYMBOL: relocation-table diff --git a/core/generator/generator.factor b/core/generator/generator.factor index 3514947e3d..7858205384 100755 --- a/core/generator/generator.factor +++ b/core/generator/generator.factor @@ -16,7 +16,7 @@ SYMBOL: compiled { [ dup compiled get key? ] [ drop ] } { [ dup inlined-block? ] [ drop ] } { [ dup primitive? ] [ drop ] } - { [ t ] [ dup compile-queue get set-at ] } + [ dup compile-queue get set-at ] } cond ; : maybe-compile ( word -- ) diff --git a/core/generator/registers/registers.factor b/core/generator/registers/registers.factor index f3dc0fb10e..8abd1cd3e0 100755 --- a/core/generator/registers/registers.factor +++ b/core/generator/registers/registers.factor @@ -195,7 +195,7 @@ INSTANCE: constant value { [ dup byte-array class< ] [ drop %unbox-byte-array ] } { [ dup bit-array class< ] [ drop %unbox-byte-array ] } { [ dup float-array class< ] [ drop %unbox-byte-array ] } - { [ t ] [ drop %unbox-any-c-ptr ] } + [ drop %unbox-any-c-ptr ] } cond ; inline : %move-via-temp ( dst src -- ) @@ -357,14 +357,14 @@ SYMBOL: fresh-objects { [ dup unboxed-c-ptr eq? ] [ over { unboxed-byte-array unboxed-alien } member? ] } - { [ t ] [ f ] } + [ f ] } cond 2nip ; : allocation ( value spec -- reg-class ) { { [ dup quotation? ] [ 2drop f ] } { [ 2dup compatible? ] [ 2drop f ] } - { [ t ] [ nip reg-spec>class ] } + [ nip reg-spec>class ] } cond ; : alloc-vreg-for ( value spec -- vreg ) diff --git a/core/generic/math/math.factor b/core/generic/math/math.factor index fce908bdef..884ab8027e 100755 --- a/core/generic/math/math.factor +++ b/core/generic/math/math.factor @@ -19,7 +19,7 @@ PREDICATE: math-class < class { { [ dup null class< ] [ drop { -1 -1 } ] } { [ dup math-class? ] [ class-types last/first ] } - { [ t ] [ drop { 100 100 } ] } + [ drop { 100 100 } ] } cond ; : math-class-max ( class class -- class ) diff --git a/core/generic/standard/engines/predicate/predicate.factor b/core/generic/standard/engines/predicate/predicate.factor index ce7d5c6c21..5335074dea 100644 --- a/core/generic/standard/engines/predicate/predicate.factor +++ b/core/generic/standard/engines/predicate/predicate.factor @@ -18,7 +18,7 @@ C: predicate-dispatch-engine { [ dup empty? ] [ drop [ "Unreachable" throw ] { } ] } { [ dup length 1 = ] [ first second { } ] } { [ dup keep-going? ] [ 1 tail-slice prune-redundant-predicates ] } - { [ t ] [ [ first second ] [ 1 tail-slice ] bi ] } + [ [ first second ] [ 1 tail-slice ] bi ] } cond ; : sort-methods ( assoc -- assoc' ) diff --git a/core/generic/standard/standard.factor b/core/generic/standard/standard.factor index ed5134a624..98194e7ef3 100644 --- a/core/generic/standard/standard.factor +++ b/core/generic/standard/standard.factor @@ -110,6 +110,9 @@ ERROR: no-next-method class generic ; \ if , ] [ ] make ; +: single-effective-method ( obj word -- method ) + [ order [ instance? ] with find-last nip ] keep method ; + TUPLE: standard-combination # ; C: standard-combination @@ -142,8 +145,7 @@ M: standard-combination next-method-quot* ] with-standard ; M: standard-generic effective-method - [ dispatch# (picker) call ] keep - [ order [ instance? ] with find-last nip ] keep method ; + [ dispatch# (picker) call ] keep single-effective-method ; TUPLE: hook-combination var ; @@ -161,6 +163,10 @@ M: hook-combination dispatch# drop 0 ; M: hook-generic extra-values drop 1 ; +M: hook-generic effective-method + [ "combination" word-prop var>> get ] keep + single-effective-method ; + M: hook-combination make-default-method [ error-method ] with-hook ; diff --git a/core/graphs/graphs-docs.factor b/core/graphs/graphs-docs.factor index 1e4350d58c..f16f8cca3b 100644 --- a/core/graphs/graphs-docs.factor +++ b/core/graphs/graphs-docs.factor @@ -21,12 +21,12 @@ HELP: graph HELP: add-vertex { $values { "vertex" object } { "edges" "a sequence" } { "graph" "an assoc mapping vertices to sequences of edges" } } -{ $description "Adds a vertex to a directed graph, using the " { $snippet "edges" } " quotation to generate a sequence of edges leaving the vertex." } +{ $description "Adds a vertex to a directed graph, with " { $snippet "edges" } " as the outward edges from the vertex." } { $side-effects "graph" } ; HELP: remove-vertex { $values { "vertex" object } { "edges" "a sequence" } { "graph" "an assoc mapping vertices to sequences of edges" } } -{ $description "Removes a vertex from a graph, using the quotation to generate a sequence of edges leaving the vertex." } +{ $description "Removes a vertex from a graph, using the given edges sequence." } { $notes "The " { $snippet "edges" } " sequence must equal the value passed to " { $link add-vertex } ", otherwise some vertices of the graph may continue to refer to the removed vertex." } { $side-effects "graph" } ; diff --git a/core/inference/backend/backend.factor b/core/inference/backend/backend.factor index 3dcb1d2360..1945ed1a38 100755 --- a/core/inference/backend/backend.factor +++ b/core/inference/backend/backend.factor @@ -251,7 +251,7 @@ TUPLE: cannot-unify-specials ; { [ dup [ curried? ] all? ] [ unify-curries ] } { [ dup [ composed? ] all? ] [ unify-composed ] } { [ dup [ special? ] contains? ] [ cannot-unify-specials ] } - { [ t ] [ drop ] } + [ drop ] } cond ; : unify-stacks ( seq -- stack ) @@ -395,7 +395,7 @@ TUPLE: effect-error word effect ; { [ dup "infer" word-prop ] [ custom-infer ] } { [ dup "no-effect" word-prop ] [ no-effect ] } { [ dup "inferred-effect" word-prop ] [ cached-infer ] } - { [ t ] [ dup infer-word make-call-node ] } + [ dup infer-word make-call-node ] } cond ; TUPLE: recursive-declare-error word ; diff --git a/core/io/encodings/utf8/utf8.factor b/core/io/encodings/utf8/utf8.factor index e98860f25d..7a22107f19 100644 --- a/core/io/encodings/utf8/utf8.factor +++ b/core/io/encodings/utf8/utf8.factor @@ -33,7 +33,7 @@ TUPLE: utf8 ; { [ dup -5 shift BIN: 110 number= ] [ double ] } { [ dup -4 shift BIN: 1110 number= ] [ triple ] } { [ dup -3 shift BIN: 11110 number= ] [ quad ] } - { [ t ] [ drop replacement-char ] } + [ drop replacement-char ] } cond ; : decode-utf8 ( stream -- char/f ) @@ -59,12 +59,12 @@ M: utf8 decode-char 2dup -6 shift encoded encoded ] } - { [ t ] [ + [ 2dup -18 shift BIN: 11110000 bitor swap stream-write1 2dup -12 shift encoded 2dup -6 shift encoded encoded - ] } + ] } cond ; M: utf8 encode-char diff --git a/core/io/files/files-docs.factor b/core/io/files/files-docs.factor index e3f86c079d..0d49e344a8 100755 --- a/core/io/files/files-docs.factor +++ b/core/io/files/files-docs.factor @@ -112,8 +112,7 @@ ARTICLE: "io.files" "Basic file operations" { $subsection "file-streams" } { $subsection "fs-meta" } { $subsection "directories" } -{ $subsection "delete-move-copy" } -{ $see-also "os" } ; +{ $subsection "delete-move-copy" } ; ABOUT: "io.files" diff --git a/core/io/files/files.factor b/core/io/files/files.factor index 6719d1334c..061e6386da 100755 --- a/core/io/files/files.factor +++ b/core/io/files/files.factor @@ -95,7 +95,7 @@ ERROR: no-parent-directory path ; 1 tail left-trim-separators append-path-empty ] } { [ dup head..? ] [ drop no-parent-directory ] } - { [ t ] [ nip ] } + [ nip ] } cond ; PRIVATE> @@ -105,7 +105,7 @@ PRIVATE> { [ dup "\\\\?\\" head? ] [ t ] } { [ dup length 2 < ] [ f ] } { [ dup second CHAR: : = ] [ t ] } - { [ t ] [ f ] } + [ f ] } cond ; : absolute-path? ( path -- ? ) @@ -114,7 +114,7 @@ PRIVATE> { [ dup "resource:" head? ] [ t ] } { [ os windows? ] [ windows-absolute-path? ] } { [ dup first path-separator? ] [ t ] } - { [ t ] [ f ] } + [ f ] } cond nip ; : append-path ( str1 str2 -- str ) @@ -130,10 +130,10 @@ PRIVATE> { [ over absolute-path? over first path-separator? and ] [ >r 2 head r> append ] } - { [ t ] [ + [ >r right-trim-separators "/" r> left-trim-separators 3append - ] } + ] } cond ; : prepend-path ( str1 str2 -- str ) @@ -220,10 +220,10 @@ HOOK: make-directory io-backend ( path -- ) { [ dup root-directory? ] [ ] } { [ dup empty? ] [ ] } { [ dup exists? ] [ ] } - { [ t ] [ + [ dup parent-directory make-directories dup make-directory - ] } + ] } cond drop ; ! Directory listings @@ -322,9 +322,10 @@ C: pathname M: pathname <=> [ pathname-string ] compare ; ! Home directory -: home ( -- dir ) - { - { [ os winnt? ] [ "USERPROFILE" os-env ] } - { [ os wince? ] [ "" resource-path ] } - { [ os unix? ] [ "HOME" os-env ] } - } cond ; +HOOK: home os ( -- dir ) + +M: winnt home "USERPROFILE" os-env ; + +M: wince home "" resource-path ; + +M: unix home "HOME" os-env ; diff --git a/core/math/intervals/intervals.factor b/core/math/intervals/intervals.factor index cc51060f63..4ca1a8637c 100755 --- a/core/math/intervals/intervals.factor +++ b/core/math/intervals/intervals.factor @@ -103,7 +103,7 @@ C: interval 2drop over second over second and [ ] [ 2drop f ] if ] } - { [ t ] [ 2drop ] } + [ 2drop ] } cond ; : interval-intersect ( i1 i2 -- i3 ) @@ -202,7 +202,7 @@ SYMBOL: incomparable { [ 2dup interval-intersect not ] [ (interval<) ] } { [ 2dup left-endpoint-< ] [ f ] } { [ 2dup right-endpoint-< ] [ f ] } - { [ t ] [ incomparable ] } + [ incomparable ] } cond 2nip ; : left-endpoint-<= ( i1 i2 -- ? ) @@ -215,7 +215,7 @@ SYMBOL: incomparable { { [ 2dup interval-intersect not ] [ (interval<) ] } { [ 2dup right-endpoint-<= ] [ t ] } - { [ t ] [ incomparable ] } + [ incomparable ] } cond 2nip ; : interval> ( i1 i2 -- ? ) diff --git a/core/math/parser/parser.factor b/core/math/parser/parser.factor index 68c4768c87..1a1a080564 100755 --- a/core/math/parser/parser.factor +++ b/core/math/parser/parser.factor @@ -62,7 +62,7 @@ SYMBOL: negative? { { [ dup empty? ] [ drop f ] } { [ f over memq? ] [ drop f ] } - { [ t ] [ radix get [ < ] curry all? ] } + [ radix get [ < ] curry all? ] } cond ; : string>integer ( str -- n/f ) @@ -77,7 +77,7 @@ PRIVATE> { { [ CHAR: / over member? ] [ string>ratio ] } { [ CHAR: . over member? ] [ string>float ] } - { [ t ] [ string>integer ] } + [ string>integer ] } cond r> [ dup [ neg ] when ] when ] with-radix ; @@ -134,10 +134,8 @@ M: ratio >base } { [ CHAR: . over member? ] [ ] - } { - [ t ] - [ ".0" append ] } + [ ".0" append ] } cond ; M: float >base @@ -145,7 +143,7 @@ M: float >base { [ 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" ] } - { [ t ] [ float>string fix-float ] } + [ float>string fix-float ] } cond ; : number>string ( n -- str ) 10 >base ; diff --git a/core/optimizer/control/control-tests.factor b/core/optimizer/control/control-tests.factor index d7638fa66d..ce77cdd43a 100755 --- a/core/optimizer/control/control-tests.factor +++ b/core/optimizer/control/control-tests.factor @@ -9,23 +9,23 @@ optimizer ; { [ over #label? not ] [ 2drop f ] } { [ over #label-word over eq? not ] [ 2drop f ] } { [ over #label-loop? not ] [ 2drop f ] } - { [ t ] [ 2drop t ] } + [ 2drop t ] } cond ] curry node-exists? ; : label-is-not-loop? ( node word -- ? ) [ { - { [ over #label? not ] [ 2drop f ] } - { [ over #label-word over eq? not ] [ 2drop f ] } - { [ over #label-loop? ] [ 2drop f ] } - { [ t ] [ 2drop t ] } - } cond + { [ over #label? not ] [ f ] } + { [ over #label-word over eq? not ] [ f ] } + { [ over #label-loop? ] [ f ] } + [ t ] + } cond 2nip ] curry node-exists? ; : loop-test-1 ( a -- ) dup [ 1+ loop-test-1 ] [ drop ] if ; inline - + [ t ] [ [ loop-test-1 ] dataflow dup detect-loops \ loop-test-1 label-is-loop? diff --git a/core/optimizer/control/control.factor b/core/optimizer/control/control.factor index 11228c879a..f9f8901c41 100755 --- a/core/optimizer/control/control.factor +++ b/core/optimizer/control/control.factor @@ -156,7 +156,7 @@ SYMBOL: potential-loops { [ dup null class< ] [ drop f f ] } { [ dup \ f class-not class< ] [ drop t t ] } { [ dup \ f class< ] [ drop f t ] } - { [ t ] [ drop f f ] } + [ drop f f ] } cond ] if ; diff --git a/core/optimizer/inlining/inlining.factor b/core/optimizer/inlining/inlining.factor index 9d41d6eae1..8447d1be5f 100755 --- a/core/optimizer/inlining/inlining.factor +++ b/core/optimizer/inlining/inlining.factor @@ -36,7 +36,7 @@ DEFER: (flat-length) ! not inline { [ dup inline? not ] [ drop 1 ] } ! inline - { [ t ] [ dup dup set word-def (flat-length) ] } + [ dup dup set word-def (flat-length) ] } cond ; : (flat-length) ( seq -- n ) @@ -45,7 +45,7 @@ DEFER: (flat-length) { [ dup quotation? ] [ (flat-length) 1+ ] } { [ dup array? ] [ (flat-length) ] } { [ dup word? ] [ word-flat-length ] } - { [ t ] [ drop 1 ] } + [ drop 1 ] } cond ] map sum ; @@ -94,7 +94,7 @@ DEFER: (flat-length) dup node-param { { [ dup standard-generic? ] [ inline-standard-method ] } { [ dup math-generic? ] [ inline-math-method ] } - { [ t ] [ 2drop t ] } + [ 2drop t ] } cond ; ! Resolve type checks at compile time where possible @@ -217,5 +217,5 @@ M: #call optimize-node* { [ dup optimize-predicate? ] [ optimize-predicate ] } { [ dup optimistic-inline? ] [ optimistic-inline ] } { [ dup method-body-inline? ] [ optimistic-inline ] } - { [ t ] [ inline-method ] } + [ inline-method ] } cond dup not ; diff --git a/core/optimizer/pattern-match/pattern-match.factor b/core/optimizer/pattern-match/pattern-match.factor index 0e7e801938..5beb2555f0 100755 --- a/core/optimizer/pattern-match/pattern-match.factor +++ b/core/optimizer/pattern-match/pattern-match.factor @@ -19,7 +19,7 @@ SYMBOL: @ { [ dup @ eq? ] [ drop match-@ ] } { [ dup class? ] [ match-class ] } { [ over value? not ] [ 2drop f ] } - { [ t ] [ swap value-literal = ] } + [ swap value-literal = ] } cond ; : node-match? ( node values pattern -- ? ) diff --git a/core/optimizer/specializers/specializers.factor b/core/optimizer/specializers/specializers.factor index d115d0a1c6..b33a9e8fc2 100755 --- a/core/optimizer/specializers/specializers.factor +++ b/core/optimizer/specializers/specializers.factor @@ -57,7 +57,7 @@ IN: optimizer.specializers [ dup "specializer" word-prop ] [ "specializer" word-prop specialize-quot ] } - { [ t ] [ drop ] } + [ drop ] } cond ; : specialized-length ( specializer -- n ) diff --git a/core/parser/parser.factor b/core/parser/parser.factor index 6c09e08f84..1e1d6a5606 100755 --- a/core/parser/parser.factor +++ b/core/parser/parser.factor @@ -324,7 +324,7 @@ M: staging-violation summary { [ dup not ] [ drop unexpected-eof t ] } { [ dup delimiter? ] [ unexpected t ] } { [ dup parsing? ] [ nip execute-parsing t ] } - { [ t ] [ pick push drop t ] } + [ pick push drop t ] } cond ; : (parse-until) ( accum end -- accum ) diff --git a/core/prettyprint/prettyprint.factor b/core/prettyprint/prettyprint.factor index 03d3e456ca..e1a53696af 100755 --- a/core/prettyprint/prettyprint.factor +++ b/core/prettyprint/prettyprint.factor @@ -107,7 +107,7 @@ SYMBOL: -> { [ dup word? not ] [ , ] } { [ dup "break?" word-prop ] [ drop ] } { [ dup "step-into?" word-prop ] [ remove-step-into ] } - { [ t ] [ , ] } + [ , ] } cond ] each ] [ ] make ; diff --git a/core/syntax/syntax.factor b/core/syntax/syntax.factor index 005672c1c6..0c759265e9 100755 --- a/core/syntax/syntax.factor +++ b/core/syntax/syntax.factor @@ -61,7 +61,7 @@ IN: bootstrap.syntax scan { { [ dup length 1 = ] [ first ] } { [ "\\" ?head ] [ next-escape drop ] } - { [ t ] [ name>char-hook get call ] } + [ name>char-hook get call ] } cond parsed ] define-syntax diff --git a/core/system/system-docs.factor b/core/system/system-docs.factor index d0b2cfb194..5aac0a8e8c 100755 --- a/core/system/system-docs.factor +++ b/core/system/system-docs.factor @@ -101,7 +101,7 @@ HELP: set-os-envs { $values { "assoc" "an association mapping strings to strings" } } { $description "Replaces the current set of environment variables." } { $notes - "Names and values of environment variables are operating system-specific." + "Names and values of environment variables are operating system-specific. Windows NT allows values up to 32766 characters in length." } { $errors "Windows CE has no concept of environment variables, so this word throws an error there." } ; diff --git a/core/system/system-tests.factor b/core/system/system-tests.factor index d5a48080c2..c731a14725 100755 --- a/core/system/system-tests.factor +++ b/core/system/system-tests.factor @@ -1,4 +1,5 @@ -USING: math tools.test system prettyprint namespaces kernel ; +USING: math tools.test system prettyprint namespaces kernel +strings sequences ; IN: system.tests os wince? [ @@ -19,3 +20,8 @@ os unix? [ [ ] [ "factor-test-key-1" unset-os-env ] unit-test [ f ] [ "factor-test-key-1" os-env ] unit-test +[ ] [ + 32766 CHAR: a "factor-test-key-long" set-os-env +] unit-test +[ 32766 ] [ "factor-test-key-long" os-env length ] unit-test +[ ] [ "factor-test-key-long" unset-os-env ] unit-test diff --git a/core/threads/threads.factor b/core/threads/threads.factor index d7d7988893..8623255cd2 100755 --- a/core/threads/threads.factor +++ b/core/threads/threads.factor @@ -4,7 +4,7 @@ IN: threads USING: arrays hashtables heaps kernel kernel.private math namespaces sequences vectors continuations continuations.private -dlists assocs system combinators init boxes ; +dlists assocs system combinators init boxes accessors ; SYMBOL: initial-thread @@ -18,11 +18,10 @@ mailbox variables sleep-entry ; ! Thread-local storage : tnamespace ( -- assoc ) - self dup thread-variables - [ ] [ H{ } clone dup rot set-thread-variables ] ?if ; + self variables>> [ H{ } clone dup self (>>variables) ] unless* ; : tget ( key -- value ) - self thread-variables at ; + self variables>> at ; : tset ( value key -- ) tnamespace set-at ; @@ -35,7 +34,7 @@ mailbox variables sleep-entry ; : thread ( id -- thread ) threads at ; : thread-registered? ( thread -- ? ) - thread-id threads key? ; + id>> threads key? ; : check-unregistered dup thread-registered? @@ -48,59 +47,58 @@ mailbox variables sleep-entry ; > threads set-at ; : unregister-thread ( thread -- ) - check-registered thread-id threads delete-at ; + check-registered id>> threads delete-at ; : set-self ( thread -- ) 40 setenv ; inline PRIVATE> : ( quot name -- thread ) - \ thread counter [ ] { - set-thread-quot - set-thread-name - set-thread-id - set-thread-continuation - set-thread-exit-handler - } \ thread construct ; + \ thread construct-empty + swap >>name + swap >>quot + \ thread counter >>id + >>continuation + [ ] >>exit-handler ; : run-queue 42 getenv ; : sleep-queue 43 getenv ; : resume ( thread -- ) - f over set-thread-state + f >>state check-registered run-queue push-front ; : resume-now ( thread -- ) - f over set-thread-state + f >>state check-registered run-queue push-back ; : resume-with ( obj thread -- ) - f over set-thread-state + f >>state check-registered 2array run-queue push-front ; : sleep-time ( -- ms/f ) { { [ run-queue dlist-empty? not ] [ 0 ] } { [ sleep-queue heap-empty? ] [ f ] } - { [ t ] [ sleep-queue heap-peek nip millis [-] ] } + [ sleep-queue heap-peek nip millis [-] ] } cond ; r check-registered dup r> sleep-queue heap-push* - swap set-thread-sleep-entry ; + >>sleep-entry drop ; : expire-sleep? ( heap -- ? ) dup heap-empty? [ drop f ] [ heap-peek nip millis <= ] if ; : expire-sleep ( thread -- ) - f over set-thread-sleep-entry resume ; + f >>sleep-entry resume ; : expire-sleep-loop ( -- ) sleep-queue @@ -123,21 +121,21 @@ PRIVATE> ] [ pop-back dup array? [ first2 ] [ f swap ] if dup set-self - f over set-thread-state - thread-continuation box> + f >>state + continuation>> box> continue-with ] if ; PRIVATE> : stop ( -- ) - self dup thread-exit-handler call + self dup exit-handler>> call unregister-thread next ; : suspend ( quot state -- obj ) [ - self thread-continuation >box - self set-thread-state + self continuation>> >box + self (>>state) self swap call next ] callcc1 2nip ; inline @@ -157,9 +155,9 @@ M: real sleep millis + >integer sleep-until ; : interrupt ( thread -- ) - dup thread-state [ - dup thread-sleep-entry [ sleep-queue heap-delete ] when* - f over set-thread-sleep-entry + dup state>> [ + dup sleep-entry>> [ sleep-queue heap-delete ] when* + f >>sleep-entry dup resume ] when drop ; @@ -171,7 +169,7 @@ M: real sleep V{ } set-catchstack { } set-retainstack >r { } set-datastack r> - thread-quot [ call stop ] call-clear + quot>> [ call stop ] call-clear ] 1 (throw) ] "spawn" suspend 2drop ; @@ -196,8 +194,8 @@ GENERIC: error-in-thread ( error thread -- ) 43 setenv initial-thread global [ drop f "Initial" ] cache - over set-thread-continuation - f over set-thread-state + >>continuation + f >>state dup register-thread set-self ; diff --git a/core/words/words-docs.factor b/core/words/words-docs.factor index a715aab64f..f259378f7e 100755 --- a/core/words/words-docs.factor +++ b/core/words/words-docs.factor @@ -284,7 +284,7 @@ HELP: HELP: gensym { $values { "word" word } } -{ $description "Creates an uninterned word that is not equal to any other word in the system. Gensyms have an automatically-generated name based on a prefix and an incrementing counter." } +{ $description "Creates an uninterned word that is not equal to any other word in the system." } { $examples { $unchecked-example "gensym ." "G:260561" } } { $notes "Gensyms are often used as placeholder values that have no meaning of their own but must be unique. For example, the compiler uses gensyms to label sections of code." } ; diff --git a/core/words/words.factor b/core/words/words.factor index 7794a7f41f..e1d2f11356 100755 --- a/core/words/words.factor +++ b/core/words/words.factor @@ -2,8 +2,7 @@ ! See http://factorcode.org/license.txt for BSD license. USING: arrays definitions graphs assocs kernel kernel.private slots.private math namespaces sequences strings vectors sbufs -quotations assocs hashtables sorting math.parser words.private -vocabs combinators ; +quotations assocs hashtables sorting words.private vocabs ; IN: words : word ( -- word ) \ word get-global ; @@ -66,11 +65,11 @@ SYMBOL: bootstrapping? GENERIC: crossref? ( word -- ? ) M: word crossref? - { - { [ dup "forgotten" word-prop ] [ f ] } - { [ dup word-vocabulary ] [ t ] } - { [ t ] [ f ] } - } cond nip ; + dup "forgotten" word-prop [ + drop f + ] [ + word-vocabulary >boolean + ] if ; GENERIC# (quot-uses) 1 ( obj assoc -- ) @@ -191,7 +190,7 @@ M: word subwords drop f ; { "methods" "combination" "default-method" } reset-props ; : gensym ( -- word ) - "G:" \ gensym counter number>string append f ; + "( gensym )" f ; : define-temp ( quot -- word ) gensym dup rot define ; diff --git a/extra/bootstrap/random/random.factor b/extra/bootstrap/random/random.factor index fa0c54d0c6..782cf16e9e 100755 --- a/extra/bootstrap/random/random.factor +++ b/extra/bootstrap/random/random.factor @@ -9,6 +9,7 @@ namespaces random ; { [ os unix? ] [ "random.unix" require ] } } cond -! [ [ 32 random-bits ] with-secure-random random-generator set-global ] -[ millis random-generator set-global ] -"generator.random" add-init-hook +[ + [ 32 random-bits ] with-secure-random + random-generator set-global +] "generator.random" add-init-hook diff --git a/extra/bunny/model/model.factor b/extra/bunny/model/model.factor index 2cb0df5ca1..6010a340a7 100755 --- a/extra/bunny/model/model.factor +++ b/extra/bunny/model/model.factor @@ -13,7 +13,7 @@ IN: bunny.model numbers { { [ dup length 5 = ] [ 3 head pick push ] } { [ dup first 3 = ] [ 1 tail over push ] } - { [ t ] [ drop ] } + [ drop ] } cond (parse-model) ] when* ; diff --git a/extra/cairo/png/png.factor b/extra/cairo/png/png.factor index f9908e4581..2fc2a26c6a 100755 --- a/extra/cairo/png/png.factor +++ b/extra/cairo/png/png.factor @@ -10,17 +10,17 @@ TUPLE: png-gadget png ; ERROR: cairo-error string ; -: check-zero +: check-zero ( n -- n ) dup zero? [ "PNG dimension is 0" cairo-error ] when ; : cairo-png-error ( n -- ) { - { [ dup CAIRO_STATUS_NO_MEMORY = ] [ "Cairo: no memory" cairo-error ] } - { [ dup CAIRO_STATUS_FILE_NOT_FOUND = ] [ "Cairo: file not found" cairo-error ] } - { [ dup CAIRO_STATUS_READ_ERROR = ] [ "Cairo: read error" cairo-error ] } - { [ t ] [ drop ] } + { CAIRO_STATUS_NO_MEMORY [ "Cairo: no memory" cairo-error ] } + { CAIRO_STATUS_FILE_NOT_FOUND [ "Cairo: file not found" cairo-error ] } + { CAIRO_STATUS_READ_ERROR [ "Cairo: read error" cairo-error ] } + [ drop ] } cond ; : ( path -- png ) diff --git a/extra/calendar/windows/windows.factor b/extra/calendar/windows/windows.factor index 2986422155..b621d3bde3 100755 --- a/extra/calendar/windows/windows.factor +++ b/extra/calendar/windows/windows.factor @@ -5,12 +5,11 @@ IN: calendar.windows M: windows gmt-offset ( -- hours minutes seconds ) "TIME_ZONE_INFORMATION" dup GetTimeZoneInformation { - { [ dup TIME_ZONE_ID_INVALID = ] [ win32-error-string throw ] } - { [ dup [ TIME_ZONE_ID_UNKNOWN = ] [ TIME_ZONE_ID_STANDARD = ] bi or ] [ - drop TIME_ZONE_INFORMATION-Bias ] } - { [ dup TIME_ZONE_ID_DAYLIGHT = ] [ - drop + { TIME_ZONE_ID_INVALID [ win32-error-string throw ] } + { TIME_ZONE_ID_UNKNOWN [ TIME_ZONE_INFORMATION-Bias ] } + { TIME_ZONE_ID_STANDARD [ TIME_ZONE_INFORMATION-Bias ] } + { TIME_ZONE_ID_DAYLIGHT [ [ TIME_ZONE_INFORMATION-Bias ] [ TIME_ZONE_INFORMATION-DaylightBias ] bi + ] } - } cond neg 60 /mod 0 ; + } case neg 60 /mod 0 ; diff --git a/extra/cocoa/application/application.factor b/extra/cocoa/application/application.factor index 0cf020a087..129b949b1d 100755 --- a/extra/cocoa/application/application.factor +++ b/extra/cocoa/application/application.factor @@ -1,8 +1,9 @@ ! Copyright (C) 2006, 2007 Slava Pestov ! See http://factorcode.org/license.txt for BSD license. -USING: alien io kernel namespaces core-foundation cocoa.messages -cocoa cocoa.classes cocoa.runtime sequences threads -debugger init inspector kernel.private ; +USING: alien io kernel namespaces core-foundation +core-foundation.run-loop cocoa.messages cocoa cocoa.classes +cocoa.runtime sequences threads debugger init inspector +kernel.private ; IN: cocoa.application : ( str -- alien ) -> autorelease ; @@ -21,8 +22,6 @@ IN: cocoa.application : with-cocoa ( quot -- ) [ NSApp drop call ] with-autorelease-pool ; -: CFRunLoopDefaultMode "kCFRunLoopDefaultMode" ; - : next-event ( app -- event ) 0 f CFRunLoopDefaultMode 1 -> nextEventMatchingMask:untilDate:inMode:dequeue: ; diff --git a/extra/cocoa/messages/messages.factor b/extra/cocoa/messages/messages.factor index 480e19b005..90dc19a581 100755 --- a/extra/cocoa/messages/messages.factor +++ b/extra/cocoa/messages/messages.factor @@ -154,7 +154,7 @@ H{ { [ dup CHAR: ^ = ] [ 3drop "void*" ] } { [ dup CHAR: { = ] [ drop objc-struct-type ] } { [ dup CHAR: [ = ] [ 3drop "void*" ] } - { [ t ] [ 2nip 1string objc>alien-types get at ] } + [ 2nip 1string objc>alien-types get at ] } cond ; : parse-objc-type ( string -- ctype ) 0 swap (parse-objc-type) ; diff --git a/extra/concurrency/mailboxes/mailboxes-docs.factor b/extra/concurrency/mailboxes/mailboxes-docs.factor index 50694776c5..a9b86e3bcd 100755 --- a/extra/concurrency/mailboxes/mailboxes-docs.factor +++ b/extra/concurrency/mailboxes/mailboxes-docs.factor @@ -57,7 +57,7 @@ HELP: mailbox-get? ARTICLE: "concurrency.mailboxes" "Mailboxes" -"A " { $emphasis "mailbox" } " is a first-in-first-out queue where the operation of removing an element blocks if the queue is empty, instead of throwing an error." +"A " { $emphasis "mailbox" } " is a first-in-first-out queue where the operation of removing an element blocks if the queue is empty, instead of throwing an error. Mailboxes are implemented in the " { $vocab-link "concurrency.mailboxes" } " vocabulary." { $subsection mailbox } { $subsection } "Removing the first element:" @@ -73,3 +73,5 @@ ARTICLE: "concurrency.mailboxes" "Mailboxes" "Testing if a mailbox is empty:" { $subsection mailbox-empty? } { $subsection while-mailbox-empty } ; + +ABOUT: "concurrency.mailboxes" diff --git a/extra/concurrency/mailboxes/mailboxes-tests.factor b/extra/concurrency/mailboxes/mailboxes-tests.factor index 2cb12bcaba..7fe09cdcf5 100755 --- a/extra/concurrency/mailboxes/mailboxes-tests.factor +++ b/extra/concurrency/mailboxes/mailboxes-tests.factor @@ -1,6 +1,7 @@ IN: concurrency.mailboxes.tests -USING: concurrency.mailboxes vectors sequences threads -tools.test math kernel strings ; +USING: concurrency.mailboxes concurrency.count-downs vectors +sequences threads tools.test math kernel strings namespaces +continuations calendar ; [ V{ 1 2 3 } ] [ 0 @@ -38,3 +39,37 @@ tools.test math kernel strings ; "junk2" over mailbox-put mailbox-get ] unit-test + + "m" set + +1 "c" set +1 "d" set + +[ + "c" get await + [ "m" get mailbox-get drop ] + [ drop "d" get count-down ] recover +] "Mailbox close test" spawn drop + +[ ] [ "c" get count-down ] unit-test +[ ] [ "m" get dispose ] unit-test +[ ] [ "d" get 5 seconds await-timeout ] unit-test + +[ ] [ "m" get dispose ] unit-test + + "m" set + +1 "c" set +1 "d" set + +[ + "c" get await + "m" get wait-for-close + "d" get count-down +] "Mailbox close test" spawn drop + +[ ] [ "c" get count-down ] unit-test +[ ] [ "m" get dispose ] unit-test +[ ] [ "d" get 5 seconds await-timeout ] unit-test + +[ ] [ "m" get dispose ] unit-test diff --git a/extra/concurrency/mailboxes/mailboxes.factor b/extra/concurrency/mailboxes/mailboxes.factor index 7b6405679f..36aafbdc84 100755 --- a/extra/concurrency/mailboxes/mailboxes.factor +++ b/extra/concurrency/mailboxes/mailboxes.factor @@ -3,41 +3,50 @@ IN: concurrency.mailboxes USING: dlists threads sequences continuations namespaces random math quotations words kernel arrays assocs -init system concurrency.conditions ; +init system concurrency.conditions accessors ; -TUPLE: mailbox threads data ; +TUPLE: mailbox threads data closed ; + +: check-closed ( mailbox -- ) + closed>> [ "Mailbox closed" throw ] when ; inline + +M: mailbox dispose + t >>closed threads>> notify-all ; : ( -- mailbox ) - mailbox construct-boa ; + f mailbox construct-boa ; : mailbox-empty? ( mailbox -- bool ) - mailbox-data dlist-empty? ; + data>> dlist-empty? ; : mailbox-put ( obj mailbox -- ) - [ mailbox-data push-front ] keep - mailbox-threads notify-all yield ; + [ data>> push-front ] + [ threads>> notify-all ] bi yield ; + +: wait-for-mailbox ( mailbox timeout -- ) + >r threads>> r> "mailbox" wait ; : block-unless-pred ( mailbox timeout pred -- ) - pick mailbox-data over dlist-contains? [ + pick check-closed + pick data>> over dlist-contains? [ 3drop ] [ - >r over mailbox-threads over "mailbox" wait r> - block-unless-pred + >r 2dup wait-for-mailbox r> block-unless-pred ] if ; inline : block-if-empty ( mailbox timeout -- mailbox ) + over check-closed over mailbox-empty? [ - over mailbox-threads over "mailbox" wait - block-if-empty + 2dup wait-for-mailbox block-if-empty ] [ drop ] if ; : mailbox-peek ( mailbox -- obj ) - mailbox-data peek-back ; + data>> peek-back ; : mailbox-get-timeout ( mailbox timeout -- obj ) - block-if-empty mailbox-data pop-back ; + block-if-empty data>> pop-back ; : mailbox-get ( mailbox -- obj ) f mailbox-get-timeout ; @@ -45,7 +54,7 @@ TUPLE: mailbox threads data ; : mailbox-get-all-timeout ( mailbox timeout -- array ) block-if-empty [ dup mailbox-empty? ] - [ dup mailbox-data pop-back ] + [ dup data>> pop-back ] [ ] unfold nip ; : mailbox-get-all ( mailbox -- array ) @@ -60,11 +69,18 @@ TUPLE: mailbox threads data ; : mailbox-get-timeout? ( mailbox timeout pred -- obj ) 3dup block-unless-pred - nip >r mailbox-data r> delete-node-if ; inline + nip >r data>> r> delete-node-if ; inline : mailbox-get? ( mailbox pred -- obj ) f swap mailbox-get-timeout? ; inline +: wait-for-close-timeout ( mailbox timeout -- ) + over closed>> + [ 2drop ] [ 2dup wait-for-mailbox wait-for-close-timeout ] if ; + +: wait-for-close ( mailbox -- ) + f wait-for-close-timeout ; + TUPLE: linked-error thread ; : ( error thread -- linked ) diff --git a/extra/concurrency/messaging/messaging-docs.factor b/extra/concurrency/messaging/messaging-docs.factor index e7aa5d1a7e..1219982f51 100755 --- a/extra/concurrency/messaging/messaging-docs.factor +++ b/extra/concurrency/messaging/messaging-docs.factor @@ -32,7 +32,7 @@ HELP: spawn-linked { $description "Start a thread which runs the given quotation. If that quotation throws an error which is not caught then the error will get propagated to the thread that spawned it. This can be used to set up 'supervisor' threades that restart child threades that crash due to uncaught errors.\n" } { $see-also spawn } ; -ARTICLE: { "concurrency" "messaging" } "Mailboxes" +ARTICLE: { "concurrency" "messaging" } "Sending and receiving messages" "Each thread has an associated mailbox. Other threads can place items on this queue by sending the thread a message. A thread can check its mailbox for messages, blocking if none are pending, and thread them as they are queued." $nl "The messages that are sent from thread to thread are any Factor value. Factor tuples are ideal for this sort of thing as you can send a tuple to a thread and the generic word dispatch mechanism can be used to perform actions depending on what the type of the tuple is." @@ -43,7 +43,8 @@ $nl { $subsection receive } { $subsection receive-timeout } { $subsection receive-if } -{ $subsection receive-if-timeout } ; +{ $subsection receive-if-timeout } +{ $see-also "concurrency.mailboxes" } ; ARTICLE: { "concurrency" "synchronous-sends" } "Synchronous sends" "The " { $link send } " word sends a message asynchronously, and the sending thread continues immediately. It is also possible to send a message to a thread and block until a response is received:" diff --git a/extra/concurrency/messaging/messaging-tests.factor b/extra/concurrency/messaging/messaging-tests.factor index 6de381b166..b69773f3b1 100755 --- a/extra/concurrency/messaging/messaging-tests.factor +++ b/extra/concurrency/messaging/messaging-tests.factor @@ -3,7 +3,8 @@ ! USING: kernel threads vectors arrays sequences namespaces tools.test continuations dlists strings math words -match quotations concurrency.messaging concurrency.mailboxes ; +match quotations concurrency.messaging concurrency.mailboxes +concurrency.count-downs ; IN: concurrency.messaging.tests [ ] [ my-mailbox mailbox-data dlist-delete-all ] unit-test @@ -52,4 +53,15 @@ SYMBOL: exit [ value , self , ] { } make "counter" get send receive exit "counter" get send -] unit-test \ No newline at end of file +] unit-test + +! Not yet + +! 1 "c" set + +! [ +! "c" get count-down +! receive drop +! ] "Bad synchronous send" spawn "t" set + +! [ 3 "t" get send-synchronous ] must-fail \ No newline at end of file diff --git a/extra/core-foundation/core-foundation.factor b/extra/core-foundation/core-foundation.factor index 73b8fce229..77ad30ad8f 100644 --- a/extra/core-foundation/core-foundation.factor +++ b/extra/core-foundation/core-foundation.factor @@ -9,9 +9,9 @@ TYPEDEF: void* CFBundleRef TYPEDEF: void* CFStringRef TYPEDEF: void* CFURLRef TYPEDEF: void* CFUUIDRef -TYPEDEF: void* CFRunLoopRef TYPEDEF: bool Boolean TYPEDEF: int CFIndex +TYPEDEF: int SInt32 TYPEDEF: double CFTimeInterval TYPEDEF: double CFAbsoluteTime @@ -85,5 +85,3 @@ FUNCTION: void CFRelease ( void* cf ) ; ] [ "Cannot load bundled named " prepend throw ] ?if ; - -FUNCTION: CFRunLoopRef CFRunLoopGetMain ( ) ; diff --git a/extra/core-foundation/fsevents/fsevents.factor b/extra/core-foundation/fsevents/fsevents.factor index 55f2462061..24211a59c7 100644 --- a/extra/core-foundation/fsevents/fsevents.factor +++ b/extra/core-foundation/fsevents/fsevents.factor @@ -1,7 +1,8 @@ ! Copyright (C) 2008 Slava Pestov ! See http://factorcode.org/license.txt for BSD license. USING: alien alien.c-types alien.syntax kernel math sequences -namespaces assocs init continuations core-foundation ; +namespaces assocs init accessors continuations combinators +core-foundation core-foundation.run-loop ; IN: core-foundation.fsevents ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! @@ -151,12 +152,10 @@ SYMBOL: event-stream-callbacks [ event-stream-callbacks global - [ [ drop expired? not ] assoc-subset ] change-at + [ [ drop expired? not ] assoc-subset H{ } assoc-like ] change-at 1 \ event-stream-counter set-global ] "core-foundation" add-init-hook -event-stream-callbacks global [ H{ } assoc-like ] change-at - : add-event-source-callback ( quot -- id ) event-stream-counter [ event-stream-callbacks get set-at ] keep ; @@ -184,11 +183,11 @@ event-stream-callbacks global [ H{ } assoc-like ] change-at } "cdecl" [ [ >event-triple ] 3curry map - swap event-stream-callbacks get at call - drop + swap event-stream-callbacks get at + dup [ call drop ] [ 3drop ] if ] alien-callback ; -TUPLE: event-stream info handle ; +TUPLE: event-stream info handle closed ; : ( quot paths latency flags -- event-stream ) >r >r >r @@ -196,9 +195,15 @@ TUPLE: event-stream info handle ; >r master-event-source-callback r> r> r> r> dup enable-event-stream - event-stream construct-boa ; + f event-stream construct-boa ; M: event-stream dispose - dup event-stream-info remove-event-source-callback - event-stream-handle dup disable-event-stream - FSEventStreamRelease ; + dup closed>> [ drop ] [ + t >>closed + { + [ info>> remove-event-source-callback ] + [ handle>> disable-event-stream ] + [ handle>> FSEventStreamInvalidate ] + [ handle>> FSEventStreamRelease ] + } cleave + ] if ; diff --git a/extra/core-foundation/run-loop/run-loop.factor b/extra/core-foundation/run-loop/run-loop.factor new file mode 100644 index 0000000000..7594766635 --- /dev/null +++ b/extra/core-foundation/run-loop/run-loop.factor @@ -0,0 +1,38 @@ +! Copyright (C) 2008 Slava Pestov +! See http://factorcode.org/license.txt for BSD license. +USING: alien.syntax kernel threads init namespaces alien +core-foundation ; +IN: core-foundation.run-loop + +: kCFRunLoopRunFinished 1 ; inline +: kCFRunLoopRunStopped 2 ; inline +: kCFRunLoopRunTimedOut 3 ; inline +: kCFRunLoopRunHandledSource 4 ; inline + +TYPEDEF: void* CFRunLoopRef + +FUNCTION: CFRunLoopRef CFRunLoopGetMain ( ) ; + +FUNCTION: SInt32 CFRunLoopRunInMode ( + CFStringRef mode, + CFTimeInterval seconds, + Boolean returnAfterSourceHandled +) ; + +: CFRunLoopDefaultMode ( -- alien ) + #! Ugly, but we don't have static NSStrings + \ CFRunLoopDefaultMode get-global dup expired? [ + drop + "kCFRunLoopDefaultMode" + dup \ CFRunLoopDefaultMode set-global + ] when ; + +: run-loop-thread ( -- ) + CFRunLoopDefaultMode 0 f CFRunLoopRunInMode + kCFRunLoopRunHandledSource = [ 1000 sleep ] unless + run-loop-thread ; + +: start-run-loop-thread ( -- ) + [ run-loop-thread t ] "CFRunLoop dispatcher" spawn-server drop ; + +[ start-run-loop-thread ] "core-foundation.run-loop" add-init-hook diff --git a/extra/db/sql/sql-tests.factor b/extra/db/sql/sql-tests.factor index c490ace770..488026fcc7 100644 --- a/extra/db/sql/sql-tests.factor +++ b/extra/db/sql/sql-tests.factor @@ -38,5 +38,3 @@ TUPLE: person name age ; { offset 40 } { limit 20 } } ; - - diff --git a/extra/db/sql/sql.factor b/extra/db/sql/sql.factor index 99dde99280..26e8429efd 100755 --- a/extra/db/sql/sql.factor +++ b/extra/db/sql/sql.factor @@ -55,7 +55,7 @@ TUPLE: no-sql-match ; { [ dup number? ] [ number>string sql% ] } { [ dup symbol? ] [ unparse sql% ] } { [ dup word? ] [ unparse sql% ] } - { [ t ] [ T{ no-sql-match } throw ] } + [ T{ no-sql-match } throw ] } cond ; : parse-sql ( obj -- sql in-spec out-spec in out ) diff --git a/extra/db/sqlite/lib/lib.factor b/extra/db/sqlite/lib/lib.factor index f81d7de4b8..e66accd7e9 100755 --- a/extra/db/sqlite/lib/lib.factor +++ b/extra/db/sqlite/lib/lib.factor @@ -20,7 +20,7 @@ IN: db.sqlite.lib { { [ dup SQLITE_OK = ] [ drop ] } { [ dup SQLITE_ERROR = ] [ sqlite-statement-error ] } - { [ t ] [ sqlite-error ] } + [ sqlite-error ] } cond ; : sqlite-open ( filename -- db ) diff --git a/extra/documents/documents.factor b/extra/documents/documents.factor index 14f0dc41ac..1c0802b721 100755 --- a/extra/documents/documents.factor +++ b/extra/documents/documents.factor @@ -151,14 +151,14 @@ TUPLE: char-elt ; -rot { { [ over { 0 0 } = ] [ drop ] } { [ over second zero? ] [ >r first 1- r> line-end ] } - { [ t ] [ pick call ] } + [ pick call ] } cond nip ; inline : (next-char) ( loc document quot -- loc ) -rot { { [ 2dup doc-end = ] [ drop ] } { [ 2dup line-end? ] [ drop first 1+ 0 2array ] } - { [ t ] [ pick call ] } + [ pick call ] } cond nip ; inline M: char-elt prev-elt diff --git a/extra/fry/fry.factor b/extra/fry/fry.factor index d983bd2715..6c20aac7f2 100755 --- a/extra/fry/fry.factor +++ b/extra/fry/fry.factor @@ -22,11 +22,11 @@ DEFER: (fry) drop 1quotation ] [ unclip { - { , [ [ curry ] ((fry)) ] } - { @ [ [ compose ] ((fry)) ] } + { \ , [ [ curry ] ((fry)) ] } + { \ @ [ [ compose ] ((fry)) ] } ! to avoid confusion, remove if fry goes core - { namespaces:, [ [ curry ] ((fry)) ] } + { \ namespaces:, [ [ curry ] ((fry)) ] } [ swap >r suffix r> (fry) ] } case diff --git a/extra/hardware-info/hardware-info.factor b/extra/hardware-info/hardware-info.factor index 53aab483a1..cc345c7537 100755 --- a/extra/hardware-info/hardware-info.factor +++ b/extra/hardware-info/hardware-info.factor @@ -14,7 +14,7 @@ IN: hardware-info { [ os windows? ] [ "hardware-info.windows" ] } { [ os linux? ] [ "hardware-info.linux" ] } { [ os macosx? ] [ "hardware-info.macosx" ] } - { [ t ] [ f ] } + [ f ] } cond [ require ] when* >> : hardware-report. ( -- ) diff --git a/extra/help/cookbook/cookbook.factor b/extra/help/cookbook/cookbook.factor index f1d4ac4ca7..9b21bf7fff 100755 --- a/extra/help/cookbook/cookbook.factor +++ b/extra/help/cookbook/cookbook.factor @@ -199,7 +199,7 @@ ARTICLE: "cookbook-io" "Input and output cookbook" } "Convert a file of 4-byte cells from little to big endian or vice versa, by directly mapping it into memory and operating on it with sequence words:" { $code - "\"mydata.dat\" dup file-info file-info-length [" + "\"mydata.dat\" dup file-info size>> [" " 4 [ reverse-here ] change-each" "] with-mapped-file" } diff --git a/extra/help/help.factor b/extra/help/help.factor index 4e8424f7a3..aa2704a799 100755 --- a/extra/help/help.factor +++ b/extra/help/help.factor @@ -139,7 +139,7 @@ M: word set-article-parent swap "help-parent" set-word-prop ; { { [ dup empty? ] [ (:help-none) ] } { [ dup length 1 = ] [ first help ] } - { [ t ] [ (:help-multi) ] } + [ (:help-multi) ] } cond (:help-debugger) ; : remove-article ( name -- ) diff --git a/extra/html/parser/printer/printer.factor b/extra/html/parser/printer/printer.factor index 5ed9ab84c1..3078cf23a5 100644 --- a/extra/html/parser/printer/printer.factor +++ b/extra/html/parser/printer/printer.factor @@ -92,7 +92,7 @@ M: printer print-tag ( tag -- ) [ print-closing-named-tag ] } { [ dup tag-name string? ] [ print-opening-named-tag ] } - { [ t ] [ throw ] } + [ throw ] } cond ; SYMBOL: tablestack diff --git a/extra/http/http.factor b/extra/http/http.factor index 6ff4829b48..a6afe80443 100755 --- a/extra/http/http.factor +++ b/extra/http/http.factor @@ -145,10 +145,10 @@ TUPLE: cookie name value path domain expires http-only ; : (unparse-cookie) ( key value -- ) { - { [ dup f eq? ] [ 2drop ] } - { [ dup t eq? ] [ drop , ] } - { [ t ] [ "=" swap 3append , ] } - } cond ; + { f [ drop ] } + { t [ , ] } + [ "=" swap 3append , ] + } case ; : unparse-cookie ( cookie -- strings ) [ @@ -399,7 +399,7 @@ body ; { [ dup not ] [ drop ] } { [ dup string? ] [ write ] } { [ dup callable? ] [ call ] } - { [ t ] [ stdio get stream-copy ] } + [ stdio get stream-copy ] } cond ; M: response write-response ( respose -- ) diff --git a/extra/http/server/server.factor b/extra/http/server/server.factor index 2cc0f80f03..e1561bce89 100755 --- a/extra/http/server/server.factor +++ b/extra/http/server/server.factor @@ -89,7 +89,7 @@ SYMBOL: form-hook { { [ over "http://" head? ] [ link>string ] } { [ over "/" head? ] [ absolute-redirect ] } - { [ t ] [ relative-redirect ] } + [ relative-redirect ] } cond ; : ( to query code message -- response ) diff --git a/extra/http/server/static/static.factor b/extra/http/server/static/static.factor index 905c7320ca..8632e0f139 100755 --- a/extra/http/server/static/static.factor +++ b/extra/http/server/static/static.factor @@ -10,7 +10,7 @@ IN: http.server.static TUPLE: file-responder root hook special ; : file-http-date ( filename -- string ) - file-info file-info-modified timestamp>http-string ; + file-info modified>> timestamp>http-string ; : last-modified-matches? ( filename -- ? ) file-http-date dup [ @@ -27,7 +27,7 @@ TUPLE: file-responder root hook special ; [ swap - [ file-info file-info-size "content-length" set-header ] + [ file-info size>> "content-length" set-header ] [ file-http-date "last-modified" set-header ] [ '[ , binary stdio get stream-copy ] >>body ] tri diff --git a/extra/http/server/templating/fhtml/fhtml.factor b/extra/http/server/templating/fhtml/fhtml.factor index f3d9d54a25..6cd5c78b72 100755 --- a/extra/http/server/templating/fhtml/fhtml.factor +++ b/extra/http/server/templating/fhtml/fhtml.factor @@ -26,7 +26,7 @@ M: template-lexer skip-word { { [ 2dup nth CHAR: " = ] [ drop 1+ ] } { [ 2dup swap tail-slice "%>" head? ] [ drop 2 + ] } - { [ t ] [ f skip ] } + [ f skip ] } cond ] change-lexer-column ; diff --git a/extra/inverse/inverse-tests.factor b/extra/inverse/inverse-tests.factor index 31e7c5f78a..101637e4e8 100644 --- a/extra/inverse/inverse-tests.factor +++ b/extra/inverse/inverse-tests.factor @@ -1,5 +1,5 @@ USING: inverse tools.test arrays math kernel sequences -math.functions math.constants ; +math.functions math.constants continuations ; IN: inverse-tests [ 2 ] [ { 3 2 } [ 3 swap 2array ] undo ] unit-test @@ -51,7 +51,7 @@ C: nil { { [ ] [ list-sum + ] } { [ ] [ 0 ] } - { [ ] [ "Malformed list" throw ] } + [ "Malformed list" throw ] } switch ; [ 10 ] [ 1 2 3 4 list-sum ] unit-test @@ -59,6 +59,7 @@ C: nil [ 1 2 ] [ 1 2 [ ] undo ] unit-test [ t ] [ 1 2 [ ] matches? ] unit-test [ f ] [ 1 2 [ ] matches? ] unit-test +[ "Malformed list" ] [ [ f list-sum ] [ ] recover ] unit-test : empty-cons ( -- cons ) cons construct-empty ; : cons* ( cdr car -- cons ) { set-cons-cdr set-cons-car } cons construct ; @@ -68,3 +69,4 @@ C: nil [ t ] [ pi [ pi ] matches? ] unit-test [ 0.0 ] [ 0.0 pi + [ pi + ] undo ] unit-test +[ ] [ 3 [ _ ] undo ] unit-test diff --git a/extra/inverse/inverse.factor b/extra/inverse/inverse.factor index 1b7badd94a..9c94c86ce9 100755 --- a/extra/inverse/inverse.factor +++ b/extra/inverse/inverse.factor @@ -60,11 +60,13 @@ PREDICATE: math-inverse < word "math-inverse" word-prop ; PREDICATE: pop-inverse < word "pop-length" word-prop ; UNION: explicit-inverse normal-inverse math-inverse pop-inverse ; -: enough? ( stack quot -- ? ) - [ >r length r> 1quotation infer effect-in >= ] [ 3drop f ] - recover ; +: enough? ( stack word -- ? ) + dup deferred? [ 2drop f ] [ + [ >r length r> 1quotation infer effect-in >= ] + [ 3drop f ] recover + ] if ; -: fold-word ( stack quot -- stack ) +: fold-word ( stack word -- stack ) 2dup enough? [ 1quotation with-datastack ] [ >r % r> , { } ] if ; @@ -72,10 +74,10 @@ UNION: explicit-inverse normal-inverse math-inverse pop-inverse ; [ { } swap [ fold-word ] each % ] [ ] make ; : flattenable? ( object -- ? ) - [ [ word? ] [ primitive? not ] and? ] [ + { [ word? ] [ primitive? not ] [ { "inverse" "math-inverse" "pop-inverse" } [ word-prop ] with contains? not - ] and? ; + ] } <-&& ; : (flatten) ( quot -- ) [ dup flattenable? [ word-def (flatten) ] [ , ] if ] each ; @@ -159,7 +161,7 @@ MACRO: undo ( quot -- ) [undo] ; 2curry ] define-pop-inverse -: _ f ; +DEFER: _ \ _ [ drop ] define-inverse : both ( object object -- object ) @@ -256,6 +258,7 @@ M: no-match summary drop "Fall through in switch" ; [ no-match ] [ swap \ recover-fail 3array >quotation ] reduce ; : [switch] ( quot-alist -- quot ) + [ dup quotation? [ [ ] swap 2array ] when ] map reverse [ >r [undo] r> compose ] { } assoc>map recover-chain ; diff --git a/extra/io/encodings/8-bit/8-bit-docs.factor b/extra/io/encodings/8-bit/8-bit-docs.factor index e8dadc13f7..33d629b105 100644 --- a/extra/io/encodings/8-bit/8-bit-docs.factor +++ b/extra/io/encodings/8-bit/8-bit-docs.factor @@ -1,6 +1,7 @@ ! Copyright (C) 2008 Daniel Ehrenberg ! See http://factorcode.org/license.txt for BSD license. -USING: help.syntax help.markup io.encodings.8-bit.private ; +USING: help.syntax help.markup io.encodings.8-bit.private +strings ; IN: io.encodings.8-bit ARTICLE: "io.encodings.8-bit" "8-bit encodings" @@ -34,8 +35,8 @@ HELP: 8-bit { $class-description "Describes an 8-bit encoding, including its name (a symbol) and a table used for encoding and decoding." } ; HELP: define-8-bit-encoding -{ $values { "name" "a string" } { "path" "a path" } } -{ $description "Creates a new encoding with the given name, using the resource file at the path to tell how to encode and decode octets. The resource file should be in a similar format to those at " { $url "ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/" } } ; +{ $values { "name" string } { "stream" "an input stream" } } +{ $description "Creates a new encoding. The stream should be in a similar format to those at " { $url "ftp://ftp.unicode.org/Public/MAPPINGS/ISO8859/" } } ; HELP: latin1 { $description "This is the ISO-8859-1 encoding, also called Latin-1: Western European. It is an 8-bit superset of ASCII which is the default for a mimetype starting with 'text' and provides the characters necessary for most western European languages." } diff --git a/extra/io/encodings/8-bit/8-bit.factor b/extra/io/encodings/8-bit/8-bit.factor index 259173fec4..04e8ee8569 100755 --- a/extra/io/encodings/8-bit/8-bit.factor +++ b/extra/io/encodings/8-bit/8-bit.factor @@ -29,9 +29,10 @@ IN: io.encodings.8-bit { "mac-roman" "ROMAN" } } ; -: full-path ( file-name -- path ) +: encoding-file ( file-name -- stream ) "extra/io/encodings/8-bit/" ".TXT" - swapd 3append resource-path ; + swapd 3append resource-path + ascii ; : tail-if ( seq n -- newseq ) 2dup swap length <= [ tail ] [ drop ] if ; @@ -48,8 +49,8 @@ IN: io.encodings.8-bit : ch>byte ( assoc -- newassoc ) [ swap ] assoc-map >hashtable ; -: parse-file ( file-name -- byte>ch ch>byte ) - ascii file-lines process-contents +: parse-file ( path -- byte>ch ch>byte ) + lines process-contents [ byte>ch ] [ ch>byte ] bi ; TUPLE: 8-bit name decode encode ; @@ -71,13 +72,13 @@ M: 8-bit decode-char : make-8-bit ( word byte>ch ch>byte -- ) [ 8-bit construct-boa ] 2curry dupd curry define ; -: define-8-bit-encoding ( name path -- ) +: define-8-bit-encoding ( name stream -- ) >r in get create r> parse-file make-8-bit ; PRIVATE> [ "io.encodings.8-bit" in [ - mappings [ full-path define-8-bit-encoding ] assoc-each + mappings [ encoding-file define-8-bit-encoding ] assoc-each ] with-variable ] with-compilation-unit diff --git a/extra/io/launcher/launcher-docs.factor b/extra/io/launcher/launcher-docs.factor index 0f6ca3a2c9..4446b82f20 100755 --- a/extra/io/launcher/launcher-docs.factor +++ b/extra/io/launcher/launcher-docs.factor @@ -129,9 +129,6 @@ HELP: { $values { "process" process } } { $description "Creates a new, empty process. It must be filled in before being passed to " { $link run-process } "." } ; -HELP: process-stream -{ $class-description "A bidirectional stream for interacting with a running process. Instances are created by calling " { $link } ". The " { $link process-stream-process } " slot holds a " { $link process } " instance." } ; - HELP: { $values { "desc" "a launch descriptor" } @@ -144,7 +141,7 @@ HELP: with-process-stream { "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 " { $link process-stream } ". After the quotation returns, waits for the process to end and outputs the 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 } } diff --git a/extra/io/launcher/launcher.factor b/extra/io/launcher/launcher.factor index fa4bdcaaea..00352adc7b 100755 --- a/extra/io/launcher/launcher.factor +++ b/extra/io/launcher/launcher.factor @@ -150,18 +150,18 @@ M: process timed-out kill-process ; HOOK: (process-stream) io-backend ( process -- handle in out ) -TUPLE: process-stream process ; +: ( desc encoding -- stream process ) + >r >process dup dup (process-stream) + r> -roll + process-started ; : ( desc encoding -- stream ) - >r >process dup dup (process-stream) - >r >r process-started process-stream construct-boa - r> r> r> - over set-delegate ; + drop ; inline : with-process-stream ( desc quot -- status ) - swap + swap >r [ swap with-stream ] keep - process>> wait-for-process ; inline + r> wait-for-process ; inline : notify-exit ( process status -- ) >>status diff --git a/extra/io/mmap/mmap-tests.factor b/extra/io/mmap/mmap-tests.factor index b17d7aeab9..a00f7cd92b 100755 --- a/extra/io/mmap/mmap-tests.factor +++ b/extra/io/mmap/mmap-tests.factor @@ -1,10 +1,10 @@ USING: io io.mmap io.files kernel tools.test continuations -sequences io.encodings.ascii ; +sequences io.encodings.ascii accessors ; IN: io.mmap.tests [ "mmap-test-file.txt" resource-path delete-file ] ignore-errors [ ] [ "12345" "mmap-test-file.txt" resource-path ascii set-file-contents ] unit-test -[ ] [ "mmap-test-file.txt" resource-path dup file-info file-info-size [ CHAR: 2 0 pick set-nth drop ] with-mapped-file ] unit-test -[ 5 ] [ "mmap-test-file.txt" resource-path dup file-info file-info-size [ length ] with-mapped-file ] unit-test +[ ] [ "mmap-test-file.txt" resource-path dup file-info size>> [ CHAR: 2 0 pick set-nth drop ] with-mapped-file ] unit-test +[ 5 ] [ "mmap-test-file.txt" resource-path dup file-info size>> [ length ] with-mapped-file ] unit-test [ "22345" ] [ "mmap-test-file.txt" resource-path ascii file-contents ] unit-test [ "mmap-test-file.txt" resource-path delete-file ] ignore-errors diff --git a/extra/io/monitors/monitors-docs.factor b/extra/io/monitors/monitors-docs.factor index 4f24879e19..cd6a06a8e9 100755 --- a/extra/io/monitors/monitors-docs.factor +++ b/extra/io/monitors/monitors-docs.factor @@ -1,58 +1,108 @@ IN: io.monitors -USING: help.markup help.syntax continuations ; +USING: help.markup help.syntax continuations +concurrency.mailboxes quotations ; + +HELP: with-monitors +{ $values { "quot" quotation } } +{ $description "Calls a quotation in a new dynamic scope where file system monitor operations can be performed." } +{ $errors "Throws an error if the platform does not support file system change monitors." } ; HELP: { $values { "path" "a pathname string" } { "recursive?" "a boolean" } { "monitor" "a new monitor" } } -{ $description "Opens a file system change monitor which listens for changes on " { $snippet "path" } ". The boolean indicates whether changes in subdirectories should be reported." -$nl -"Not all operating systems support recursive monitors; if recursive monitoring is not available, an error is thrown and the caller must implement alternative logic for monitoring subdirectories." } ; +{ $contract "Opens a file system change monitor which listens for changes on " { $snippet "path" } ". The boolean indicates whether changes in subdirectories should be reported." } +{ $errors "Throws an error if the pathname does not exist, if a monitor could not be created or if the platform does not support monitors." } ; + +HELP: (monitor) +{ $values { "path" "a pathname string" } { "recursive?" "a boolean" } { "mailbox" mailbox } { "monitor" "a new monitor" } } +{ $contract "Opens a file system change monitor which listens for changes on " { $snippet "path" } " and posts notifications to " { $snippet "mailbox" } " as triples with shape " { $snippet "{ path changed monitor } " } ". The boolean indicates whether changes in subdirectories should be reported." } +{ $errors "Throws an error if the pathname does not exist, if a monitor could not be created or if the platform does not support monitors." } ; HELP: next-change { $values { "monitor" "a monitor" } { "path" "a pathname string" } { "changed" "a change descriptor" } } -{ $description "Waits for file system changes and outputs the pathname of the first changed file. The change descriptor is a sequence of symbols documented in " { $link "io.monitors.descriptors" } "." } ; +{ $contract "Waits for file system changes and outputs the pathname of the first changed file. The change descriptor is a sequence of symbols documented in " { $link "io.monitors.descriptors" } "." } +{ $errors "Throws an error if the monitor is closed from another thread." } ; HELP: with-monitor { $values { "path" "a pathname string" } { "recursive?" "a boolean" } { "quot" "a quotation with stack effect " { $snippet "( monitor -- )" } } } -{ $description "Opens a file system change monitor and passes it to the quotation. Closes the monitor after the quotation returns or throws an error." } ; +{ $description "Opens a file system change monitor and passes it to the quotation. Closes the monitor after the quotation returns or throws an error." } +{ $errors "Throws an error if the pathname does not exist, if a monitor could not be created or if the platform does not support monitors." } ; HELP: +add-file+ -{ $description "Indicates that the file has been added to the directory." } ; +{ $description "Indicates that a file has been added to its parent directory." } ; HELP: +remove-file+ -{ $description "Indicates that the file has been removed from the directory." } ; +{ $description "Indicates that a file has been removed from its parent directory." } ; HELP: +modify-file+ -{ $description "Indicates that the file contents have changed." } ; +{ $description "Indicates that a file's contents have changed." } ; + +HELP: +rename-file-old+ +{ $description "Indicates that a file has been renamed, and this is the old name." } ; + +HELP: +rename-file-new+ +{ $description "Indicates that a file has been renamed, and this is the new name." } ; HELP: +rename-file+ -{ $description "Indicates that file has been renamed." } ; +{ $description "Indicates that a file has been renamed." } ; ARTICLE: "io.monitors.descriptors" "File system change descriptors" "Change descriptors output by " { $link next-change } ":" { $subsection +add-file+ } { $subsection +remove-file+ } { $subsection +modify-file+ } -{ $subsection +rename-file+ } -{ $subsection +add-file+ } ; +{ $subsection +rename-file-old+ } +{ $subsection +rename-file-new+ } +{ $subsection +rename-file+ } ; + +ARTICLE: "io.monitors.platforms" "Monitors on different platforms" +"Whether the " { $snippet "path" } " output value of " { $link next-change } " contains an absolute path or a path relative to the path given to " { $link } " is platform-specific. User code should not assume either case." +{ $heading "Mac OS X" } +"Factor uses " { $snippet "FSEventStream" } "s to implement monitors on Mac OS X. This requires Mac OS X 10.5 or later." +$nl +{ $snippet "FSEventStream" } "s always monitor directory hierarchies recursively, and the " { $snippet "recursive?" } " parameter to " { $link } " has no effect." +$nl +"The " { $snippet "changed" } " output value of the " { $link next-change } " word always outputs " { $link +modify-file+ } " and the " { $snippet "path" } " output value is always the directory containing the file that changed. Unlike other platforms, fine-grained information is not available." +{ $heading "Windows" } +"Factor uses " { $snippet "ReadDirectoryChanges" } " to implement monitors on Windows." +$nl +"Both recursive and non-recursive monitors are directly supported by the operating system." +{ $heading "Linux" } +"Factor uses " { $snippet "inotify" } " to implement monitors on Linux. This requires Linux kernel version 2.6.16 or later." +$nl +"Factor simulates recursive monitors by creating a hierarchy of monitors for every subdirectory, since " { $snippet "inotify" } " can only monitor a single directory. This is transparent to user code." +$nl +"Inside a single " { $link with-monitors } " scope, only one monitor may be created for any given directory." +{ $heading "BSD" } +"Factor uses " { $snippet "kqueue" } " to implement monitors on BSD." +$nl +"The " { $snippet "kqueue" } " system is limited to monitoring individual files and directories. Monitoring a directory only notifies of files being added and removed to the directory itself, not of changes to file contents." +{ $heading "Windows CE" } +"Windows CE does not support monitors." ; ARTICLE: "io.monitors" "File system change monitors" "File system change monitors listen for changes to file names, attributes and contents under a specified directory. They can optionally be recursive, in which case subdirectories are also monitored." $nl +"Monitoring operations must be wrapped in a combinator:" +{ $subsection with-monitors } "Creating a file system change monitor and listening for changes:" { $subsection } { $subsection next-change } +"An alternative programming style is where instead of having a thread listen for changes on a monitor, change notifications are posted to a mailbox:" +{ $subsection (monitor) } { $subsection "io.monitors.descriptors" } -"Monitors are closed by calling " { $link dispose } " or " { $link with-disposal } "." -$nl -"A utility combinator which opens a monitor and cleans it up after:" +{ $subsection "io.monitors.platforms" } +"Monitors are closed by calling " { $link dispose } " or " { $link with-disposal } ". An easy way to pair construction with disposal is to use a combinator:" { $subsection with-monitor } -"An example which watches the Factor directory for changes:" +"Monitors support the " { $link "io.timeouts" } "." +$nl +"An example which watches a directory for changes:" { $code "USE: io.monitors" ": watch-loop ( monitor -- )" " dup next-change . . nl nl flush watch-loop ;" "" - "\"\" resource-path f [ watch-loop ] with-monitor" + ": watch-directory ( path -- )" + " [ t [ watch-loop ] with-monitor ] with-monitors" } ; ABOUT: "io.monitors" diff --git a/extra/io/monitors/monitors-tests.factor b/extra/io/monitors/monitors-tests.factor index 7170e824c8..ab919dd008 100644 --- a/extra/io/monitors/monitors-tests.factor +++ b/extra/io/monitors/monitors-tests.factor @@ -3,36 +3,89 @@ USING: io.monitors tools.test io.files system sequences continuations namespaces concurrency.count-downs kernel io threads calendar prettyprint ; -os { winnt macosx linux } member? [ - [ "monitor-test" temp-file delete-tree ] ignore-errors +os { winnt linux macosx } member? [ + [ + [ "monitor-test" temp-file delete-tree ] ignore-errors - [ ] [ "monitor-test/xyz" temp-file make-directories ] unit-test + [ ] [ "monitor-test" temp-file make-directory ] unit-test - [ ] [ "monitor-test" temp-file t "m" set ] unit-test + [ ] [ "monitor-test" temp-file t "m" set ] unit-test - [ ] [ 1 "b" set ] unit-test + [ ] [ "monitor-test/a1" temp-file make-directory ] unit-test - [ ] [ 1 "c" set ] unit-test + [ ] [ "monitor-test/a2" temp-file make-directory ] unit-test - [ ] [ - [ - "b" get count-down - [ - "m" get next-change drop - dup print flush right-trim-separators - "xyz" tail? not - ] [ ] [ ] while - "c" get count-down - ] "Monitor test thread" spawn drop - ] unit-test + [ ] [ "monitor-test/a1" temp-file "monitor-test/a2" temp-file move-file-into ] unit-test - [ ] [ "b" get await ] unit-test + [ t ] [ "monitor-test/a2/a1" temp-file exists? ] unit-test - [ ] [ "monitor-test/xyz/test.txt" temp-file touch-file ] unit-test + [ ] [ "monitor-test/a2/a1/a3.txt" temp-file touch-file ] unit-test - [ ] [ "c" get 30 seconds await-timeout ] unit-test + [ t ] [ "monitor-test/a2/a1/a3.txt" temp-file exists? ] unit-test - [ ] [ "m" get dispose ] unit-test + [ ] [ "monitor-test/a2/a1/a4.txt" temp-file touch-file ] unit-test + [ ] [ "monitor-test/a2/a1/a5.txt" temp-file touch-file ] unit-test + [ ] [ "monitor-test/a2/a1/a4.txt" temp-file delete-file ] unit-test + [ ] [ "monitor-test/a2/a1/a5.txt" temp-file "monitor-test/a2/a1/a4.txt" temp-file move-file ] unit-test - [ "m" get dispose ] must-fail + [ t ] [ "monitor-test/a2/a1/a4.txt" temp-file exists? ] unit-test + + [ ] [ "m" get dispose ] unit-test + ] with-monitors + + + [ + [ "monitor-test" temp-file delete-tree ] ignore-errors + + [ ] [ "monitor-test/xyz" temp-file make-directories ] unit-test + + [ ] [ "monitor-test" temp-file t "m" set ] unit-test + + [ ] [ 1 "b" set ] unit-test + + [ ] [ 1 "c1" set ] unit-test + + [ ] [ 1 "c2" set ] unit-test + + [ ] [ + [ + "b" get count-down + + [ + "m" get next-change drop + dup print flush + dup parent-directory + [ right-trim-separators "xyz" tail? ] either? not + ] [ ] [ ] while + + "c1" get count-down + + [ + "m" get next-change drop + dup print flush + dup parent-directory + [ right-trim-separators "yxy" tail? ] either? not + ] [ ] [ ] while + + "c2" get count-down + ] "Monitor test thread" spawn drop + ] unit-test + + [ ] [ "b" get await ] unit-test + + [ ] [ "monitor-test/xyz/test.txt" temp-file touch-file ] unit-test + + [ ] [ "c1" get 15 seconds await-timeout ] unit-test + + [ ] [ "monitor-test/subdir/blah/yxy" temp-file make-directories ] unit-test + + [ ] [ "monitor-test/subdir/blah/yxy/test.txt" temp-file touch-file ] unit-test + + [ ] [ "c2" get 15 seconds await-timeout ] unit-test + + ! Dispose twice + [ ] [ "m" get dispose ] unit-test + + [ ] [ "m" get dispose ] unit-test + ] with-monitors ] when diff --git a/extra/io/monitors/monitors.factor b/extra/io/monitors/monitors.factor index 1678c2de41..5c88968ee7 100755 --- a/extra/io/monitors/monitors.factor +++ b/extra/io/monitors/monitors.factor @@ -1,83 +1,55 @@ -! Copyright (C) 2008 Slava Pestov. -! See http://factorcode.org/license.txt for BSD license. -USING: io.backend kernel continuations namespaces sequences -assocs hashtables sorting arrays threads boxes io.timeouts ; -IN: io.monitors - -array ; - -M: monitor dispose - dup check-monitor - t over set-monitor-closed? - delegate dispose ; - -! Simple monitor; used on Linux and Mac OS X. On Windows, -! monitors are full-fledged ports. -TUPLE: simple-monitor handle callback timeout ; - -M: simple-monitor timeout simple-monitor-timeout ; - -M: simple-monitor set-timeout set-simple-monitor-timeout ; - -: ( handle -- simple-monitor ) - f (monitor) { - set-simple-monitor-handle - set-delegate - set-simple-monitor-callback - } simple-monitor construct ; - -: construct-simple-monitor ( handle class -- simple-monitor ) - >r r> construct-delegate ; inline - -: notify-callback ( simple-monitor -- ) - simple-monitor-callback [ resume ] if-box? ; - -M: simple-monitor timed-out - notify-callback ; - -M: simple-monitor fill-queue ( monitor -- ) - [ - [ swap simple-monitor-callback >box ] - "monitor" suspend drop - ] with-timeout - check-monitor ; - -M: simple-monitor dispose ( monitor -- ) - dup delegate dispose notify-callback ; - -PRIVATE> - -HOOK: io-backend ( path recursive? -- monitor ) - -: next-change ( monitor -- path changed ) - dup check-monitor - dup monitor-queue dup assoc-empty? [ - drop dup fill-queue next-change - ] [ nip dequeue-change ] if ; - -SYMBOL: +add-file+ -SYMBOL: +remove-file+ -SYMBOL: +modify-file+ -SYMBOL: +rename-file+ - -: with-monitor ( path recursive? quot -- ) - >r r> with-disposal ; inline +! Copyright (C) 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: io.backend kernel continuations namespaces sequences +assocs hashtables sorting arrays threads boxes io.timeouts +accessors concurrency.mailboxes ; +IN: io.monitors + +HOOK: init-monitors io-backend ( -- ) + +M: object init-monitors ; + +HOOK: dispose-monitors io-backend ( -- ) + +M: object dispose-monitors ; + +: with-monitors ( quot -- ) + [ + init-monitors + [ dispose-monitors ] [ ] cleanup + ] with-scope ; inline + +TUPLE: monitor < identity-tuple path queue timeout ; + +M: monitor hashcode* path>> hashcode* ; + +M: monitor timeout timeout>> ; + +M: monitor set-timeout (>>timeout) ; + +: construct-monitor ( path mailbox class -- monitor ) + construct-empty + swap >>queue + swap >>path ; inline + +: queue-change ( path changes monitor -- ) + 3dup and and + [ [ 3array ] keep queue>> mailbox-put ] [ 3drop ] if ; + +HOOK: (monitor) io-backend ( path recursive? mailbox -- monitor ) + +: ( path recursive? -- monitor ) + (monitor) ; + +: next-change ( monitor -- path changed ) + [ queue>> ] [ timeout ] bi mailbox-get-timeout first2 ; + +SYMBOL: +add-file+ +SYMBOL: +remove-file+ +SYMBOL: +modify-file+ +SYMBOL: +rename-file-old+ +SYMBOL: +rename-file-new+ +SYMBOL: +rename-file+ + +: with-monitor ( path recursive? quot -- ) + >r r> with-disposal ; inline diff --git a/extra/io/monitors/recursive/recursive-tests.factor b/extra/io/monitors/recursive/recursive-tests.factor new file mode 100644 index 0000000000..3182747194 --- /dev/null +++ b/extra/io/monitors/recursive/recursive-tests.factor @@ -0,0 +1,59 @@ +USING: accessors math kernel namespaces continuations +io.files io.monitors io.monitors.recursive io.backend +concurrency.mailboxes +tools.test ; +IN: io.monitors.recursive.tests + +\ pump-thread must-infer + +SINGLETON: mock-io-backend + +TUPLE: counter i ; + +SYMBOL: dummy-monitor-created +SYMBOL: dummy-monitor-disposed + +TUPLE: dummy-monitor < monitor ; + +M: dummy-monitor dispose + drop dummy-monitor-disposed get [ 1+ ] change-i drop ; + +M: mock-io-backend (monitor) + nip + over exists? [ + dummy-monitor construct-monitor + dummy-monitor-created get [ 1+ ] change-i drop + ] [ + "Does not exist" throw + ] if ; + +M: mock-io-backend link-info + global [ link-info ] bind ; + +[ ] [ 0 counter construct-boa dummy-monitor-created set ] unit-test +[ ] [ 0 counter construct-boa dummy-monitor-disposed set ] unit-test + +[ ] [ + mock-io-backend io-backend [ + "" resource-path dispose + ] with-variable +] unit-test + +[ t ] [ dummy-monitor-created get i>> 0 > ] unit-test + +[ t ] [ dummy-monitor-created get i>> dummy-monitor-disposed get i>> = ] unit-test + +[ "doesnotexist" temp-file delete-tree ] ignore-errors + +[ + mock-io-backend io-backend [ + "doesnotexist" temp-file dispose + ] with-variable +] must-fail + +[ ] [ + mock-io-backend io-backend [ + "" resource-path + [ dispose ] [ dispose ] bi + ] with-variable +] unit-test diff --git a/extra/io/monitors/recursive/recursive.factor b/extra/io/monitors/recursive/recursive.factor new file mode 100644 index 0000000000..8c2560f681 --- /dev/null +++ b/extra/io/monitors/recursive/recursive.factor @@ -0,0 +1,105 @@ +! Copyright (C) 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: accessors sequences assocs arrays continuations combinators kernel +threads concurrency.messaging concurrency.mailboxes +concurrency.promises +io.files io.monitors ; +IN: io.monitors.recursive + +! Simulate recursive monitors on platforms that don't have them + +TUPLE: recursive-monitor < monitor children thread ready ; + +DEFER: add-child-monitor + +: qualify-path ( path -- path' ) + monitor tget path>> prepend-path ; + +: add-child-monitors ( path -- ) + #! We yield since this directory scan might take a while. + [ + directory* [ first add-child-monitor yield ] each + ] curry ignore-errors ; + +: add-child-monitor ( path -- ) + qualify-path dup link-info type>> +directory+ eq? [ + [ add-child-monitors ] + [ + [ f my-mailbox (monitor) ] keep + monitor tget children>> set-at + ] bi + ] [ drop ] if ; + +USE: io +USE: prettyprint + +: remove-child-monitor ( monitor -- ) + monitor tget children>> delete-at* + [ dispose ] [ drop ] if ; + +M: recursive-monitor dispose + dup queue>> closed>> [ + drop + ] [ + [ "stop" swap thread>> send-synchronous drop ] + [ queue>> dispose ] bi + ] if ; + +: stop-pump ( -- ) + monitor tget children>> [ nip dispose ] assoc-each ; + +: pump-step ( msg -- ) + first3 path>> swap >r prepend-path r> monitor tget 3array + monitor tget queue>> + mailbox-put ; + +: child-added ( path monitor -- ) + path>> prepend-path add-child-monitor ; + +: child-removed ( path monitor -- ) + path>> prepend-path remove-child-monitor ; + +: update-hierarchy ( msg -- ) + first3 swap [ + { + { +add-file+ [ child-added ] } + { +remove-file+ [ child-removed ] } + { +rename-file-old+ [ child-removed ] } + { +rename-file-new+ [ child-added ] } + [ 3drop ] + } case + ] with with each ; + +: pump-loop ( -- ) + receive dup synchronous? [ + >r stop-pump t r> reply-synchronous + ] [ + [ [ update-hierarchy ] curry ignore-errors ] [ pump-step ] bi + pump-loop + ] if ; + +: monitor-ready ( error/t -- ) + monitor tget ready>> fulfill ; + +: pump-thread ( monitor -- ) + monitor tset + [ "" add-child-monitor t monitor-ready ] + [ [ self monitor-ready ] keep rethrow ] + recover + pump-loop ; + +: start-pump-thread ( monitor -- ) + dup [ pump-thread ] curry + "Recursive monitor pump" spawn + >>thread drop ; + +: wait-for-ready ( monitor -- ) + ready>> ?promise ?linked drop ; + +: ( path mailbox -- monitor ) + >r (normalize-path) r> + recursive-monitor construct-monitor + H{ } clone >>children + >>ready + dup start-pump-thread + dup wait-for-ready ; diff --git a/extra/io/nonblocking/nonblocking-docs.factor b/extra/io/nonblocking/nonblocking-docs.factor index ee9978f2c8..bd2be34c9d 100755 --- a/extra/io/nonblocking/nonblocking-docs.factor +++ b/extra/io/nonblocking/nonblocking-docs.factor @@ -1,5 +1,5 @@ USING: io io.buffers io.backend help.markup help.syntax kernel -byte-arrays sbufs words continuations byte-vectors ; +byte-arrays sbufs words continuations byte-vectors classes ; IN: io.nonblocking ARTICLE: "io.nonblocking" "Non-blocking I/O implementation" @@ -36,10 +36,10 @@ HELP: port $nl "Ports have the following slots:" { $list - { { $link port-handle } " - a native handle identifying the underlying native resource used by the port" } - { { $link port-error } " - the most recent I/O error, if any. This error is thrown to the waiting thread when " { $link pending-error } " is called by stream operations" } - { { $link port-type } " - a symbol identifying the port's intended purpose" } - { { $link port-eof? } " - a flag indicating if the port has reached the end of file while reading" } + { { $snippet "handle" } " - a native handle identifying the underlying native resource used by the port" } + { { $snippet "error" } " - the most recent I/O error, if any. This error is thrown to the waiting thread when " { $link pending-error } " is called by stream operations" } + { { $snippet "type" } " - a symbol identifying the port's intended purpose" } + { { $snippet "eof" } " - a flag indicating if the port has reached the end of file while reading" } } } ; HELP: input-port @@ -53,12 +53,12 @@ HELP: init-handle { $contract "Prepares a native handle for use by the port; called by " { $link } "." } ; HELP: -{ $values { "handle" "a native handle identifying an I/O resource" } { "buffer" "a " { $link buffer } " or " { $link f } } { "type" symbol } { "port" "a new " { $link port } } } -{ $description "Creates a new " { $link port } " using the specified native handle and I/O buffer." } +{ $values { "handle" "a native handle identifying an I/O resource" } { "class" class } { "port" "a new " { $link port } } } +{ $description "Creates a new " { $link port } " with no buffer." } $low-level-note ; HELP: -{ $values { "handle" "a native handle identifying an I/O resource" } { "type" symbol } { "port" "a new " { $link port } } } +{ $values { "handle" "a native handle identifying an I/O resource" } { "class" class } { "port" "a new " { $link port } } } { $description "Creates a new " { $link port } " using the specified native handle and a default-sized I/O buffer." } $low-level-note ; @@ -93,5 +93,5 @@ HELP: unless-eof { $description "If the port has reached end of file, outputs " { $link f } ", otherwise applies the quotation to the port." } ; HELP: can-write? -{ $values { "len" "a positive integer" } { "writer" output-port } { "?" "a boolean" } } +{ $values { "len" "a positive integer" } { "buffer" buffer } { "?" "a boolean" } } { $description "Tests if the port's output buffer can accomodate " { $snippet "len" } " bytes. If the buffer is empty, this always outputs " { $link t } ", since in that case the buffer will be grown automatically." } ; diff --git a/extra/io/nonblocking/nonblocking.factor b/extra/io/nonblocking/nonblocking.factor index 85319ad8ef..048a5d7b1c 100755 --- a/extra/io/nonblocking/nonblocking.factor +++ b/extra/io/nonblocking/nonblocking.factor @@ -1,46 +1,39 @@ ! Copyright (C) 2005, 2008 Slava Pestov, Doug Coleman ! See http://factorcode.org/license.txt for BSD license. -IN: io.nonblocking USING: math kernel io sequences io.buffers io.timeouts generic byte-vectors system io.streams.duplex io.encodings io.backend continuations debugger classes byte-arrays namespaces -splitting dlists assocs io.encodings.binary ; +splitting dlists assocs io.encodings.binary accessors ; +IN: io.nonblocking SYMBOL: default-buffer-size 64 1024 * default-buffer-size set-global -! Common delegate of native stream readers and writers -TUPLE: port -handle -error -timeout -type eof? ; +TUPLE: port handle buffer error timeout closed eof ; -M: port timeout port-timeout ; +M: port timeout timeout>> ; -M: port set-timeout set-port-timeout ; - -SYMBOL: closed - -PREDICATE: input-port < port port-type input-port eq? ; -PREDICATE: output-port < port port-type output-port eq? ; +M: port set-timeout (>>timeout) ; GENERIC: init-handle ( handle -- ) + GENERIC: close-handle ( handle -- ) -: ( handle buffer type -- port ) - pick init-handle { - set-port-handle - set-delegate - set-port-type - } port construct ; +: ( handle class -- port ) + construct-empty + swap dup init-handle >>handle ; inline -: ( handle type -- port ) - default-buffer-size get swap ; +: ( handle class -- port ) + + default-buffer-size get >>buffer ; inline + +TUPLE: input-port < port ; : ( handle -- input-port ) input-port ; +TUPLE: output-port < port ; + : ( handle -- output-port ) output-port ; @@ -48,7 +41,10 @@ GENERIC: close-handle ( handle -- ) swap [ swap ] [ ] [ dispose drop ] cleanup ; : pending-error ( port -- ) - dup port-error f rot set-port-error [ throw ] when* ; + [ f ] change-error drop [ throw ] when* ; + +: check-closed ( port -- port ) + dup closed>> [ "Port closed" throw ] when ; HOOK: cancel-io io-backend ( port -- ) @@ -59,21 +55,22 @@ M: port timed-out cancel-io ; GENERIC: (wait-to-read) ( port -- ) : wait-to-read ( count port -- ) - tuck buffer-length > [ (wait-to-read) ] [ drop ] if ; + tuck buffer>> buffer-length > [ (wait-to-read) ] [ drop ] if ; : wait-to-read1 ( port -- ) 1 swap wait-to-read ; : unless-eof ( port quot -- value ) - >r dup buffer-empty? over port-eof? and - [ f swap set-port-eof? f ] r> if ; inline + >r dup buffer>> buffer-empty? over eof>> and + [ f >>eof drop f ] r> if ; inline M: input-port stream-read1 - dup wait-to-read1 [ buffer-pop ] unless-eof ; + check-closed + dup wait-to-read1 [ buffer>> buffer-pop ] unless-eof ; : read-step ( count port -- byte-array/f ) [ wait-to-read ] 2keep - [ dupd buffer-read ] unless-eof nip ; + [ dupd buffer>> buffer-read ] unless-eof nip ; : read-loop ( count port accum -- ) pick over length - dup 0 > [ @@ -87,6 +84,7 @@ M: input-port stream-read1 ] if ; M: input-port stream-read + check-closed >r 0 max >fixnum r> 2dup read-step dup [ pick over length > [ @@ -94,72 +92,75 @@ M: input-port stream-read [ push-all ] keep [ read-loop ] keep B{ } like - ] [ - 2nip - ] if - ] [ - 2nip - ] if ; + ] [ 2nip ] if + ] [ 2nip ] if ; M: input-port stream-read-partial ( max stream -- byte-array/f ) + check-closed >r 0 max >fixnum r> read-step ; -: can-write? ( len writer -- ? ) +: can-write? ( len buffer -- ? ) [ buffer-fill + ] keep buffer-capacity <= ; : wait-to-write ( len port -- ) - tuck can-write? [ drop ] [ stream-flush ] if ; + tuck buffer>> can-write? [ drop ] [ stream-flush ] if ; M: output-port stream-write1 - 1 over wait-to-write byte>buffer ; + check-closed + 1 over wait-to-write + buffer>> byte>buffer ; M: output-port stream-write - over length over buffer-size > [ - [ buffer-size ] keep - [ stream-write ] curry each + check-closed + over length over buffer>> buffer-size > [ + [ buffer>> buffer-size ] + [ [ stream-write ] curry ] bi + each ] [ - over length over wait-to-write >buffer + [ >r length r> wait-to-write ] + [ buffer>> >buffer ] 2bi ] if ; GENERIC: port-flush ( port -- ) M: output-port stream-flush ( port -- ) - dup port-flush pending-error ; + check-closed + [ port-flush ] [ pending-error ] bi ; -: close-port ( port type -- ) - output-port eq? [ dup port-flush ] when +GENERIC: close-port ( port -- ) + +M: output-port close-port + [ port-flush ] [ call-next-method ] bi ; + +M: port close-port dup cancel-io - dup port-handle close-handle - dup delegate [ buffer-free ] when* - f swap set-delegate ; + dup handle>> close-handle + [ [ buffer-free ] when* f ] change-buffer drop ; M: port dispose - dup port-type closed eq? - [ drop ] - [ dup port-type >r closed over set-port-type r> close-port ] - if ; + dup closed>> [ drop ] [ t >>closed close-port ] if ; -TUPLE: server-port addr client client-addr encoding ; +TUPLE: server-port < port addr client client-addr encoding ; : ( handle addr encoding -- server ) - rot f server-port - { set-server-port-addr set-server-port-encoding set-delegate } - server-port construct ; + rot server-port + swap >>encoding + swap >>addr ; -: check-server-port ( port -- ) - port-type server-port assert= ; +: check-server-port ( port -- port ) + dup server-port? [ "Not a server port" throw ] unless ; inline -TUPLE: datagram-port addr packet packet-addr ; +TUPLE: datagram-port < port addr packet packet-addr ; : ( handle addr -- datagram ) - >r f datagram-port r> - { set-delegate set-datagram-port-addr } - datagram-port construct ; + swap datagram-port + swap >>addr ; -: check-datagram-port ( port -- ) - port-type datagram-port assert= ; +: check-datagram-port ( port -- port ) + check-closed + dup datagram-port? [ "Not a datagram port" throw ] unless ; inline -: check-datagram-send ( packet addrspec port -- ) - dup check-datagram-port - datagram-port-addr [ class ] bi@ assert= - class byte-array assert= ; +: check-datagram-send ( packet addrspec port -- packet addrspec port ) + check-datagram-port + 2dup addr>> [ class ] bi@ assert= + pick class byte-array assert= ; diff --git a/extra/io/server/server.factor b/extra/io/server/server.factor index 0b7e626908..1d5ed16dc5 100755 --- a/extra/io/server/server.factor +++ b/extra/io/server/server.factor @@ -12,17 +12,17 @@ SYMBOL: servers LOG: accepted-connection NOTICE -: with-client ( client quot -- ) +: with-client ( client addrspec quot -- ) [ - over client-stream-addr accepted-connection + swap accepted-connection with-stream* - ] curry with-disposal ; inline + ] 2curry with-disposal ; inline \ with-client DEBUG add-error-logging : accept-loop ( server quot -- ) [ - >r accept r> [ with-client ] 2curry "Client" spawn drop + >r accept r> [ with-client ] 3curry "Client" spawn drop ] 2keep accept-loop ; inline : server-loop ( addrspec encoding quot -- ) diff --git a/extra/io/sockets/impl/impl.factor b/extra/io/sockets/impl/impl.factor index 5b0790ca2d..498430fdbc 100755 --- a/extra/io/sockets/impl/impl.factor +++ b/extra/io/sockets/impl/impl.factor @@ -90,7 +90,7 @@ M: inet6 parse-sockaddr { [ dup AF_INET = ] [ T{ inet4 } ] } { [ dup AF_INET6 = ] [ T{ inet6 } ] } { [ dup AF_UNIX = ] [ T{ local } ] } - { [ t ] [ f ] } + [ f ] } cond nip ; M: f parse-sockaddr nip ; diff --git a/extra/io/sockets/sockets-docs.factor b/extra/io/sockets/sockets-docs.factor index fa38ec90ee..ad78b4631c 100755 --- a/extra/io/sockets/sockets-docs.factor +++ b/extra/io/sockets/sockets-docs.factor @@ -17,8 +17,6 @@ ARTICLE: "network-connection" "Connection-oriented networking" "Connection-oriented network servers are implemented by first opening a server socket, then waiting for connections:" { $subsection } { $subsection accept } -"The stream returned by " { $link accept } " holds the address specifier of the remote client:" -{ $subsection client-stream-addr } "Server sockets are closed by calling " { $link dispose } "." $nl "Address specifiers have the following interpretation with connection-oriented networking words:" @@ -118,10 +116,8 @@ HELP: { $errors "Throws an error if the address is already in use, or if it if the system forbids access." } ; HELP: accept -{ $values { "server" "a handle" } { "client" "a bidirectional stream" } } -{ $description "Waits for a connection to a server socket created by " { $link } ", and outputs a bidirectional stream when the connection has been established. The encoding of this stream is the one that was passed to the server constructor." -$nl -"The returned client stream responds to the " { $link client-stream-addr } " word with the address of the incoming connection." } +{ $values { "server" "a handle" } { "client" "a bidirectional stream" } { "addrspec" "an address specifier" } } +{ $description "Waits for a connection to a server socket created by " { $link } ", and outputs a bidirectional stream when the connection has been established. The encoding of this stream is the one that was passed to the server constructor." } { $errors "Throws an error if the server socket is closed or otherwise is unavailable." } ; HELP: diff --git a/extra/io/sockets/sockets.factor b/extra/io/sockets/sockets.factor index 17799227b8..04141c56ef 100755 --- a/extra/io/sockets/sockets.factor +++ b/extra/io/sockets/sockets.factor @@ -1,7 +1,7 @@ ! 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 ; +sequences arrays io.encodings io.nonblocking accessors ; IN: io.sockets TUPLE: local path ; @@ -21,20 +21,14 @@ TUPLE: inet host port ; C: inet -TUPLE: client-stream addr ; +HOOK: ((client)) io-backend ( addrspec -- client-in client-out ) -: ( addrspec delegate -- stream ) - { set-client-stream-addr set-delegate } - client-stream construct ; - -HOOK: (client) io-backend ( addrspec -- client-in client-out ) - -GENERIC: client* ( addrspec -- client-in client-out ) -M: array client* [ (client) 2array ] attempt-all first2 ; -M: object client* (client) ; +GENERIC: (client) ( addrspec -- client-in client-out ) +M: array (client) [ ((client)) 2array ] attempt-all first2 ; +M: object (client) ((client)) ; : ( addrspec encoding -- stream ) - >r client* r> ; + >r (client) r> ; HOOK: (server) io-backend ( addrspec -- handle ) @@ -43,10 +37,9 @@ HOOK: (server) io-backend ( addrspec -- handle ) HOOK: (accept) io-backend ( server -- addrspec handle ) -: accept ( server -- client ) - [ (accept) dup ] keep - server-port-encoding - ; +: accept ( server -- client addrspec ) + [ (accept) dup ] [ encoding>> ] bi + swap ; HOOK: io-backend ( addrspec -- datagram ) @@ -58,7 +51,8 @@ HOOK: resolve-host io-backend ( host serv passive? -- seq ) HOOK: host-name io-backend ( -- string ) -M: inet client* - dup inet-host swap inet-port f resolve-host - dup empty? [ "Host name lookup failed" throw ] when - client* ; +M: inet (client) + [ host>> ] [ port>> ] bi f resolve-host + [ empty? [ "Host name lookup failed" throw ] when ] + [ (client) ] + bi ; diff --git a/extra/io/timeouts/timeouts-docs.factor b/extra/io/timeouts/timeouts-docs.factor index df7e1389cc..64104083be 100755 --- a/extra/io/timeouts/timeouts-docs.factor +++ b/extra/io/timeouts/timeouts-docs.factor @@ -18,13 +18,13 @@ HELP: with-timeout { $description "Applies the quotation to the object. If the object's timeout expires before the quotation returns, " { $link timed-out } " is called on the object." } ; ARTICLE: "io.timeouts" "I/O timeout protocol" -"Streams and processes support optional timeouts, which impose an upper bound on the length of time for which an operation on these objects can block. Timeouts are used in network servers to prevent malicious clients from holding onto connections forever, and to ensure that runaway processes get killed." +"Streams, processes and monitors support optional timeouts, which impose an upper bound on the length of time for which an operation on these objects can block. Timeouts are used in network servers to prevent malicious clients from holding onto connections forever, and to ensure that runaway processes get killed." { $subsection timeout } { $subsection set-timeout } "The I/O timeout protocol can be implemented by any class wishing to support timeouts on blocking operations." { $subsection timed-out } "A combinator to be used in operations which can time out:" { $subsection with-timeout } -{ $see-also "stream-protocol" "io.launcher" } ; +{ $see-also "stream-protocol" "io.launcher" "io.monitors" } ; ABOUT: "io.timeouts" diff --git a/extra/io/unix/backend/backend.factor b/extra/io/unix/backend/backend.factor old mode 100755 new mode 100644 index 865490b0ce..396b8cf2e8 --- a/extra/io/unix/backend/backend.factor +++ b/extra/io/unix/backend/backend.factor @@ -14,18 +14,13 @@ TUPLE: io-task port callbacks ; : io-task-fd port>> handle>> ; : ( port continuation/f class -- task ) - >r [ 1vector ] [ V{ } clone ] if* io-task construct-boa - r> construct-delegate ; inline + construct-empty + swap [ 1vector ] [ V{ } clone ] if* >>callbacks + swap >>port ; inline -TUPLE: input-task ; +TUPLE: input-task < io-task ; -: ( port continuation class -- task ) - >r input-task r> construct-delegate ; inline - -TUPLE: output-task ; - -: ( port continuation class -- task ) - >r output-task r> construct-delegate ; inline +TUPLE: output-task < io-task ; GENERIC: do-io-task ( task -- ? ) GENERIC: io-task-container ( mx task -- hashtable ) @@ -37,9 +32,10 @@ M: input-task io-task-container drop reads>> ; M: output-task io-task-container drop writes>> ; -: ( -- mx ) f H{ } clone H{ } clone mx construct-boa ; - -: construct-mx ( class -- obj ) swap construct-delegate ; +: construct-mx ( class -- obj ) + construct-empty + H{ } clone >>reads + H{ } clone >>writes ; inline GENERIC: register-io-task ( task mx -- ) GENERIC: unregister-io-task ( task mx -- ) @@ -123,16 +119,18 @@ M: unix cancel-io ( port -- ) ! Readers : reader-eof ( reader -- ) - dup buffer-empty? [ t >>eof? ] when drop ; + dup buffer>> buffer-empty? [ t >>eof ] when drop ; : (refill) ( port -- n ) - [ handle>> ] [ buffer-end ] [ buffer-capacity ] tri read ; + [ handle>> ] + [ buffer>> buffer-end ] + [ buffer>> buffer-capacity ] tri read ; : refill ( port -- ? ) #! Return f if there is a recoverable error - dup buffer-empty? [ + dup buffer>> buffer-empty? [ dup (refill) dup 0 >= [ - swap n>buffer t + swap buffer>> n>buffer t ] [ drop defer-error ] if @@ -140,10 +138,10 @@ M: unix cancel-io ( port -- ) drop t ] if ; -TUPLE: read-task ; +TUPLE: read-task < input-task ; : ( port continuation -- task ) - read-task ; + read-task ; M: read-task do-io-task io-task-port dup refill @@ -155,28 +153,33 @@ M: input-port (wait-to-read) ! Writers : write-step ( port -- ? ) - dup [ handle>> ] [ buffer@ ] [ buffer-length ] tri write - dup 0 >= [ swap buffer-consume f ] [ drop defer-error ] if ; + dup + [ handle>> ] + [ buffer>> buffer@ ] + [ buffer>> buffer-length ] tri + write dup 0 >= + [ swap buffer>> buffer-consume f ] + [ drop defer-error ] if ; -TUPLE: write-task ; +TUPLE: write-task < output-task ; : ( port continuation -- task ) - write-task ; + write-task ; M: write-task do-io-task - io-task-port dup [ buffer-empty? ] [ port-error ] bi or - [ 0 swap buffer-reset t ] [ write-step ] if ; + io-task-port dup [ buffer>> buffer-empty? ] [ port-error ] bi or + [ 0 swap buffer>> buffer-reset t ] [ write-step ] if ; : add-write-io-task ( port continuation -- ) - over port-handle mx get-global mx-writes at* + over handle>> mx get-global writes>> at* [ io-task-callbacks push drop ] [ drop add-io-task ] if ; : (wait-to-write) ( port -- ) [ add-write-io-task ] with-port-continuation drop ; -M: port port-flush ( port -- ) - dup buffer-empty? [ drop ] [ (wait-to-write) ] if ; +M: output-port port-flush ( port -- ) + dup buffer>> buffer-empty? [ drop ] [ (wait-to-write) ] if ; M: unix io-multiplex ( ms/f -- ) mx get-global wait-for-events ; @@ -187,13 +190,12 @@ M: unix (init-stdio) ( -- ) 2 ; ! mx io-task for embedding an fd-based mx inside another mx -TUPLE: mx-port mx ; +TUPLE: mx-port < port mx ; : ( mx -- port ) - dup fd>> f mx-port - { set-mx-port-mx set-delegate } mx-port construct ; + dup fd>> mx-port swap >>mx ; -TUPLE: mx-task ; +TUPLE: mx-task < io-task ; : ( port -- task ) f mx-task ; @@ -203,3 +205,6 @@ M: mx-task do-io-task : multiplexer-error ( n -- ) 0 < [ err_no ignorable-error? [ (io-error) ] unless ] when ; + +: ?flag ( n mask symbol -- n ) + pick rot bitand 0 > [ , ] [ drop ] if ; diff --git a/extra/io/unix/bsd/bsd.factor b/extra/io/unix/bsd/bsd.factor index 12a64a41f9..d74c355642 100755 --- a/extra/io/unix/bsd/bsd.factor +++ b/extra/io/unix/bsd/bsd.factor @@ -1,8 +1,18 @@ ! Copyright (C) 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. IN: io.unix.bsd -USING: io.backend io.unix.backend io.unix.select -namespaces system ; +USING: namespaces system kernel accessors assocs continuations +unix +io.backend io.unix.backend io.unix.select io.unix.kqueue io.monitors ; M: bsd init-io ( -- ) - mx set-global ; + mx set-global + kqueue-mx set-global + kqueue-mx get-global + dup io-task-fd + [ mx get-global reads>> set-at ] + [ mx get-global writes>> set-at ] 2bi ; + +M: bsd (monitor) ( path recursive? mailbox -- ) + swap [ "Recursive kqueue monitors not supported" throw ] when + ; diff --git a/extra/io/unix/epoll/epoll.factor b/extra/io/unix/epoll/epoll.factor index 1459549f9e..2d7ca9ba3f 100644 --- a/extra/io/unix/epoll/epoll.factor +++ b/extra/io/unix/epoll/epoll.factor @@ -5,7 +5,7 @@ bit-arrays sequences assocs unix unix.linux.epoll math namespaces structs ; IN: io.unix.epoll -TUPLE: epoll-mx events ; +TUPLE: epoll-mx < mx events ; : max-events ( -- n ) #! We read up to 256 events at a time. This is an arbitrary @@ -33,12 +33,10 @@ M: output-task io-task-events drop EPOLLOUT ; epoll_ctl io-error ; M: epoll-mx register-io-task ( task mx -- ) - 2dup EPOLL_CTL_ADD do-epoll-ctl - delegate register-io-task ; + [ EPOLL_CTL_ADD do-epoll-ctl ] [ call-next-method ] 2bi ; M: epoll-mx unregister-io-task ( task mx -- ) - 2dup delegate unregister-io-task - EPOLL_CTL_DEL do-epoll-ctl ; + [ call-next-method ] [ EPOLL_CTL_DEL do-epoll-ctl ] 2bi ; : wait-event ( mx timeout -- n ) >r { mx-fd epoll-mx-events } get-slots max-events diff --git a/extra/io/unix/files/files.factor b/extra/io/unix/files/files.factor index 39c18b4601..5873568a9e 100755 --- a/extra/io/unix/files/files.factor +++ b/extra/io/unix/files/files.factor @@ -72,20 +72,20 @@ M: unix delete-directory ( path -- ) M: unix copy-file ( from to -- ) [ normalize-path ] bi@ [ (copy-file) ] - [ swap file-info file-info-permissions chmod io-error ] + [ swap file-info permissions>> chmod io-error ] 2bi ; : stat>type ( stat -- type ) - stat-st_mode { - { [ dup S_ISREG ] [ +regular-file+ ] } - { [ dup S_ISDIR ] [ +directory+ ] } - { [ dup S_ISCHR ] [ +character-device+ ] } - { [ dup S_ISBLK ] [ +block-device+ ] } - { [ dup S_ISFIFO ] [ +fifo+ ] } - { [ dup S_ISLNK ] [ +symbolic-link+ ] } - { [ dup S_ISSOCK ] [ +socket+ ] } - { [ t ] [ +unknown+ ] } - } cond nip ; + stat-st_mode S_IFMT bitand { + { S_IFREG [ +regular-file+ ] } + { S_IFDIR [ +directory+ ] } + { S_IFCHR [ +character-device+ ] } + { S_IFBLK [ +block-device+ ] } + { S_IFIFO [ +fifo+ ] } + { S_IFLNK [ +symbolic-link+ ] } + { S_IFSOCK [ +socket+ ] } + [ drop +unknown+ ] + } case ; : stat>file-info ( stat -- info ) { diff --git a/extra/io/unix/kqueue/kqueue.factor b/extra/io/unix/kqueue/kqueue.factor old mode 100755 new mode 100644 index 97b186edf3..3a140bdbec --- a/extra/io/unix/kqueue/kqueue.factor +++ b/extra/io/unix/kqueue/kqueue.factor @@ -1,12 +1,14 @@ ! Copyright (C) 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: alien.c-types kernel io.nonblocking io.unix.backend -sequences assocs unix unix.time unix.kqueue unix.process math namespaces -combinators threads vectors io.launcher -io.unix.launcher ; +USING: alien.c-types kernel math math.bitfields namespaces +locals accessors combinators threads vectors hashtables +sequences assocs continuations +unix unix.time unix.kqueue unix.process +io.nonblocking io.unix.backend io.launcher io.unix.launcher +io.monitors ; IN: io.unix.kqueue -TUPLE: kqueue-mx events ; +TUPLE: kqueue-mx < mx events monitors ; : max-events ( -- n ) #! We read up to 256 events at a time. This is an arbitrary @@ -15,8 +17,9 @@ TUPLE: kqueue-mx events ; : ( -- mx ) kqueue-mx construct-mx - kqueue dup io-error over set-mx-fd - max-events "kevent" over set-kqueue-mx-events ; + H{ } clone >>monitors + kqueue dup io-error >>fd + max-events "kevent" >>events ; GENERIC: io-task-filter ( task -- n ) @@ -24,52 +27,78 @@ M: input-task io-task-filter drop EVFILT_READ ; M: output-task io-task-filter drop EVFILT_WRITE ; +GENERIC: io-task-fflags ( task -- n ) + +M: io-task io-task-fflags drop 0 ; + : make-kevent ( task flags -- event ) "kevent" tuck set-kevent-flags over io-task-fd over set-kevent-ident + over io-task-fflags over set-kevent-fflags swap io-task-filter over set-kevent-filter ; : register-kevent ( kevent mx -- ) - mx-fd swap 1 f 0 f kevent + fd>> swap 1 f 0 f kevent 0 < [ err_no ESRCH = [ (io-error) ] unless ] when ; M: kqueue-mx register-io-task ( task mx -- ) - over EV_ADD make-kevent over register-kevent - delegate register-io-task ; + [ >r EV_ADD make-kevent r> register-kevent ] + [ call-next-method ] + 2bi ; M: kqueue-mx unregister-io-task ( task mx -- ) - 2dup delegate unregister-io-task - swap EV_DELETE make-kevent swap register-kevent ; + [ call-next-method ] + [ >r EV_DELETE make-kevent r> register-kevent ] + 2bi ; : wait-kevent ( mx timespec -- n ) - >r dup mx-fd f 0 roll kqueue-mx-events max-events r> kevent + >r [ fd>> f 0 ] keep events>> max-events r> kevent dup multiplexer-error ; -: kevent-read-task ( mx fd -- ) - over mx-reads at handle-io-task ; +:: kevent-read-task ( mx fd kevent -- ) + mx fd mx reads>> at handle-io-task ; -: kevent-write-task ( mx fd -- ) - over mx-reads at handle-io-task ; +:: kevent-write-task ( mx fd kevent -- ) + mx fd mx writes>> at handle-io-task ; -: kevent-proc-task ( pid -- ) - dup wait-for-pid swap find-process +:: kevent-proc-task ( mx pid kevent -- ) + pid wait-for-pid + pid find-process dup [ swap notify-exit ] [ 2drop ] if ; +: parse-action ( mask -- changed ) + [ + NOTE_DELETE +remove-file+ ?flag + NOTE_WRITE +modify-file+ ?flag + NOTE_EXTEND +modify-file+ ?flag + NOTE_ATTRIB +modify-file+ ?flag + NOTE_RENAME +rename-file+ ?flag + NOTE_REVOKE +remove-file+ ?flag + drop + ] { } make prune ; + +:: kevent-vnode-task ( mx kevent fd -- ) + "" + kevent kevent-fflags parse-action + fd mx monitors>> at queue-change ; + : handle-kevent ( mx kevent -- ) - dup kevent-ident swap kevent-filter { + [ ] [ kevent-ident ] [ kevent-filter ] tri { { [ dup EVFILT_READ = ] [ drop kevent-read-task ] } { [ dup EVFILT_WRITE = ] [ drop kevent-write-task ] } - { [ dup EVFILT_PROC = ] [ drop kevent-proc-task drop ] } + { [ dup EVFILT_PROC = ] [ drop kevent-proc-task ] } + { [ dup EVFILT_VNODE = ] [ drop kevent-vnode-task ] } } cond ; : handle-kevents ( mx n -- ) - [ over kqueue-mx-events kevent-nth handle-kevent ] with each ; + [ over events>> kevent-nth handle-kevent ] with each ; M: kqueue-mx wait-for-events ( ms mx -- ) swap dup [ make-timespec ] when dupd wait-kevent handle-kevents ; +! Procs : make-proc-kevent ( pid -- kevent ) "kevent" tuck set-kevent-ident @@ -77,5 +106,44 @@ M: kqueue-mx wait-for-events ( ms mx -- ) EVFILT_PROC over set-kevent-filter NOTE_EXIT over set-kevent-fflags ; -: add-pid-task ( pid mx -- ) +: register-pid-task ( pid mx -- ) swap make-proc-kevent swap register-kevent ; + +! VNodes +TUPLE: vnode-monitor < monitor fd ; + +: vnode-fflags ( -- n ) + { + NOTE_DELETE + NOTE_WRITE + NOTE_EXTEND + NOTE_ATTRIB + NOTE_LINK + NOTE_RENAME + NOTE_REVOKE + } flags ; + +: make-vnode-kevent ( fd flags -- kevent ) + "kevent" + tuck set-kevent-flags + tuck set-kevent-ident + EVFILT_VNODE over set-kevent-filter + vnode-fflags over set-kevent-fflags ; + +: register-monitor ( monitor mx -- ) + >r dup fd>> r> + [ >r EV_ADD EV_CLEAR bitor make-vnode-kevent r> register-kevent drop ] + [ monitors>> set-at ] 3bi ; + +: unregister-monitor ( monitor mx -- ) + >r fd>> r> + [ monitors>> delete-at ] + [ >r EV_DELETE make-vnode-kevent r> register-kevent ] 2bi ; + +: ( path mailbox -- monitor ) + >r [ O_RDONLY 0 open dup io-error ] keep r> + vnode-monitor construct-monitor swap >>fd + [ dup kqueue-mx get register-monitor ] [ ] [ fd>> close ] cleanup ; + +M: vnode-monitor dispose + [ kqueue-mx get unregister-monitor ] [ fd>> close ] bi ; diff --git a/extra/io/unix/launcher/launcher.factor b/extra/io/unix/launcher/launcher.factor index 82852f6311..2c1e6261c0 100755 --- a/extra/io/unix/launcher/launcher.factor +++ b/extra/io/unix/launcher/launcher.factor @@ -55,7 +55,7 @@ USE: unix { [ pick string? ] [ redirect-file ] } { [ pick +closed+ eq? ] [ redirect-closed ] } { [ pick +inherit+ eq? ] [ redirect-closed ] } - { [ t ] [ redirect-stream ] } + [ redirect-stream ] } cond ; : ?closed dup +closed+ eq? [ drop "/dev/null" ] when ; diff --git a/extra/io/unix/linux/linux.factor b/extra/io/unix/linux/linux.factor index 30c61f6d21..e75f4c5f6b 100755 --- a/extra/io/unix/linux/linux.factor +++ b/extra/io/unix/linux/linux.factor @@ -1,125 +1,10 @@ ! Copyright (C) 2008 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: kernel io.backend io.monitors io.monitors.private -io.files io.buffers io.nonblocking io.timeouts io.unix.backend -io.unix.select io.unix.launcher unix.linux.inotify assocs -namespaces threads continuations init math alien.c-types alien -vocabs.loader accessors system ; +USING: kernel io.backend io.monitors io.unix.backend +io.unix.select io.unix.linux.monitors system namespaces ; IN: io.unix.linux -TUPLE: linux-monitor ; - -: ( wd -- monitor ) - linux-monitor construct-simple-monitor ; - -TUPLE: inotify watches ; - -: watches ( -- assoc ) inotify get-global watches>> ; - -: wd>monitor ( wd -- monitor ) watches at ; - -: ( -- port/f ) - H{ } clone - inotify_init dup 0 < [ 2drop f ] [ - inotify - { set-inotify-watches set-delegate } inotify construct - ] if ; - -: inotify-fd inotify get-global handle>> ; - -: (add-watch) ( path mask -- wd ) - inotify-fd -rot inotify_add_watch dup io-error ; - -: check-existing ( wd -- ) - watches key? [ - "Cannot open multiple monitors for the same file" throw - ] when ; - -: add-watch ( path mask -- monitor ) - (add-watch) dup check-existing - [ dup ] keep watches set-at ; - -: remove-watch ( monitor -- ) - dup simple-monitor-handle watches delete-at - simple-monitor-handle inotify-fd swap inotify_rm_watch io-error ; - -: check-inotify - inotify get [ - "inotify is not supported by this Linux release" throw - ] unless ; - -M: linux ( path recursive? -- monitor ) - check-inotify - drop IN_CHANGE_EVENTS add-watch ; - -M: linux-monitor dispose ( monitor -- ) - dup delegate dispose remove-watch ; - -: ?flag ( n mask symbol -- n ) - pick rot bitand 0 > [ , ] [ drop ] if ; - -: parse-action ( mask -- changed ) - [ - IN_CREATE +add-file+ ?flag - IN_DELETE +remove-file+ ?flag - IN_DELETE_SELF +remove-file+ ?flag - IN_MODIFY +modify-file+ ?flag - IN_ATTRIB +modify-file+ ?flag - IN_MOVED_FROM +rename-file+ ?flag - IN_MOVED_TO +rename-file+ ?flag - IN_MOVE_SELF +rename-file+ ?flag - drop - ] { } make ; - -: parse-file-notify ( buffer -- changed path ) - { inotify-event-name inotify-event-mask } get-slots - parse-action swap alien>char-string ; - -: events-exhausted? ( i buffer -- ? ) - fill>> >= ; - -: inotify-event@ ( i buffer -- alien ) - ptr>> ; - -: next-event ( i buffer -- i buffer ) - 2dup inotify-event@ - inotify-event-len "inotify-event" heap-size + - swap >r + r> ; - -: parse-file-notifications ( i buffer -- ) - 2dup events-exhausted? [ 2drop ] [ - 2dup inotify-event@ dup inotify-event-wd wd>monitor [ - monitor-queue [ - parse-file-notify changed-file - ] bind - ] keep notify-callback - next-event parse-file-notifications - ] if ; - -: read-notifications ( port -- ) - dup refill drop - 0 over parse-file-notifications - 0 swap buffer-reset ; - -TUPLE: inotify-task ; - -: ( port -- task ) - f inotify-task ; - -: init-inotify ( mx -- ) - dup [ - dup inotify set-global - swap register-io-task - ] [ - 2drop - ] if ; - -M: inotify-task do-io-task ( task -- ) - io-task-port read-notifications f ; - M: linux init-io ( -- ) - - [ mx set-global ] - [ init-inotify ] bi ; + mx set-global ; linux set-io-backend diff --git a/extra/io/unix/linux/monitors/monitors.factor b/extra/io/unix/linux/monitors/monitors.factor new file mode 100644 index 0000000000..f92fb36d0d --- /dev/null +++ b/extra/io/unix/linux/monitors/monitors.factor @@ -0,0 +1,126 @@ +! Copyright (C) 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: kernel io.backend io.monitors io.monitors.recursive +io.files io.buffers io.monitors io.nonblocking io.timeouts +io.unix.backend io.unix.select unix.linux.inotify assocs +namespaces threads continuations init math math.bitfields +alien.c-types alien vocabs.loader accessors system hashtables ; +IN: io.unix.linux.monitors + +TUPLE: linux-monitor < monitor wd ; + +: ( wd path mailbox -- monitor ) + linux-monitor construct-monitor + swap >>wd ; + +SYMBOL: watches + +SYMBOL: inotify + +: wd>monitor ( wd -- monitor ) watches get at ; + +: ( -- port/f ) + inotify_init dup 0 < [ drop f ] [ ] if ; + +: inotify-fd inotify get handle>> ; + +: check-existing ( wd -- ) + watches get key? [ + "Cannot open multiple monitors for the same file" throw + ] when ; + +: (add-watch) ( path mask -- wd ) + inotify-fd -rot inotify_add_watch dup io-error dup check-existing ; + +: add-watch ( path mask mailbox -- monitor ) + >r + >r (normalize-path) r> + [ (add-watch) ] [ drop ] 2bi r> + [ ] [ ] [ wd>> ] tri watches get set-at ; + +: check-inotify + inotify get [ + "Calling outside with-monitors" throw + ] unless ; + +M: linux (monitor) ( path recursive? mailbox -- monitor ) + swap [ + + ] [ + check-inotify + IN_CHANGE_EVENTS swap add-watch + ] if ; + +M: linux-monitor dispose ( monitor -- ) + [ wd>> watches get delete-at ] + [ wd>> inotify-fd swap inotify_rm_watch io-error ] bi ; + +: ignore-flags? ( mask -- ? ) + { + IN_DELETE_SELF + IN_MOVE_SELF + IN_UNMOUNT + IN_Q_OVERFLOW + IN_IGNORED + } flags bitand 0 > ; + +: parse-action ( mask -- changed ) + [ + IN_CREATE +add-file+ ?flag + IN_DELETE +remove-file+ ?flag + IN_MODIFY +modify-file+ ?flag + IN_ATTRIB +modify-file+ ?flag + IN_MOVED_FROM +rename-file-old+ ?flag + IN_MOVED_TO +rename-file-new+ ?flag + drop + ] { } make prune ; + +: parse-file-notify ( buffer -- path changed ) + dup inotify-event-mask ignore-flags? [ + drop f f + ] [ + [ inotify-event-name alien>char-string ] + [ inotify-event-mask parse-action ] bi + ] if ; + +: events-exhausted? ( i buffer -- ? ) + fill>> >= ; + +: inotify-event@ ( i buffer -- alien ) + ptr>> ; + +: next-event ( i buffer -- i buffer ) + 2dup inotify-event@ + inotify-event-len "inotify-event" heap-size + + swap >r + r> ; + +: parse-file-notifications ( i buffer -- ) + 2dup events-exhausted? [ 2drop ] [ + 2dup inotify-event@ dup inotify-event-wd wd>monitor + >r parse-file-notify r> queue-change + next-event parse-file-notifications + ] if ; + +: inotify-read-loop ( port -- ) + dup wait-to-read1 + 0 over buffer>> parse-file-notifications + 0 over buffer>> buffer-reset + inotify-read-loop ; + +: inotify-read-thread ( port -- ) + [ inotify-read-loop ] curry ignore-errors ; + +M: linux init-monitors + H{ } clone watches set + [ + [ inotify set ] + [ + [ inotify-read-thread ] curry + "Linux monitor thread" spawn drop + ] bi + ] [ + "Linux kernel version is too old" throw + ] if* ; + +M: linux dispose-monitors + inotify get dispose ; diff --git a/extra/io/unix/macosx/macosx.factor b/extra/io/unix/macosx/macosx.factor index c1c73ea018..60ba4c08b3 100644 --- a/extra/io/unix/macosx/macosx.factor +++ b/extra/io/unix/macosx/macosx.factor @@ -1,23 +1,23 @@ -USING: io.unix.bsd io.backend io.monitors io.monitors.private -continuations kernel core-foundation.fsevents sequences -namespaces arrays system ; +! Copyright (C) 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: io.unix.bsd io.backend io.monitors core-foundation.fsevents +continuations kernel sequences namespaces arrays system locals +accessors ; IN: io.unix.macosx -macosx set-io-backend - -TUPLE: macosx-monitor ; +TUPLE: macosx-monitor < monitor handle ; : enqueue-notifications ( triples monitor -- ) - tuck monitor-queue - [ [ first { +modify-file+ } swap changed-file ] each ] bind - notify-callback ; + [ + >r first { +modify-file+ } r> queue-change + ] curry each ; -M: macosx - drop - f macosx-monitor construct-simple-monitor +M:: macosx (monitor) ( path recursive? mailbox -- monitor ) + path mailbox macosx-monitor construct-monitor dup [ enqueue-notifications ] curry - rot 1array 0 0 - over set-simple-monitor-handle ; + path 1array 0 0 >>handle ; M: macosx-monitor dispose - dup simple-monitor-handle dispose delegate dispose ; + handle>> dispose ; + +macosx set-io-backend diff --git a/extra/io/unix/select/select.factor b/extra/io/unix/select/select.factor index aceee0f311..facaf4d73d 100755 --- a/extra/io/unix/select/select.factor +++ b/extra/io/unix/select/select.factor @@ -5,7 +5,7 @@ bit-arrays sequences assocs unix math namespaces structs accessors ; IN: io.unix.select -TUPLE: select-mx read-fdset write-fdset ; +TUPLE: select-mx < mx read-fdset write-fdset ; ! Factor's bit-arrays are an array of bytes, OS X expects ! FD_SET to be an array of cells, so we have to account for @@ -15,8 +15,8 @@ TUPLE: select-mx read-fdset write-fdset ; : ( -- mx ) select-mx construct-mx - FD_SETSIZE 8 * >>read-fdset - FD_SETSIZE 8 * >>write-fdset ; + FD_SETSIZE 8 * >>read-fdset + FD_SETSIZE 8 * >>write-fdset ; : clear-nth ( n seq -- ? ) [ nth ] [ f -rot set-nth ] 2bi ; @@ -29,7 +29,6 @@ TUPLE: select-mx read-fdset write-fdset ; [ handle-fd ] 2curry assoc-each ; : init-fdset ( tasks fdset -- ) - ! dup clear-bits [ >r drop t swap munge r> set-nth ] curry assoc-each ; : read-fdset/tasks @@ -45,9 +44,9 @@ TUPLE: select-mx read-fdset write-fdset ; [ reads>> max-fd ] [ writes>> max-fd ] bi max 1+ ; : init-fdsets ( mx -- nfds read write except ) - [ num-fds ] keep - [ read-fdset/tasks tuck init-fdset ] keep - write-fdset/tasks tuck init-fdset + [ num-fds ] + [ read-fdset/tasks tuck init-fdset ] + [ write-fdset/tasks tuck init-fdset ] tri f ; M: select-mx wait-for-events ( ms mx -- ) diff --git a/extra/io/unix/sockets/sockets.factor b/extra/io/unix/sockets/sockets.factor index a54205a878..cecc70fb08 100755 --- a/extra/io/unix/sockets/sockets.factor +++ b/extra/io/unix/sockets/sockets.factor @@ -7,7 +7,7 @@ USING: alien alien.c-types generic io kernel math namespaces io.nonblocking parser threads unix sequences byte-arrays io.sockets io.binary io.unix.backend io.streams.duplex io.sockets.impl math.parser continuations libc -combinators io.backend io.files io.files.private system ; +combinators io.backend io.files io.files.private system accessors ; IN: io.unix.sockets : pending-init-error ( port -- ) @@ -30,10 +30,10 @@ M: unix addrinfo-error ( n -- ) : init-client-socket ( fd -- ) SOL_SOCKET SO_OOBINLINE sockopt ; -TUPLE: connect-task ; +TUPLE: connect-task < output-task ; : ( port continuation -- task ) - connect-task ; + connect-task ; M: connect-task do-io-task io-task-port dup port-handle f 0 write @@ -42,7 +42,7 @@ M: connect-task do-io-task : wait-to-connect ( port -- ) [ add-io-task ] with-port-continuation drop ; -M: unix (client) ( addrspec -- client-in client-out ) +M: unix ((client)) ( addrspec -- client-in client-out ) dup make-sockaddr/size >r >r protocol-family SOCK_STREAM socket-fd dup r> r> connect @@ -61,10 +61,10 @@ USE: unix : init-server-socket ( fd -- ) SOL_SOCKET SO_REUSEADDR sockopt ; -TUPLE: accept-task ; +TUPLE: accept-task < input-task ; : ( port continuation -- task ) - accept-task ; + accept-task ; : accept-sockaddr ( port -- fd sockaddr ) dup port-handle swap server-port-addr sockaddr-type @@ -97,11 +97,10 @@ M: unix (server) ( addrspec -- handle ) M: unix (accept) ( server -- addrspec handle ) #! Wait for a client connection. - dup check-server-port - dup wait-to-accept - dup pending-error - dup server-port-client-addr - swap server-port-client ; + check-server-port + [ wait-to-accept ] + [ pending-error ] + [ [ client-addr>> ] [ client>> ] bi ] tri ; ! Datagram sockets - UDP and Unix domain M: unix @@ -128,10 +127,10 @@ packet-size receive-buffer set-global rot head ] if ; -TUPLE: receive-task ; +TUPLE: receive-task < input-task ; : ( stream continuation -- task ) - receive-task ; + receive-task ; M: receive-task do-io-task io-task-port @@ -148,19 +147,18 @@ M: receive-task do-io-task [ add-io-task ] with-port-continuation drop ; M: unix receive ( datagram -- packet addrspec ) - dup check-datagram-port - dup wait-receive - dup pending-error - dup datagram-port-packet - swap datagram-port-packet-addr ; + check-datagram-port + [ wait-receive ] + [ pending-error ] + [ [ packet>> ] [ packet-addr>> ] bi ] tri ; : do-send ( socket data sockaddr len -- n ) >r >r dup length 0 r> r> sendto ; -TUPLE: send-task packet sockaddr len ; +TUPLE: send-task < output-task packet sockaddr len ; : ( packet sockaddr len stream continuation -- task ) - send-task [ + send-task [ { set-send-task-packet set-send-task-sockaddr @@ -180,7 +178,7 @@ M: send-task do-io-task 2drop 2drop ; M: unix send ( packet addrspec datagram -- ) - 3dup check-datagram-send + check-datagram-send [ >r make-sockaddr/size r> wait-send ] keep pending-error ; diff --git a/extra/io/unix/unix-tests.factor b/extra/io/unix/unix-tests.factor index c8ed4fc41c..ff315bc529 100755 --- a/extra/io/unix/unix-tests.factor +++ b/extra/io/unix/unix-tests.factor @@ -11,7 +11,7 @@ IN: io.unix.tests socket-server ascii [ - accept [ + accept drop [ "Hello world" print flush readln "XYZ" = "FOO" "BAR" ? print flush ] with-stream diff --git a/extra/io/windows/nt/backend/backend.factor b/extra/io/windows/nt/backend/backend.factor index 822973b85b..fe7f1ecc61 100755 --- a/extra/io/windows/nt/backend/backend.factor +++ b/extra/io/windows/nt/backend/backend.factor @@ -3,7 +3,7 @@ continuations destructors io io.backend io.nonblocking io.windows libc kernel math namespaces sequences threads classes.tuple.lib windows windows.errors windows.kernel32 strings splitting io.files qualified ascii -combinators.lib system ; +combinators.lib system accessors ; QUALIFIED: windows.winsock IN: io.windows.nt.backend @@ -38,15 +38,15 @@ M: winnt add-completion ( handle -- ) zero? [ GetLastError { { [ dup expected-io-error? ] [ 2drop t ] } - { [ dup eof? ] [ drop t swap set-port-eof? f ] } - { [ t ] [ (win32-error-string) throw ] } + { [ dup eof? ] [ drop t >>eof drop f ] } + [ (win32-error-string) throw ] } cond ] [ drop t ] if ; : get-overlapped-result ( overlapped port -- bytes-transferred ) - dup port-handle win32-file-handle rot 0 + dup handle>> handle>> rot 0 [ 0 GetOverlappedResult overlapped-error? drop ] keep *uint ; : save-callback ( overlapped port -- ) @@ -75,11 +75,11 @@ M: winnt add-completion ( handle -- ) ] [ dup eof? [ drop lookup-callback - dup io-callback-port t swap set-port-eof? + dup port>> t >>eof drop ] [ (win32-error-string) swap lookup-callback - [ io-callback-port set-port-error ] keep - ] if io-callback-thread resume f + [ port>> set-port-error ] keep + ] if thread>> resume f ] if ] [ lookup-callback @@ -90,7 +90,7 @@ M: winnt add-completion ( handle -- ) handle-overlapped [ 0 drain-overlapped ] unless ; M: winnt cancel-io - port-handle win32-file-handle CancelIo drop ; + handle>> handle>> CancelIo drop ; M: winnt io-multiplex ( ms -- ) drain-overlapped ; diff --git a/extra/io/windows/nt/files/files.factor b/extra/io/windows/nt/files/files.factor index 3232ab6ff3..eec473e840 100755 --- a/extra/io/windows/nt/files/files.factor +++ b/extra/io/windows/nt/files/files.factor @@ -3,7 +3,7 @@ io.timeouts io.nonblocking io.windows io.windows.nt.backend kernel libc math threads windows windows.kernel32 system alien.c-types alien.arrays sequences combinators combinators.lib sequences.lib ascii splitting alien strings assocs namespaces -io.files.private ; +io.files.private accessors ; IN: io.windows.nt.files M: winnt cwd @@ -25,7 +25,7 @@ M: winnt root-directory? ( path -- ? ) { [ dup length 2 = ] [ dup second CHAR: : = ] } && nip ] [ t ] } - { [ t ] [ f ] } + [ f ] } cond nip ; ERROR: not-absolute-path ; @@ -64,7 +64,7 @@ M: winnt FileArgs-overlapped ( port -- overlapped ) dup pending-error tuck get-overlapped-result dup pick update-file-ptr - swap buffer-consume ; + swap buffer>> buffer-consume ; : (flush-output) ( port -- ) dup make-FileArgs @@ -73,7 +73,7 @@ M: winnt FileArgs-overlapped ( port -- overlapped ) >r FileArgs-lpOverlapped r> [ save-callback ] 2keep [ finish-flush ] keep - dup buffer-empty? [ drop ] [ (flush-output) ] if + dup buffer>> buffer-empty? [ drop ] [ (flush-output) ] if ] [ 2drop ] if ; @@ -82,14 +82,14 @@ M: winnt FileArgs-overlapped ( port -- overlapped ) [ [ (flush-output) ] with-timeout ] with-destructors ; M: port port-flush - dup buffer-empty? [ dup flush-output ] unless drop ; + dup buffer>> buffer-empty? [ dup flush-output ] unless drop ; : finish-read ( overlapped port -- ) dup pending-error tuck get-overlapped-result dup zero? [ - drop t swap set-port-eof? + drop t >>eof drop ] [ - dup pick n>buffer + dup pick buffer>> n>buffer swap update-file-ptr ] if ; diff --git a/extra/io/windows/nt/launcher/launcher.factor b/extra/io/windows/nt/launcher/launcher.factor index 97de248d24..f57902608f 100755 --- a/extra/io/windows/nt/launcher/launcher.factor +++ b/extra/io/windows/nt/launcher/launcher.factor @@ -55,7 +55,7 @@ IN: io.windows.nt.launcher { [ pick +inherit+ eq? ] [ redirect-inherit ] } { [ pick +closed+ eq? ] [ redirect-closed ] } { [ pick string? ] [ redirect-file ] } - { [ t ] [ redirect-stream ] } + [ redirect-stream ] } cond ; : default-stdout ( args -- handle ) diff --git a/extra/io/windows/nt/monitors/monitors.factor b/extra/io/windows/nt/monitors/monitors.factor index 164b529b61..7f3a13b281 100755 --- a/extra/io/windows/nt/monitors/monitors.factor +++ b/extra/io/windows/nt/monitors/monitors.factor @@ -1,11 +1,11 @@ ! Copyright (C) 2008 Doug Coleman, Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. -USING: alien.c-types destructors io.windows -io.windows.nt.backend kernel math windows windows.kernel32 -windows.types libc assocs alien namespaces continuations -io.monitors io.monitors.private io.nonblocking io.buffers -io.files io.timeouts io sequences hashtables sorting arrays -combinators math.bitfields strings system ; +USING: alien alien.c-types libc destructors locals +kernel math assocs namespaces continuations sequences hashtables +sorting arrays combinators math.bitfields strings system +io.windows io.windows.nt.backend io.monitors io.nonblocking +io.buffers io.files io.timeouts io accessors threads +windows windows.kernel32 windows.types ; IN: io.windows.nt.monitors : open-directory ( path -- handle ) @@ -21,67 +21,76 @@ IN: io.windows.nt.monitors dup add-completion f ; -TUPLE: win32-monitor path recursive? ; +TUPLE: win32-monitor-port < input-port recursive ; -: ( path recursive? port -- monitor ) - (monitor) { - set-win32-monitor-path - set-win32-monitor-recursive? - set-delegate - } win32-monitor construct ; +TUPLE: win32-monitor < monitor port ; -M: winnt ( path recursive? -- monitor ) - [ - over open-directory win32-monitor - - ] with-destructors ; - -: begin-reading-changes ( monitor -- overlapped ) - dup port-handle win32-file-handle - over buffer-ptr - pick buffer-size - roll win32-monitor-recursive? 1 0 ? +: begin-reading-changes ( port -- overlapped ) + { + [ handle>> handle>> ] + [ buffer>> buffer-ptr ] + [ buffer>> buffer-size ] + [ recursive>> 1 0 ? ] + } cleave FILE_NOTIFY_CHANGE_ALL 0 (make-overlapped) [ f ReadDirectoryChangesW win32-error=0/f ] keep ; -: read-changes ( monitor -- bytes ) +: read-changes ( port -- bytes ) [ [ dup begin-reading-changes swap [ save-callback ] 2keep - dup check-monitor ! we may have closed it... + check-closed ! we may have closed it... get-overlapped-result ] with-timeout ] with-destructors ; : parse-action ( action -- changed ) { - { [ dup FILE_ACTION_ADDED = ] [ +add-file+ ] } - { [ dup FILE_ACTION_REMOVED = ] [ +remove-file+ ] } - { [ dup FILE_ACTION_MODIFIED = ] [ +modify-file+ ] } - { [ dup FILE_ACTION_RENAMED_OLD_NAME = ] [ +rename-file+ ] } - { [ dup FILE_ACTION_RENAMED_NEW_NAME = ] [ +rename-file+ ] } - { [ t ] [ +modify-file+ ] } - } cond nip ; + { FILE_ACTION_ADDED [ +add-file+ ] } + { FILE_ACTION_REMOVED [ +remove-file+ ] } + { FILE_ACTION_MODIFIED [ +modify-file+ ] } + { FILE_ACTION_RENAMED_OLD_NAME [ +rename-file+ ] } + { FILE_ACTION_RENAMED_NEW_NAME [ +rename-file+ ] } + [ drop +modify-file+ ] + } case ; : memory>u16-string ( alien len -- string ) [ memory>byte-array ] keep 2/ c-ushort-array> >string ; -: parse-file-notify ( buffer -- changed path ) - { - FILE_NOTIFY_INFORMATION-FileName - FILE_NOTIFY_INFORMATION-FileNameLength - FILE_NOTIFY_INFORMATION-Action - } get-slots parse-action 1array -rot memory>u16-string ; +: parse-notify-record ( buffer -- changed path ) + [ FILE_NOTIFY_INFORMATION-Action parse-action ] + [ FILE_NOTIFY_INFORMATION-FileName ] + [ FILE_NOTIFY_INFORMATION-FileNameLength ] tri + memory>u16-string ; -: (changed-files) ( buffer -- ) - dup parse-file-notify changed-file - dup FILE_NOTIFY_INFORMATION-NextEntryOffset dup zero? - [ 2drop ] [ swap (changed-files) ] if ; +: file-notify-records ( buffer -- seq ) + [ dup FILE_NOTIFY_INFORMATION-NextEntryOffset 0 > ] + [ [ [ FILE_NOTIFY_INFORMATION-NextEntryOffset ] keep ] keep ] + [ ] unfold nip ; -M: win32-monitor fill-queue ( monitor -- ) - dup buffer-ptr over read-changes - [ zero? [ drop ] [ (changed-files) ] if ] H{ } make-assoc - swap set-monitor-queue ; +: parse-notify-records ( monitor buffer -- ) + file-notify-records + [ parse-notify-record rot queue-change ] with each ; + +: fill-queue ( monitor -- ) + dup port>> [ buffer>> buffer-ptr ] [ read-changes zero? ] bi + [ 2dup parse-notify-records ] unless 2drop ; + +: fill-queue-thread ( monitor -- ) + dup fill-queue fill-queue ; + +M:: winnt (monitor) ( path recursive? mailbox -- monitor ) + [ + path mailbox win32-monitor construct-monitor + path open-directory \ win32-monitor-port + recursive? >>recursive + >>port + dup [ fill-queue-thread ] curry + "Windows monitor thread" spawn drop + ] with-destructors ; + +M: win32-monitor dispose + port>> dispose ; diff --git a/extra/io/windows/nt/sockets/sockets.factor b/extra/io/windows/nt/sockets/sockets.factor index 36acaac992..a9d487dad7 100755 --- a/extra/io/windows/nt/sockets/sockets.factor +++ b/extra/io/windows/nt/sockets/sockets.factor @@ -2,7 +2,7 @@ USING: alien alien.accessors alien.c-types byte-arrays continuations destructors io.nonblocking io.timeouts io.sockets io.sockets.impl io namespaces io.streams.duplex io.windows io.windows.nt.backend windows.winsock kernel libc math sequences -threads classes.tuple.lib system ; +threads classes.tuple.lib system accessors ; IN: io.windows.nt.sockets : malloc-int ( object -- object ) @@ -122,7 +122,7 @@ TUPLE: AcceptEx-args port M: winnt (accept) ( server -- addrspec handle ) [ [ - dup check-server-port + check-server-port \ AcceptEx-args construct-empty [ init-accept ] keep [ ((accept)) ] keep @@ -159,7 +159,7 @@ TUPLE: WSARecvFrom-args port : init-WSARecvFrom ( datagram WSARecvFrom -- ) [ set-WSARecvFrom-args-port ] 2keep [ - >r delegate port-handle delegate win32-file-handle r> + >r handle>> handle>> r> set-WSARecvFrom-args-s* ] 2keep [ >r datagram-port-addr sockaddr-type heap-size r> @@ -192,7 +192,7 @@ TUPLE: WSARecvFrom-args port M: winnt receive ( datagram -- packet addrspec ) [ - dup check-datagram-port + check-datagram-port \ WSARecvFrom-args construct-empty [ init-WSARecvFrom ] keep [ call-WSARecvFrom ] keep @@ -244,7 +244,7 @@ USE: io.sockets M: winnt send ( packet addrspec datagram -- ) [ - 3dup check-datagram-send + check-datagram-send \ WSASendTo-args construct-empty [ init-WSASendTo ] keep [ call-WSASendTo ] keep diff --git a/extra/io/windows/windows.factor b/extra/io/windows/windows.factor index 3e0f4e9e86..d4e202013b 100755 --- a/extra/io/windows/windows.factor +++ b/extra/io/windows/windows.factor @@ -5,7 +5,7 @@ io.buffers io.files io.nonblocking io.sockets io.binary io.sockets.impl windows.errors strings io.streams.duplex kernel math namespaces sequences windows windows.kernel32 windows.shell32 windows.types windows.winsock splitting -continuations math.bitfields system ; +continuations math.bitfields system accessors ; IN: io.windows M: windows destruct-handle CloseHandle drop ; @@ -92,7 +92,7 @@ M: win32-file close-handle ( handle -- ) ] when drop ; : open-append ( path -- handle length ) - [ dup file-info file-info-size ] [ drop 0 ] recover + [ dup file-info size>> ] [ drop 0 ] recover >r (open-append) r> 2dup set-file-pointer ; TUPLE: FileArgs @@ -103,9 +103,9 @@ C: FileArgs : make-FileArgs ( port -- ) [ port-handle win32-file-handle ] keep - [ delegate ] keep + [ buffer>> ] keep [ - buffer-length + buffer>> buffer-length "DWORD" ] keep FileArgs-overlapped ; @@ -152,11 +152,10 @@ M: windows delete-directory ( path -- ) HOOK: WSASocket-flags io-backend ( -- DWORD ) -TUPLE: win32-socket ; +TUPLE: win32-socket < win32-file ; : ( handle -- win32-socket ) - f - \ win32-socket construct-delegate ; + f win32-file construct-boa ; : open-socket ( family type -- socket ) 0 f 0 WSASocket-flags WSASocket dup socket-error ; diff --git a/extra/koszul/koszul.factor b/extra/koszul/koszul.factor index add37173b7..e3c2997d0b 100755 --- a/extra/koszul/koszul.factor +++ b/extra/koszul/koszul.factor @@ -15,7 +15,7 @@ IN: koszul { [ dup number? ] [ { } associate ] } { [ dup array? ] [ 1 swap associate ] } { [ dup hashtable? ] [ ] } - { [ t ] [ 1array >alt ] } + [ 1array >alt ] } cond ; : canonicalize @@ -31,10 +31,10 @@ SYMBOL: terms ! Printing elements : num-alt. ( n -- str ) { - { [ dup 1 = ] [ drop " + " ] } - { [ dup -1 = ] [ drop " - " ] } - { [ t ] [ number>string " + " prepend ] } - } cond ; + { 1 [ " + " ] } + { -1 [ " - " ] } + [ number>string " + " prepend ] + } case ; : (alt.) ( basis n -- str ) over empty? [ diff --git a/extra/lazy-lists/lazy-lists.factor b/extra/lazy-lists/lazy-lists.factor index d13848498f..ebd2fe9f2e 100644 --- a/extra/lazy-lists/lazy-lists.factor +++ b/extra/lazy-lists/lazy-lists.factor @@ -321,7 +321,7 @@ M: sequence-cons nil? ( sequence-cons -- bool ) { { [ dup sequence? ] [ 0 swap seq>list ] } { [ dup list? ] [ ] } - { [ t ] [ "Could not convert object to a list" throw ] } + [ "Could not convert object to a list" throw ] } cond ; TUPLE: lazy-concat car cdr ; diff --git a/extra/logging/parser/parser.factor b/extra/logging/parser/parser.factor index 015861501e..c6b073e501 100755 --- a/extra/logging/parser/parser.factor +++ b/extra/logging/parser/parser.factor @@ -66,7 +66,7 @@ MEMO: 'log-line' ( -- parser ) parse-log-line { { [ dup malformed? ] [ malformed-line ] } { [ dup multiline? ] [ add-multiline ] } - { [ t ] [ , ] } + [ , ] } cond ] each ] { } make ; diff --git a/extra/logging/server/server.factor b/extra/logging/server/server.factor index bed6a2fec3..c6aee034cc 100755 --- a/extra/logging/server/server.factor +++ b/extra/logging/server/server.factor @@ -40,10 +40,10 @@ SYMBOL: log-files rot [ empty? not ] subset { { [ dup empty? ] [ 3drop ] } { [ dup length 1 = ] [ first -rot f (write-message) ] } - { [ t ] [ + [ [ first -rot f (write-message) ] 3keep 1 tail -rot [ t (write-message) ] 2curry each - ] } + ] } cond ; : (log-message) ( msg -- ) diff --git a/extra/match/match.factor b/extra/match/match.factor index 825d58c7c2..e559ebc60d 100755 --- a/extra/match/match.factor +++ b/extra/match/match.factor @@ -58,7 +58,7 @@ MACRO: match-cond ( assoc -- ) { [ dup match-var? ] [ get ] } { [ dup sequence? ] [ [ replace-patterns ] map ] } { [ dup tuple? ] [ tuple>array replace-patterns >tuple ] } - { [ t ] [ ] } + [ ] } cond ; : match-replace ( object pattern1 pattern2 -- result ) diff --git a/extra/math/functions/functions.factor b/extra/math/functions/functions.factor index 77c7d9247d..b3cfba8650 100755 --- a/extra/math/functions/functions.factor +++ b/extra/math/functions/functions.factor @@ -99,7 +99,7 @@ M: real absq sq ; { [ pick fp-nan? pick fp-nan? or ] [ 3drop f ] } { [ dup zero? ] [ drop number= ] } { [ dup 0 < ] [ ~rel ] } - { [ t ] [ ~abs ] } + [ ~abs ] } cond ; : power-of-2? ( n -- ? ) diff --git a/extra/math/miller-rabin/miller-rabin.factor b/extra/math/miller-rabin/miller-rabin.factor index ea7f02829d..c8a21512ec 100755 --- a/extra/math/miller-rabin/miller-rabin.factor +++ b/extra/math/miller-rabin/miller-rabin.factor @@ -55,7 +55,7 @@ TUPLE: miller-rabin-bounds ; { [ dup 1 <= ] [ 3drop f ] } { [ dup 2 = ] [ 3drop t ] } { [ dup even? ] [ 3drop f ] } - { [ t ] [ [ drop trials set t (miller-rabin) ] with-scope ] } + [ [ drop trials set t (miller-rabin) ] with-scope ] } cond ; : miller-rabin ( n -- ? ) 10 miller-rabin* ; diff --git a/extra/math/primes/primes.factor b/extra/math/primes/primes.factor index eeb1b66a89..edad69fffc 100644 --- a/extra/math/primes/primes.factor +++ b/extra/math/primes/primes.factor @@ -38,9 +38,8 @@ PRIVATE> { [ dup 2 < ] [ drop { } ] } { [ dup 1000003 < ] [ primes-under-million [ [ <=> ] binsearch 1+ 0 swap ] keep ] } - { [ t ] - [ primes-under-million 1000003 lprimes-from - rot [ <= ] curry lwhile list>array append ] } + [ primes-under-million 1000003 lprimes-from + rot [ <= ] curry lwhile list>array append ] } cond ; foldable : primes-between ( low high -- seq ) diff --git a/extra/multi-methods/multi-methods.factor b/extra/multi-methods/multi-methods.factor index 8f9e34b1fb..dd6fc7dfff 100755 --- a/extra/multi-methods/multi-methods.factor +++ b/extra/multi-methods/multi-methods.factor @@ -89,7 +89,7 @@ SYMBOL: total { [ 2dup [ class< ] 2keep swap class< and ] [ 0 ] } { [ 2dup class< ] [ -1 ] } { [ 2dup swap class< ] [ 1 ] } - { [ t ] [ 0 ] } + [ 0 ] } cond 2nip ] 2map [ zero? not ] find nip 0 or ; diff --git a/extra/odbc/odbc.factor b/extra/odbc/odbc.factor index ca97eab3bc..59f5095aad 100644 --- a/extra/odbc/odbc.factor +++ b/extra/odbc/odbc.factor @@ -1,270 +1,270 @@ -! Copyright (C) 2007 Chris Double. -! See http://factorcode.org/license.txt for BSD license. -USING: kernel alien alien.syntax combinators alien.c-types - strings sequences namespaces words math threads ; -IN: odbc - -"odbc" "odbc32.dll" "stdcall" add-library - -LIBRARY: odbc - -TYPEDEF: void* usb_dev_handle* -TYPEDEF: short SQLRETURN -TYPEDEF: short SQLSMALLINT -TYPEDEF: short* SQLSMALLINT* -TYPEDEF: ushort SQLUSMALLINT -TYPEDEF: uint* SQLUINTEGER* -TYPEDEF: int SQLINTEGER -TYPEDEF: char SQLCHAR -TYPEDEF: char* SQLCHAR* -TYPEDEF: void* SQLHANDLE -TYPEDEF: void* SQLHANDLE* -TYPEDEF: void* SQLHENV -TYPEDEF: void* SQLHDBC -TYPEDEF: void* SQLHSTMT -TYPEDEF: void* SQLHWND -TYPEDEF: void* SQLPOINTER - -: SQL-HANDLE-ENV ( -- number ) 1 ; inline -: SQL-HANDLE-DBC ( -- number ) 2 ; inline -: SQL-HANDLE-STMT ( -- number ) 3 ; inline -: SQL-HANDLE-DESC ( -- number ) 4 ; inline - -: SQL-NULL-HANDLE ( -- alien ) f ; inline - -: SQL-ATTR-ODBC-VERSION ( -- number ) 200 ; inline - -: SQL-OV-ODBC2 ( -- number ) 2 ; inline -: SQL-OV-ODBC3 ( -- number ) 3 ; inline - -: SQL-SUCCESS ( -- number ) 0 ; inline -: SQL-SUCCESS-WITH-INFO ( -- number ) 1 ; inline -: SQL-NO-DATA-FOUND ( -- number ) 100 ; inline - -: SQL-DRIVER-NOPROMPT ( -- number ) 0 ; inline -: SQL-DRIVER-PROMPT ( -- number ) 2 ; inline - -: SQL-C-DEFAULT ( -- number ) 99 ; inline - -SYMBOL: SQL-CHAR -SYMBOL: SQL-VARCHAR -SYMBOL: SQL-LONGVARCHAR -SYMBOL: SQL-WCHAR -SYMBOL: SQL-WCHARVAR -SYMBOL: SQL-WLONGCHARVAR -SYMBOL: SQL-DECIMAL -SYMBOL: SQL-SMALLINT -SYMBOL: SQL-NUMERIC -SYMBOL: SQL-INTEGER -SYMBOL: SQL-REAL -SYMBOL: SQL-FLOAT -SYMBOL: SQL-DOUBLE -SYMBOL: SQL-BIT -SYMBOL: SQL-TINYINT -SYMBOL: SQL-BIGINT -SYMBOL: SQL-BINARY -SYMBOL: SQL-VARBINARY -SYMBOL: SQL-LONGVARBINARY -SYMBOL: SQL-TYPE-DATE -SYMBOL: SQL-TYPE-TIME -SYMBOL: SQL-TYPE-TIMESTAMP -SYMBOL: SQL-TYPE-UTCDATETIME -SYMBOL: SQL-TYPE-UTCTIME -SYMBOL: SQL-INTERVAL-MONTH -SYMBOL: SQL-INTERVAL-YEAR -SYMBOL: SQL-INTERVAL-YEAR-TO-MONTH -SYMBOL: SQL-INTERVAL-DAY -SYMBOL: SQL-INTERVAL-HOUR -SYMBOL: SQL-INTERVAL-MINUTE -SYMBOL: SQL-INTERVAL-SECOND -SYMBOL: SQL-INTERVAL-DAY-TO-HOUR -SYMBOL: SQL-INTERVAL-DAY-TO-MINUTE -SYMBOL: SQL-INTERVAL-DAY-TO-SECOND -SYMBOL: SQL-INTERVAL-HOUR-TO-MINUTE -SYMBOL: SQL-INTERVAL-HOUR-TO-SECOND -SYMBOL: SQL-INTERVAL-MINUTE-TO-SECOND -SYMBOL: SQL-GUID -SYMBOL: SQL-TYPE-UNKNOWN - -: convert-sql-type ( number -- symbol ) - { - { [ dup 1 = ] [ drop SQL-CHAR ] } - { [ dup 12 = ] [ drop SQL-VARCHAR ] } - { [ dup -1 = ] [ drop SQL-LONGVARCHAR ] } - { [ dup -8 = ] [ drop SQL-WCHAR ] } - { [ dup -9 = ] [ drop SQL-WCHARVAR ] } - { [ dup -10 = ] [ drop SQL-WLONGCHARVAR ] } - { [ dup 3 = ] [ drop SQL-DECIMAL ] } - { [ dup 5 = ] [ drop SQL-SMALLINT ] } - { [ dup 2 = ] [ drop SQL-NUMERIC ] } - { [ dup 4 = ] [ drop SQL-INTEGER ] } - { [ dup 7 = ] [ drop SQL-REAL ] } - { [ dup 6 = ] [ drop SQL-FLOAT ] } - { [ dup 8 = ] [ drop SQL-DOUBLE ] } - { [ dup -7 = ] [ drop SQL-BIT ] } - { [ dup -6 = ] [ drop SQL-TINYINT ] } - { [ dup -5 = ] [ drop SQL-BIGINT ] } - { [ dup -2 = ] [ drop SQL-BINARY ] } - { [ dup -3 = ] [ drop SQL-VARBINARY ] } - { [ dup -4 = ] [ drop SQL-LONGVARBINARY ] } - { [ dup 91 = ] [ drop SQL-TYPE-DATE ] } - { [ dup 92 = ] [ drop SQL-TYPE-TIME ] } - { [ dup 93 = ] [ drop SQL-TYPE-TIMESTAMP ] } - { [ t ] [ drop SQL-TYPE-UNKNOWN ] } - } cond ; - -: succeeded? ( n -- bool ) - #! Did the call succeed (SQL-SUCCESS or SQL-SUCCESS-WITH-INFO) - { - { [ dup SQL-SUCCESS = ] [ drop t ] } - { [ dup SQL-SUCCESS-WITH-INFO = ] [ drop t ] } - { [ t ] [ drop f ] } - } cond ; - -FUNCTION: SQLRETURN SQLAllocHandle ( SQLSMALLINT handleType, SQLHANDLE inputHandle, SQLHANDLE* outputHandlePtr ) ; -FUNCTION: SQLRETURN SQLSetEnvAttr ( SQLHENV environmentHandle, SQLINTEGER attribute, SQLPOINTER valuePtr, SQLINTEGER stringLength ) ; -FUNCTION: SQLRETURN SQLDriverConnect ( SQLHDBC connectionHandle, SQLHWND windowHandle, SQLCHAR* inConnectionString, SQLSMALLINT stringLength, SQLCHAR* outConnectionString, SQLSMALLINT bufferLength, SQLSMALLINT* stringLength2Ptr, SQLUSMALLINT driverCompletion ) ; -FUNCTION: SQLRETURN SQLDisconnect ( SQLHDBC connectionHandle ) ; -FUNCTION: SQLRETURN SQLPrepare ( SQLHSTMT statementHandle, SQLCHAR* statementText, SQLINTEGER length ) ; -FUNCTION: SQLRETURN SQLExecute ( SQLHSTMT statementHandle ) ; -FUNCTION: SQLRETURN SQLFreeHandle ( SQLSMALLINT handleType, SQLHANDLE handle ) ; -FUNCTION: SQLRETURN SQLFetch ( SQLHSTMT statementHandle ) ; -FUNCTION: SQLRETURN SQLNumResultCols ( SQLHSTMT statementHandle, SQLSMALLINT* columnCountPtr ) ; -FUNCTION: SQLRETURN SQLDescribeCol ( SQLHSTMT statementHandle, SQLSMALLINT columnNumber, SQLCHAR* columnName, SQLSMALLINT bufferLength, SQLSMALLINT* nameLengthPtr, SQLSMALLINT* dataTypePtr, SQLUINTEGER* columnSizePtr, SQLSMALLINT* decimalDigitsPtr, SQLSMALLINT* nullablePtr ) ; -FUNCTION: SQLRETURN SQLGetData ( SQLHSTMT statementHandle, SQLUSMALLINT columnNumber, SQLSMALLINT targetType, SQLPOINTER targetValuePtr, SQLINTEGER bufferLength, SQLINTEGER* strlen_or_indPtr ) ; - -: alloc-handle ( type parent -- handle ) - f [ SQLAllocHandle ] keep swap succeeded? [ - *void* - ] [ - drop f - ] if ; - -: alloc-env-handle ( -- handle ) - SQL-HANDLE-ENV SQL-NULL-HANDLE alloc-handle ; - -: alloc-dbc-handle ( env -- handle ) - SQL-HANDLE-DBC swap alloc-handle ; - -: alloc-stmt-handle ( dbc -- handle ) - SQL-HANDLE-STMT swap alloc-handle ; - -: temp-string ( length -- byte-array length ) - [ CHAR: \space string>char-alien ] keep ; - -: odbc-init ( -- env ) - alloc-env-handle - [ - SQL-ATTR-ODBC-VERSION SQL-OV-ODBC3 0 SQLSetEnvAttr - succeeded? [ "odbc-init failed" throw ] unless - ] keep ; - -: odbc-connect ( env dsn -- dbc ) - >r alloc-dbc-handle dup r> - f swap dup length 1024 temp-string 0 SQL-DRIVER-NOPROMPT - SQLDriverConnect succeeded? [ "odbc-connect failed" throw ] unless ; - -: odbc-disconnect ( dbc -- ) - SQLDisconnect succeeded? [ "odbc-disconnect failed" throw ] unless ; - -: odbc-prepare ( dbc string -- statement ) - >r alloc-stmt-handle dup r> dup length SQLPrepare succeeded? [ "odbc-prepare failed" throw ] unless ; - -: odbc-free-statement ( statement -- ) - SQL-HANDLE-STMT swap SQLFreeHandle succeeded? [ "odbc-free-statement failed" throw ] unless ; - -: odbc-execute ( statement -- ) - SQLExecute succeeded? [ "odbc-execute failed" throw ] unless ; - -: odbc-next-row ( statement -- bool ) - SQLFetch succeeded? ; - -: odbc-number-of-columns ( statement -- number ) - 0 [ SQLNumResultCols succeeded? ] keep swap [ - *short - ] [ - drop f - ] if ; - -TUPLE: column nullable digits size type name number ; - -C: column - -: odbc-describe-column ( statement n -- column ) - dup >r - 1024 CHAR: \space string>char-alien dup >r - 1024 - 0 - 0 dup >r - 0 dup >r - 0 dup >r - 0 dup >r - SQLDescribeCol succeeded? [ - r> *short - r> *short - r> *uint - r> *short convert-sql-type - r> alien>char-string - r> - ] [ - r> drop r> drop r> drop r> drop r> drop r> drop - "odbc-describe-column failed" throw - ] if ; - -: dereference-type-pointer ( byte-array column -- object ) - column-type { - { [ dup SQL-CHAR = ] [ drop alien>char-string ] } - { [ dup SQL-VARCHAR = ] [ drop alien>char-string ] } - { [ dup SQL-LONGVARCHAR = ] [ drop alien>char-string ] } - { [ dup SQL-WCHAR = ] [ drop alien>char-string ] } - { [ dup SQL-WCHARVAR = ] [ drop alien>char-string ] } - { [ dup SQL-WLONGCHARVAR = ] [ drop alien>char-string ] } - { [ dup SQL-SMALLINT = ] [ drop *short ] } - { [ dup SQL-INTEGER = ] [ drop *long ] } - { [ dup SQL-REAL = ] [ drop *float ] } - { [ dup SQL-FLOAT = ] [ drop *double ] } - { [ dup SQL-DOUBLE = ] [ drop *double ] } - { [ dup SQL-TINYINT = ] [ drop *char ] } - { [ dup SQL-BIGINT = ] [ drop *longlong ] } - { [ t ] [ nip [ "Unknown SQL Type: " % word-name % ] "" make ] } - } cond ; - -TUPLE: field value column ; - -C: field - -: odbc-get-field ( statement column -- field ) - dup column? [ dupd odbc-describe-column ] unless dup >r column-number - SQL-C-DEFAULT - 8192 CHAR: \space string>char-alien dup >r - 8192 - f SQLGetData succeeded? [ - r> r> [ dereference-type-pointer ] keep - ] [ - r> drop r> [ - "SQLGetData Failed for Column: " % - dup column-name % - " of type: " % dup column-type word-name % - ] "" make swap - ] if ; - -: odbc-get-row-fields ( statement -- seq ) - [ - dup odbc-number-of-columns [ - 1+ odbc-get-field field-value , - ] with each - ] { } make ; - -: (odbc-get-all-rows) ( statement -- ) - dup odbc-next-row [ dup odbc-get-row-fields , yield (odbc-get-all-rows) ] [ drop ] if ; - -: odbc-get-all-rows ( statement -- seq ) - [ (odbc-get-all-rows) ] { } make ; - -: odbc-query ( string dsn -- result ) - odbc-init swap odbc-connect [ - swap odbc-prepare - dup odbc-execute - dup odbc-get-all-rows - swap odbc-free-statement - ] keep odbc-disconnect ; \ No newline at end of file +! Copyright (C) 2007 Chris Double. +! See http://factorcode.org/license.txt for BSD license. +USING: kernel alien alien.syntax combinators alien.c-types + strings sequences namespaces words math threads ; +IN: odbc + +"odbc" "odbc32.dll" "stdcall" add-library + +LIBRARY: odbc + +TYPEDEF: void* usb_dev_handle* +TYPEDEF: short SQLRETURN +TYPEDEF: short SQLSMALLINT +TYPEDEF: short* SQLSMALLINT* +TYPEDEF: ushort SQLUSMALLINT +TYPEDEF: uint* SQLUINTEGER* +TYPEDEF: int SQLINTEGER +TYPEDEF: char SQLCHAR +TYPEDEF: char* SQLCHAR* +TYPEDEF: void* SQLHANDLE +TYPEDEF: void* SQLHANDLE* +TYPEDEF: void* SQLHENV +TYPEDEF: void* SQLHDBC +TYPEDEF: void* SQLHSTMT +TYPEDEF: void* SQLHWND +TYPEDEF: void* SQLPOINTER + +: SQL-HANDLE-ENV ( -- number ) 1 ; inline +: SQL-HANDLE-DBC ( -- number ) 2 ; inline +: SQL-HANDLE-STMT ( -- number ) 3 ; inline +: SQL-HANDLE-DESC ( -- number ) 4 ; inline + +: SQL-NULL-HANDLE ( -- alien ) f ; inline + +: SQL-ATTR-ODBC-VERSION ( -- number ) 200 ; inline + +: SQL-OV-ODBC2 ( -- number ) 2 ; inline +: SQL-OV-ODBC3 ( -- number ) 3 ; inline + +: SQL-SUCCESS ( -- number ) 0 ; inline +: SQL-SUCCESS-WITH-INFO ( -- number ) 1 ; inline +: SQL-NO-DATA-FOUND ( -- number ) 100 ; inline + +: SQL-DRIVER-NOPROMPT ( -- number ) 0 ; inline +: SQL-DRIVER-PROMPT ( -- number ) 2 ; inline + +: SQL-C-DEFAULT ( -- number ) 99 ; inline + +SYMBOL: SQL-CHAR +SYMBOL: SQL-VARCHAR +SYMBOL: SQL-LONGVARCHAR +SYMBOL: SQL-WCHAR +SYMBOL: SQL-WCHARVAR +SYMBOL: SQL-WLONGCHARVAR +SYMBOL: SQL-DECIMAL +SYMBOL: SQL-SMALLINT +SYMBOL: SQL-NUMERIC +SYMBOL: SQL-INTEGER +SYMBOL: SQL-REAL +SYMBOL: SQL-FLOAT +SYMBOL: SQL-DOUBLE +SYMBOL: SQL-BIT +SYMBOL: SQL-TINYINT +SYMBOL: SQL-BIGINT +SYMBOL: SQL-BINARY +SYMBOL: SQL-VARBINARY +SYMBOL: SQL-LONGVARBINARY +SYMBOL: SQL-TYPE-DATE +SYMBOL: SQL-TYPE-TIME +SYMBOL: SQL-TYPE-TIMESTAMP +SYMBOL: SQL-TYPE-UTCDATETIME +SYMBOL: SQL-TYPE-UTCTIME +SYMBOL: SQL-INTERVAL-MONTH +SYMBOL: SQL-INTERVAL-YEAR +SYMBOL: SQL-INTERVAL-YEAR-TO-MONTH +SYMBOL: SQL-INTERVAL-DAY +SYMBOL: SQL-INTERVAL-HOUR +SYMBOL: SQL-INTERVAL-MINUTE +SYMBOL: SQL-INTERVAL-SECOND +SYMBOL: SQL-INTERVAL-DAY-TO-HOUR +SYMBOL: SQL-INTERVAL-DAY-TO-MINUTE +SYMBOL: SQL-INTERVAL-DAY-TO-SECOND +SYMBOL: SQL-INTERVAL-HOUR-TO-MINUTE +SYMBOL: SQL-INTERVAL-HOUR-TO-SECOND +SYMBOL: SQL-INTERVAL-MINUTE-TO-SECOND +SYMBOL: SQL-GUID +SYMBOL: SQL-TYPE-UNKNOWN + +: convert-sql-type ( number -- symbol ) + { + { 1 [ SQL-CHAR ] } + { 12 [ SQL-VARCHAR ] } + { -1 [ SQL-LONGVARCHAR ] } + { -8 [ SQL-WCHAR ] } + { -9 [ SQL-WCHARVAR ] } + { -10 [ SQL-WLONGCHARVAR ] } + { 3 [ SQL-DECIMAL ] } + { 5 [ SQL-SMALLINT ] } + { 2 [ SQL-NUMERIC ] } + { 4 [ SQL-INTEGER ] } + { 7 [ SQL-REAL ] } + { 6 [ SQL-FLOAT ] } + { 8 [ SQL-DOUBLE ] } + { -7 [ SQL-BIT ] } + { -6 [ SQL-TINYINT ] } + { -5 [ SQL-BIGINT ] } + { -2 [ SQL-BINARY ] } + { -3 [ SQL-VARBINARY ] } + { -4 [ SQL-LONGVARBINARY ] } + { 91 [ SQL-TYPE-DATE ] } + { 92 [ SQL-TYPE-TIME ] } + { 93 [ SQL-TYPE-TIMESTAMP ] } + [ drop SQL-TYPE-UNKNOWN ] + } case ; + +: succeeded? ( n -- bool ) + #! Did the call succeed (SQL-SUCCESS or SQL-SUCCESS-WITH-INFO) + { + { SQL-SUCCESS [ t ] } + { SQL-SUCCESS-WITH-INFO [ t ] } + [ drop f ] + } case ; + +FUNCTION: SQLRETURN SQLAllocHandle ( SQLSMALLINT handleType, SQLHANDLE inputHandle, SQLHANDLE* outputHandlePtr ) ; +FUNCTION: SQLRETURN SQLSetEnvAttr ( SQLHENV environmentHandle, SQLINTEGER attribute, SQLPOINTER valuePtr, SQLINTEGER stringLength ) ; +FUNCTION: SQLRETURN SQLDriverConnect ( SQLHDBC connectionHandle, SQLHWND windowHandle, SQLCHAR* inConnectionString, SQLSMALLINT stringLength, SQLCHAR* outConnectionString, SQLSMALLINT bufferLength, SQLSMALLINT* stringLength2Ptr, SQLUSMALLINT driverCompletion ) ; +FUNCTION: SQLRETURN SQLDisconnect ( SQLHDBC connectionHandle ) ; +FUNCTION: SQLRETURN SQLPrepare ( SQLHSTMT statementHandle, SQLCHAR* statementText, SQLINTEGER length ) ; +FUNCTION: SQLRETURN SQLExecute ( SQLHSTMT statementHandle ) ; +FUNCTION: SQLRETURN SQLFreeHandle ( SQLSMALLINT handleType, SQLHANDLE handle ) ; +FUNCTION: SQLRETURN SQLFetch ( SQLHSTMT statementHandle ) ; +FUNCTION: SQLRETURN SQLNumResultCols ( SQLHSTMT statementHandle, SQLSMALLINT* columnCountPtr ) ; +FUNCTION: SQLRETURN SQLDescribeCol ( SQLHSTMT statementHandle, SQLSMALLINT columnNumber, SQLCHAR* columnName, SQLSMALLINT bufferLength, SQLSMALLINT* nameLengthPtr, SQLSMALLINT* dataTypePtr, SQLUINTEGER* columnSizePtr, SQLSMALLINT* decimalDigitsPtr, SQLSMALLINT* nullablePtr ) ; +FUNCTION: SQLRETURN SQLGetData ( SQLHSTMT statementHandle, SQLUSMALLINT columnNumber, SQLSMALLINT targetType, SQLPOINTER targetValuePtr, SQLINTEGER bufferLength, SQLINTEGER* strlen_or_indPtr ) ; + +: alloc-handle ( type parent -- handle ) + f [ SQLAllocHandle ] keep swap succeeded? [ + *void* + ] [ + drop f + ] if ; + +: alloc-env-handle ( -- handle ) + SQL-HANDLE-ENV SQL-NULL-HANDLE alloc-handle ; + +: alloc-dbc-handle ( env -- handle ) + SQL-HANDLE-DBC swap alloc-handle ; + +: alloc-stmt-handle ( dbc -- handle ) + SQL-HANDLE-STMT swap alloc-handle ; + +: temp-string ( length -- byte-array length ) + [ CHAR: \space string>char-alien ] keep ; + +: odbc-init ( -- env ) + alloc-env-handle + [ + SQL-ATTR-ODBC-VERSION SQL-OV-ODBC3 0 SQLSetEnvAttr + succeeded? [ "odbc-init failed" throw ] unless + ] keep ; + +: odbc-connect ( env dsn -- dbc ) + >r alloc-dbc-handle dup r> + f swap dup length 1024 temp-string 0 SQL-DRIVER-NOPROMPT + SQLDriverConnect succeeded? [ "odbc-connect failed" throw ] unless ; + +: odbc-disconnect ( dbc -- ) + SQLDisconnect succeeded? [ "odbc-disconnect failed" throw ] unless ; + +: odbc-prepare ( dbc string -- statement ) + >r alloc-stmt-handle dup r> dup length SQLPrepare succeeded? [ "odbc-prepare failed" throw ] unless ; + +: odbc-free-statement ( statement -- ) + SQL-HANDLE-STMT swap SQLFreeHandle succeeded? [ "odbc-free-statement failed" throw ] unless ; + +: odbc-execute ( statement -- ) + SQLExecute succeeded? [ "odbc-execute failed" throw ] unless ; + +: odbc-next-row ( statement -- bool ) + SQLFetch succeeded? ; + +: odbc-number-of-columns ( statement -- number ) + 0 [ SQLNumResultCols succeeded? ] keep swap [ + *short + ] [ + drop f + ] if ; + +TUPLE: column nullable digits size type name number ; + +C: column + +: odbc-describe-column ( statement n -- column ) + dup >r + 1024 CHAR: \space string>char-alien dup >r + 1024 + 0 + 0 dup >r + 0 dup >r + 0 dup >r + 0 dup >r + SQLDescribeCol succeeded? [ + r> *short + r> *short + r> *uint + r> *short convert-sql-type + r> alien>char-string + r> + ] [ + r> drop r> drop r> drop r> drop r> drop r> drop + "odbc-describe-column failed" throw + ] if ; + +: dereference-type-pointer ( byte-array column -- object ) + column-type { + { SQL-CHAR [ alien>char-string ] } + { SQL-VARCHAR [ alien>char-string ] } + { SQL-LONGVARCHAR [ alien>char-string ] } + { SQL-WCHAR [ alien>char-string ] } + { SQL-WCHARVAR [ alien>char-string ] } + { SQL-WLONGCHARVAR [ alien>char-string ] } + { SQL-SMALLINT [ *short ] } + { SQL-INTEGER [ *long ] } + { SQL-REAL [ *float ] } + { SQL-FLOAT [ *double ] } + { SQL-DOUBLE [ *double ] } + { SQL-TINYINT [ *char ] } + { SQL-BIGINT [ *longlong ] } + [ nip [ "Unknown SQL Type: " % word-name % ] "" make ] + } case ; + +TUPLE: field value column ; + +C: field + +: odbc-get-field ( statement column -- field ) + dup column? [ dupd odbc-describe-column ] unless dup >r column-number + SQL-C-DEFAULT + 8192 CHAR: \space string>char-alien dup >r + 8192 + f SQLGetData succeeded? [ + r> r> [ dereference-type-pointer ] keep + ] [ + r> drop r> [ + "SQLGetData Failed for Column: " % + dup column-name % + " of type: " % dup column-type word-name % + ] "" make swap + ] if ; + +: odbc-get-row-fields ( statement -- seq ) + [ + dup odbc-number-of-columns [ + 1+ odbc-get-field field-value , + ] with each + ] { } make ; + +: (odbc-get-all-rows) ( statement -- ) + dup odbc-next-row [ dup odbc-get-row-fields , yield (odbc-get-all-rows) ] [ drop ] if ; + +: odbc-get-all-rows ( statement -- seq ) + [ (odbc-get-all-rows) ] { } make ; + +: odbc-query ( string dsn -- result ) + odbc-init swap odbc-connect [ + swap odbc-prepare + dup odbc-execute + dup odbc-get-all-rows + swap odbc-free-statement + ] keep odbc-disconnect ; diff --git a/extra/ogg/player/player.factor b/extra/ogg/player/player.factor index 2a685eccd1..d4ad11311f 100755 --- a/extra/ogg/player/player.factor +++ b/extra/ogg/player/player.factor @@ -179,7 +179,7 @@ HINTS: yuv>rgb byte-array byte-array ; num-audio-buffers-processed { { [ over player-buffers length 1 = over zero? and ] [ drop append-new-audio-buffer t ] } { [ over player-buffers length 2 = over zero? and ] [ yield drop f ] } - { [ t ] [ fill-processed-audio-buffer t ] } + [ fill-processed-audio-buffer t ] } cond ; : start-audio ( player -- player bool ) @@ -284,7 +284,7 @@ HINTS: yuv>rgb byte-array byte-array ; decode-packet { { [ is-vorbis-packet? ] [ handle-initial-vorbis-header ] } { [ is-theora-packet? ] [ handle-initial-theora-header ] } - { [ t ] [ handle-initial-unknown-header ] } + [ handle-initial-unknown-header ] } cond t ] [ f diff --git a/extra/opengl/gl/extensions/extensions.factor b/extra/opengl/gl/extensions/extensions.factor index 20929fb410..739ad203a1 100644 --- a/extra/opengl/gl/extensions/extensions.factor +++ b/extra/opengl/gl/extensions/extensions.factor @@ -8,7 +8,7 @@ ERROR: unknown-gl-platform ; { [ os windows? ] [ "opengl.gl.windows" ] } { [ os macosx? ] [ "opengl.gl.macosx" ] } { [ os unix? ] [ "opengl.gl.unix" ] } - { [ t ] [ unknown-gl-platform ] } + [ unknown-gl-platform ] } cond use+ >> SYMBOL: +gl-function-number-counter+ diff --git a/extra/optimizer/debugger/debugger.factor b/extra/optimizer/debugger/debugger.factor index 1f5453798d..a726095eb1 100755 --- a/extra/optimizer/debugger/debugger.factor +++ b/extra/optimizer/debugger/debugger.factor @@ -149,7 +149,7 @@ SYMBOL: node-count { [ dup "intrinsics" word-prop over "if-intrinsics" word-prop or ] [ intrinsics-called ] } { [ dup generic? ] [ generics-called ] } { [ dup method-body? ] [ methods-called ] } - { [ t ] [ words-called ] } + [ words-called ] } cond 1 -rot get at+ ] [ drop diff --git a/extra/oracle/oracle.factor b/extra/oracle/oracle.factor index a30ce64854..44b746f8ce 100644 --- a/extra/oracle/oracle.factor +++ b/extra/oracle/oracle.factor @@ -35,20 +35,20 @@ C: connection : check-result ( result -- ) { - { [ dup OCI_SUCCESS = ] [ drop ] } - { [ dup OCI_ERROR = ] [ err get get-oci-error ] } - { [ dup OCI_INVALID_HANDLE = ] [ "invalid handle" throw ] } - { [ t ] [ "operation failed" throw ] } - } cond ; + { OCI_SUCCESS [ ] } + { OCI_ERROR [ err get get-oci-error ] } + { OCI_INVALID_HANDLE [ "invalid handle" throw ] } + [ "operation failed" throw ] + } case ; : check-status ( status -- bool ) { - { [ dup OCI_SUCCESS = ] [ drop t ] } - { [ dup OCI_ERROR = ] [ err get get-oci-error ] } - { [ dup OCI_INVALID_HANDLE = ] [ "invalid handle" throw ] } - { [ dup OCI_NO_DATA = ] [ drop f ] } - { [ t ] [ "operation failed" throw ] } - } cond ; + { OCI_SUCCESS [ t ] } + { OCI_ERROR [ err get get-oci-error ] } + { OCI_INVALID_HANDLE [ "invalid handle" throw ] } + { OCI_NO_DATA [ f ] } + [ "operation failed" throw ] + } case ; ! ========================================================= ! Initialization and handle-allocation routines @@ -153,19 +153,19 @@ C: connection >r stm get err get r> dup length swap malloc-char-string swap OCI_NTV_SYNTAX OCI_DEFAULT OCIStmtPrepare check-result ; -: calculate-size ( type -- size object ) +: calculate-size ( type -- size ) { - { [ dup SQLT_INT = ] [ "int" heap-size ] } - { [ dup SQLT_FLT = ] [ "float" heap-size ] } - { [ dup SQLT_CHR = ] [ "char" heap-size ] } - { [ dup SQLT_NUM = ] [ "int" heap-size 10 * ] } - { [ dup SQLT_STR = ] [ 64 ] } - { [ dup SQLT_ODT = ] [ 256 ] } - } cond ; + { SQLT_INT [ "int" heap-size ] } + { SQLT_FLT [ "float" heap-size ] } + { SQLT_CHR [ "char" heap-size ] } + { SQLT_NUM [ "int" heap-size 10 * ] } + { SQLT_STR [ 64 ] } + { SQLT_ODT [ 256 ] } + } case ; : define-by-position ( position type -- ) >r >r stm get f err get - r> r> calculate-size swap >r [ "char" malloc-array dup buf set ] keep 1+ + r> r> dup calculate-size >r [ "char" malloc-array dup buf set ] keep 1+ r> f f f OCI_DEFAULT OCIDefineByPos check-result ; : execute-statement ( -- bool ) diff --git a/extra/porter-stemmer/porter-stemmer.factor b/extra/porter-stemmer/porter-stemmer.factor index fec3163e2f..81820e0152 100644 --- a/extra/porter-stemmer/porter-stemmer.factor +++ b/extra/porter-stemmer/porter-stemmer.factor @@ -60,7 +60,7 @@ USING: kernel math parser sequences combinators splitting ; { [ 1 over consonant-end? not ] [ drop f ] } { [ 2 over consonant-end? ] [ drop f ] } { [ 3 over consonant-end? not ] [ drop f ] } - { [ t ] [ "wxy" last-is? not ] } + [ "wxy" last-is? not ] } cond ; : r ( str oldsuffix newsuffix -- str ) @@ -75,7 +75,7 @@ USING: kernel math parser sequences combinators splitting ; { [ "ies" ?tail ] [ "i" append ] } { [ dup "ss" tail? ] [ ] } { [ "s" ?tail ] [ ] } - { [ t ] [ ] } + [ ] } cond ] when ; @@ -114,11 +114,11 @@ USING: kernel math parser sequences combinators splitting ; { { [ "ed" ?tail ] [ -ed ] } { [ "ing" ?tail ] [ -ing ] } - { [ t ] [ f ] } + [ f ] } cond ] [ -ed/ing ] } - { [ t ] [ ] } + [ ] } cond ; : step1c ( str -- newstr ) @@ -149,7 +149,7 @@ USING: kernel math parser sequences combinators splitting ; { [ "iviti" ?tail ] [ "iviti" "ive" r ] } { [ "biliti" ?tail ] [ "biliti" "ble" r ] } { [ "logi" ?tail ] [ "logi" "log" r ] } - { [ t ] [ ] } + [ ] } cond ; : step3 ( str -- newstr ) @@ -161,7 +161,7 @@ USING: kernel math parser sequences combinators splitting ; { [ "ical" ?tail ] [ "ical" "ic" r ] } { [ "ful" ?tail ] [ "ful" "" r ] } { [ "ness" ?tail ] [ "ness" "" r ] } - { [ t ] [ ] } + [ ] } cond ; : -ion ( str -- newstr ) @@ -192,7 +192,7 @@ USING: kernel math parser sequences combinators splitting ; { [ "ous" ?tail ] [ ] } { [ "ive" ?tail ] [ ] } { [ "ize" ?tail ] [ ] } - { [ t ] [ ] } + [ ] } cond dup consonant-seq 1 > [ nip ] [ drop ] if ; : remove-e? ( str -- ? ) @@ -210,7 +210,7 @@ USING: kernel math parser sequences combinators splitting ; { [ dup peek CHAR: l = not ] [ ] } { [ dup length 1- over double-consonant? not ] [ ] } { [ dup consonant-seq 1 > ] [ butlast ] } - { [ t ] [ ] } + [ ] } cond ; : step5 ( str -- newstr ) remove-e ll->l ; diff --git a/extra/project-euler/169/169.factor b/extra/project-euler/169/169.factor index 90655149dc..973e50748c 100644 --- a/extra/project-euler/169/169.factor +++ b/extra/project-euler/169/169.factor @@ -30,7 +30,7 @@ MEMO: fn ( n -- x ) { { [ dup 2 < ] [ drop 1 ] } { [ dup odd? ] [ 2/ fn ] } - { [ t ] [ 2/ [ fn ] [ 1- fn + ] bi + ] } + [ 2/ [ fn ] [ 1- fn + ] bi + ] } cond ; : euler169 ( -- result ) diff --git a/extra/project-euler/175/175.factor b/extra/project-euler/175/175.factor index e6b4acc8c0..853bf9a10f 100644 --- a/extra/project-euler/175/175.factor +++ b/extra/project-euler/175/175.factor @@ -44,7 +44,7 @@ IN: project-euler.175 { { [ dup integer? ] [ 1- 0 add-bits ] } { [ dup 1 < ] [ 1 over - / dupd compute 1 1 add-bits ] } - { [ t ] [ [ 1 mod compute ] 2keep >integer 0 add-bits ] } + [ [ 1 mod compute ] 2keep >integer 0 add-bits ] } cond ; PRIVATE> diff --git a/extra/reports/noise/noise.factor b/extra/reports/noise/noise.factor index 6921d1223a..c3b7311714 100755 --- a/extra/reports/noise/noise.factor +++ b/extra/reports/noise/noise.factor @@ -113,7 +113,7 @@ M: array noise [ noise ] map vsum ; noise first2 { { [ over 4 <= ] [ >r drop 0 r> ] } { [ over 15 >= ] [ >r 2 * r> ] } - { [ t ] [ ] } + [ ] } cond { ! short words are easier to read @@ -123,7 +123,7 @@ M: array noise [ noise ] map vsum ; { [ dup 25 >= ] [ >r 2 * r> 20 max ] } { [ dup 20 >= ] [ >r 5/3 * r> ] } { [ dup 15 >= ] [ >r 3/2 * r> ] } - { [ t ] [ ] } + [ ] } cond noise-factor ; GENERIC: word-noise-factor ( word -- factor ) diff --git a/extra/rot13/rot13.factor b/extra/rot13/rot13.factor index bf5105f334..6663381522 100644 --- a/extra/rot13/rot13.factor +++ b/extra/rot13/rot13.factor @@ -9,7 +9,7 @@ IN: rot13 { { [ dup letter? ] [ CHAR: a rotate ] } { [ dup LETTER? ] [ CHAR: A rotate ] } - { [ t ] [ ] } + [ ] } cond ; : rot13 ( string -- string ) [ rot-letter ] map ; diff --git a/extra/serialize/serialize.factor b/extra/serialize/serialize.factor index 7a2fbfae9e..280ce3b43e 100755 --- a/extra/serialize/serialize.factor +++ b/extra/serialize/serialize.factor @@ -65,7 +65,7 @@ GENERIC: (serialize) ( obj -- ) read1 { { [ dup HEX: ff = ] [ drop deserialize-cell read be> ] } { [ dup HEX: 80 >= ] [ HEX: 80 bitxor ] } - { [ t ] [ read be> ] } + [ read be> ] } cond ; : serialize-shared ( obj quot -- ) @@ -183,7 +183,7 @@ M: word (serialize) ( obj -- ) { { [ dup t eq? ] [ serialize-true ] } { [ dup word-vocabulary not ] [ serialize-gensym ] } - { [ t ] [ serialize-word ] } + [ serialize-word ] } cond ; M: wrapper (serialize) ( obj -- ) diff --git a/extra/smtp/server/server.factor b/extra/smtp/server/server.factor index 14957ceca2..737a887f9f 100755 --- a/extra/smtp/server/server.factor +++ b/extra/smtp/server/server.factor @@ -56,15 +56,15 @@ SYMBOL: data-mode "220 OK\r\n" write flush t ] } { [ data-mode get ] [ dup global [ print ] bind t ] } - { [ t ] [ + [ "500 ERROR\r\n" write flush t - ] } + ] } cond nip [ process ] when ; : mock-smtp-server ( port -- ) "Starting SMTP server on port " write dup . flush "127.0.0.1" swap ascii [ - accept [ + accept drop [ 1 minutes stdio get set-timeout "220 hello\r\n" write flush process diff --git a/extra/smtp/smtp.factor b/extra/smtp/smtp.factor index ee2b021329..844857d1db 100755 --- a/extra/smtp/smtp.factor +++ b/extra/smtp/smtp.factor @@ -70,7 +70,7 @@ LOG: smtp-response DEBUG { [ dup "50" head? ] [ smtp-response "syntax error" throw ] } { [ dup "53" head? ] [ smtp-response "invalid authentication data" throw ] } { [ dup "55" head? ] [ smtp-response "fatal error" throw ] } - { [ t ] [ "unknown error" throw ] } + [ "unknown error" throw ] } cond ; : multiline? ( response -- boolean ) diff --git a/extra/space-invaders/space-invaders.factor b/extra/space-invaders/space-invaders.factor index d66ffdc66e..200257b31c 100755 --- a/extra/space-invaders/space-invaders.factor +++ b/extra/space-invaders/space-invaders.factor @@ -306,7 +306,7 @@ M: invaders-gadget draw-gadget* ( gadget -- ) { [ dup 184 238 within pick 0 223 within and ] [ 2drop green ] } { [ dup 240 247 within pick 16 133 within and ] [ 2drop green ] } { [ dup 247 215 - 247 184 - within pick 0 223 within and ] [ 2drop red ] } - { [ t ] [ 2drop white ] } + [ 2drop white ] } cond ; : plot-bitmap-bits ( bitmap point byte bit -- ) diff --git a/extra/sudoku/sudoku.factor b/extra/sudoku/sudoku.factor index 764c4d92f0..b0ba85c97f 100644 --- a/extra/sudoku/sudoku.factor +++ b/extra/sudoku/sudoku.factor @@ -32,7 +32,7 @@ DEFER: search { [ 3dup nip row-contains? ] [ 3drop ] } { [ 3dup drop col-contains? ] [ 3drop ] } { [ 3dup box-contains? ] [ 3drop ] } - { [ t ] [ assume ] } + [ assume ] } cond ; : solve ( x y -- ) 9 [ 1+ 2over attempt ] each 2drop ; @@ -62,7 +62,7 @@ DEFER: search { [ over 9 = ] [ >r drop 0 r> 1+ search ] } { [ over 0 = over 9 = and ] [ 2drop solution. ] } { [ 2dup board> ] [ >r 1+ r> search ] } - { [ t ] [ solve ] } + [ solve ] } cond ; : sudoku ( board -- ) diff --git a/extra/tar/tar.factor b/extra/tar/tar.factor index 99af06b80f..038078969d 100755 --- a/extra/tar/tar.factor +++ b/extra/tar/tar.factor @@ -1,7 +1,7 @@ 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 ; +hexdump io.encodings.binary inspector accessors ; IN: tar : zero-checksum 256 ; @@ -79,87 +79,67 @@ SYMBOL: filename ] keep ] if ; -TUPLE: unknown-typeflag str ; -: ( ch -- obj ) - 1string \ unknown-typeflag construct-boa ; - -TUPLE: unimplemented-typeflag header ; -: ( header -- obj ) - global [ "Unimplemented typeflag: " print dup . flush ] bind - tar-header-typeflag - 1string \ unimplemented-typeflag construct-boa ; +ERROR: unknown-typeflag ch ; +M: unknown-typeflag summary ( obj -- str ) + ch>> 1string + "Unknown typeflag: " prepend ; : tar-append-path ( path -- newpath ) base-dir get prepend-path ; ! Normal file : typeflag-0 - tar-header-name tar-append-path binary + name>> tar-append-path binary [ read-data-blocks ] keep dispose ; ! Hard link -: typeflag-1 ( header -- ) - throw ; +: typeflag-1 ( header -- ) unknown-typeflag ; ! Symlink -: typeflag-2 ( header -- ) - throw ; +: typeflag-2 ( header -- ) unknown-typeflag ; ! character special -: typeflag-3 ( header -- ) - throw ; +: typeflag-3 ( header -- ) unknown-typeflag ; ! Block special -: typeflag-4 ( header -- ) - throw ; +: typeflag-4 ( header -- ) unknown-typeflag ; ! Directory : typeflag-5 ( header -- ) tar-header-name tar-append-path make-directories ; ! FIFO -: typeflag-6 ( header -- ) - throw ; +: typeflag-6 ( header -- ) unknown-typeflag ; ! Contiguous file -: typeflag-7 ( header -- ) - throw ; +: typeflag-7 ( header -- ) unknown-typeflag ; ! Global extended header -: typeflag-8 ( header -- ) - throw ; +: typeflag-8 ( header -- ) unknown-typeflag ; ! Extended header -: typeflag-9 ( header -- ) - throw ; +: typeflag-9 ( header -- ) unknown-typeflag ; ! Global POSIX header -: typeflag-g ( header -- ) - throw ; +: typeflag-g ( header -- ) unknown-typeflag ; ! Extended POSIX header -: typeflag-x ( header -- ) - throw ; +: typeflag-x ( header -- ) unknown-typeflag ; ! Solaris access control list -: typeflag-A ( header -- ) - throw ; +: typeflag-A ( header -- ) unknown-typeflag ; ! GNU dumpdir -: typeflag-D ( header -- ) - throw ; +: typeflag-D ( header -- ) unknown-typeflag ; ! Solaris extended attribute file -: typeflag-E ( header -- ) - throw ; +: typeflag-E ( header -- ) unknown-typeflag ; ! Inode metadata -: typeflag-I ( header -- ) - throw ; +: typeflag-I ( header -- ) unknown-typeflag ; ! Long link name -: typeflag-K ( header -- ) - throw ; +: typeflag-K ( header -- ) unknown-typeflag ; ! Long file name : typeflag-L ( header -- ) @@ -169,24 +149,19 @@ TUPLE: unimplemented-typeflag header ; filename get tar-append-path make-directories ; ! Multi volume continuation entry -: typeflag-M ( header -- ) - throw ; +: typeflag-M ( header -- ) unknown-typeflag ; ! GNU long file name -: typeflag-N ( header -- ) - throw ; +: typeflag-N ( header -- ) unknown-typeflag ; ! Sparse file -: typeflag-S ( header -- ) - throw ; +: typeflag-S ( header -- ) unknown-typeflag ; ! Volume header -: typeflag-V ( header -- ) - throw ; +: typeflag-V ( header -- ) unknown-typeflag ; ! Vendor extended header type -: typeflag-X ( header -- ) - throw ; +: typeflag-X ( header -- ) unknown-typeflag ; : (parse-tar) ( -- ) 512 read @@ -218,7 +193,7 @@ TUPLE: unimplemented-typeflag header ; { CHAR: S [ typeflag-S ] } { CHAR: V [ typeflag-V ] } { CHAR: X [ typeflag-X ] } - [ throw ] + [ unknown-typeflag ] } case ! dup tar-header-size zero? [ ! out-stream get [ dispose ] when @@ -237,7 +212,7 @@ TUPLE: unimplemented-typeflag header ; : parse-tar ( path -- obj ) binary [ - "tar-test" resource-path base-dir set + "resource:tar-test" base-dir set global [ nl nl nl "Starting to parse .tar..." print flush ] bind global [ "Expanding to: " write base-dir get . flush ] bind (parse-tar) diff --git a/extra/tools/completion/completion.factor b/extra/tools/completion/completion.factor index 16bde2100f..b9c37c0656 100755 --- a/extra/tools/completion/completion.factor +++ b/extra/tools/completion/completion.factor @@ -35,7 +35,7 @@ unicode.categories ; { [ 2dup length 1- number= ] [ 2drop 4 ] } { [ 2dup >r 1- r> nth Letter? not ] [ 2drop 10 ] } { [ 2dup >r 1+ r> nth Letter? not ] [ 2drop 4 ] } - { [ t ] [ 2drop 1 ] } + [ 2drop 1 ] } cond ; : score ( full fuzzy -- n ) diff --git a/extra/tools/deploy/backend/backend.factor b/extra/tools/deploy/backend/backend.factor index e11d16c4ec..b838654248 100755 --- a/extra/tools/deploy/backend/backend.factor +++ b/extra/tools/deploy/backend/backend.factor @@ -22,9 +22,8 @@ IN: tools.deploy.backend +stdout+ >>stderr +closed+ >>stdin +low-priority+ >>priority - utf8 - dup copy-lines - process>> wait-for-process zero? [ + utf8 + >r copy-lines r> wait-for-process zero? [ "Deployment failed" throw ] unless ; diff --git a/extra/tools/deploy/deploy-tests.factor b/extra/tools/deploy/deploy-tests.factor index 99e533f1c1..37689f749f 100755 --- a/extra/tools/deploy/deploy-tests.factor +++ b/extra/tools/deploy/deploy-tests.factor @@ -1,7 +1,7 @@ IN: tools.deploy.tests USING: tools.test system io.files kernel tools.deploy.config tools.deploy.backend math sequences io.launcher arrays -namespaces continuations layouts ; +namespaces continuations layouts accessors ; : shake-and-bake ( vocab -- ) [ "test.image" temp-file delete-file ] ignore-errors @@ -12,7 +12,7 @@ namespaces continuations layouts ; ] with-directory ; : small-enough? ( n -- ? ) - >r "test.image" temp-file file-info file-info-size r> <= ; + >r "test.image" temp-file file-info size>> r> <= ; [ ] [ "hello-world" shake-and-bake ] unit-test diff --git a/extra/tools/threads/threads.factor b/extra/tools/threads/threads.factor index 552247e2c4..060377d127 100755 --- a/extra/tools/threads/threads.factor +++ b/extra/tools/threads/threads.factor @@ -22,7 +22,7 @@ heaps.private system math math.parser ; : threads. ( -- ) standard-table-style [ [ - { "ID" "Name" "Waiting on" "Remaining sleep" } + { "ID:" "Name:" "Waiting on:" "Remaining sleep:" } [ [ write ] with-cell ] each ] with-row diff --git a/extra/tools/vocabs/browser/browser.factor b/extra/tools/vocabs/browser/browser.factor index 6ecb0bc5ad..db1edbeb61 100755 --- a/extra/tools/vocabs/browser/browser.factor +++ b/extra/tools/vocabs/browser/browser.factor @@ -10,7 +10,7 @@ IN: tools.vocabs.browser { { [ dup not ] [ drop "" ] } { [ dup vocab-main ] [ drop "[Runnable]" ] } - { [ t ] [ drop "[Loaded]" ] } + [ drop "[Loaded]" ] } cond ; : write-status ( vocab -- ) diff --git a/extra/tools/vocabs/monitor/monitor.factor b/extra/tools/vocabs/monitor/monitor.factor index 826d410480..ab5e8c66b7 100755 --- a/extra/tools/vocabs/monitor/monitor.factor +++ b/extra/tools/vocabs/monitor/monitor.factor @@ -22,25 +22,32 @@ IN: tools.vocabs.monitor : path>vocab ( path -- vocab ) chop-vocab-root path>vocab-name vocab-dir>vocab-name ; -: monitor-thread ( monitor -- ) +: monitor-loop ( monitor -- ) #! On OS X, monitors give us the full path, so we chop it #! off if its there. - next-change drop path>vocab changed-vocab reset-cache ; + dup next-change drop path>vocab changed-vocab + reset-cache + monitor-loop ; + +: monitor-thread ( -- ) + [ + [ + "" resource-path t + + H{ } clone changed-vocabs set-global + vocabs [ changed-vocab ] each + + monitor-loop + ] with-monitors + ] ignore-errors ; : start-monitor-thread ( -- ) #! Silently ignore errors during monitor creation since #! monitors are not supported on all platforms. - [ - "" resource-path t [ monitor-thread t ] curry - "Vocabulary monitor" spawn-server drop - - H{ } clone changed-vocabs set-global - - vocabs [ changed-vocab ] each - ] ignore-errors ; + [ monitor-thread ] "Vocabulary monitor" spawn drop ; [ - "-no-monitors" cli-args get member? [ + "-no-monitors" cli-args member? [ start-monitor-thread ] unless ] "tools.vocabs.monitor" add-init-hook diff --git a/extra/tools/vocabs/vocabs-tests.factor b/extra/tools/vocabs/vocabs-tests.factor index ae74d516e4..04e628d080 100644 --- a/extra/tools/vocabs/vocabs-tests.factor +++ b/extra/tools/vocabs/vocabs-tests.factor @@ -4,5 +4,6 @@ USING: tools.test tools.vocabs namespaces continuations ; [ ] [ changed-vocabs get-global f changed-vocabs set-global + [ t ] [ "kernel" changed-vocab? ] unit-test [ "kernel" changed-vocab ] [ changed-vocabs set-global ] [ ] cleanup ] unit-test diff --git a/extra/tools/vocabs/vocabs.factor b/extra/tools/vocabs/vocabs.factor index 371bbc7813..484d401769 100755 --- a/extra/tools/vocabs/vocabs.factor +++ b/extra/tools/vocabs/vocabs.factor @@ -85,10 +85,11 @@ SYMBOL: changed-vocabs : unchanged-vocabs ( vocabs -- ) [ unchanged-vocab ] each ; +: changed-vocab? ( vocab -- ? ) + changed-vocabs get dup [ key? ] [ 2drop t ] if ; + : filter-changed ( vocabs -- vocabs' ) - changed-vocabs get [ - [ key? ] curry subset - ] when* ; + [ changed-vocab? ] subset ; SYMBOL: modified-sources SYMBOL: modified-docs @@ -96,7 +97,7 @@ SYMBOL: modified-docs : (to-refresh) ( vocab variable loaded? path -- ) dup [ swap [ - pick changed-vocabs get key? [ + pick changed-vocab? [ source-modified? [ get push ] [ 2drop ] if ] [ 3drop ] if ] [ drop get push ] if @@ -254,7 +255,7 @@ MEMO: all-vocabs-seq ( -- seq ) { [ ".test" ?tail ] [ t ] } { [ "raptor" ?head ] [ t ] } { [ dup "tools.deploy.app" = ] [ t ] } - { [ t ] [ f ] } + [ f ] } cond nip ; : filter-dangerous ( seq -- seq' ) diff --git a/extra/tools/walker/walker.factor b/extra/tools/walker/walker.factor index 4d1a4da6b1..8a5ab42767 100755 --- a/extra/tools/walker/walker.factor +++ b/extra/tools/walker/walker.factor @@ -72,8 +72,9 @@ M: object add-breakpoint ; { { [ dup "step-into" word-prop ] [ "step-into" word-prop call ] } { [ dup standard-generic? ] [ effective-method (step-into-execute) ] } + { [ dup hook-generic? ] [ effective-method (step-into-execute) ] } { [ dup primitive? ] [ execute break ] } - { [ t ] [ word-def (step-into-quot) ] } + [ word-def (step-into-quot) ] } cond ; \ (step-into-execute) t "step-into?" set-word-prop @@ -153,7 +154,7 @@ SYMBOL: +stopped+ { [ dup quotation? ] [ add-breakpoint , \ break , ] } { [ dup array? ] [ add-breakpoint , \ break , ] } { [ dup word? ] [ literalize , \ (step-into-execute) , ] } - { [ t ] [ , \ break , ] } + [ , \ break , ] } cond % ] [ ] make ] change-frame ; diff --git a/extra/trees/avl/avl.factor b/extra/trees/avl/avl.factor index 81628684bc..2fa3efcf7b 100755 --- a/extra/trees/avl/avl.factor +++ b/extra/trees/avl/avl.factor @@ -29,7 +29,7 @@ TUPLE: avl-node balance ; avl-node-balance { { [ dup zero? ] [ 2drop 0 0 ] } { [ over = ] [ neg 0 ] } - { [ t ] [ 0 swap ] } + [ 0 swap ] } cond ; : double-rotate ( node -- node ) @@ -89,7 +89,7 @@ M: avl set-at ( value key node -- node ) current-side get over avl-node-balance { { [ dup zero? ] [ drop neg over set-avl-node-balance f ] } { [ dupd = ] [ drop 0 over set-avl-node-balance t ] } - { [ t ] [ dupd neg change-balance rebalance-delete ] } + [ dupd neg change-balance rebalance-delete ] } cond ; : avl-replace-with-extremity ( to-replace node -- node shorter? ) diff --git a/extra/trees/trees.factor b/extra/trees/trees.factor index e59bbab1ed..1648eeec32 100755 --- a/extra/trees/trees.factor +++ b/extra/trees/trees.factor @@ -112,7 +112,7 @@ M: tree set-at ( value key tree -- ) [ 2drop t ] } { [ >r 2nip r> [ tree-call ] 2keep rot ] [ drop [ node-key ] keep node-value t ] } - { [ t ] [ >r node-right r> find-node ] } + [ >r node-right r> find-node ] } cond ; inline M: tree-mixin assoc-find ( tree quot -- key value ? ) diff --git a/extra/ui/gadgets/buttons/buttons.factor b/extra/ui/gadgets/buttons/buttons.factor index 7e649b7ff7..978e5d48e2 100755 --- a/extra/ui/gadgets/buttons/buttons.factor +++ b/extra/ui/gadgets/buttons/buttons.factor @@ -55,7 +55,7 @@ C: button-paint { [ dup button-pressed? ] [ drop button-paint-pressed ] } { [ dup button-selected? ] [ drop button-paint-selected ] } { [ dup button-rollover? ] [ drop button-paint-rollover ] } - { [ t ] [ drop button-paint-plain ] } + [ drop button-paint-plain ] } cond ; M: button-paint draw-interior diff --git a/extra/ui/gadgets/gadgets.factor b/extra/ui/gadgets/gadgets.factor index 3ad76b0a16..f4e5ca2a46 100755 --- a/extra/ui/gadgets/gadgets.factor +++ b/extra/ui/gadgets/gadgets.factor @@ -378,7 +378,7 @@ SYMBOL: in-layout? { { [ 2dup eq? ] [ 2drop t ] } { [ dup not ] [ 2drop f ] } - { [ t ] [ gadget-parent child? ] } + [ gadget-parent child? ] } cond ; GENERIC: focusable-child* ( gadget -- child/t ) diff --git a/extra/ui/gadgets/panes/panes.factor b/extra/ui/gadgets/panes/panes.factor index fedacbd2af..439e938186 100755 --- a/extra/ui/gadgets/panes/panes.factor +++ b/extra/ui/gadgets/panes/panes.factor @@ -88,7 +88,7 @@ C: pane-stream dup gadget-children { { [ dup empty? ] [ 2drop ""