diff --git a/core/alien/compiler/compiler.factor b/core/alien/compiler/compiler.factor index 9c686bd4aa..992c7763f2 100755 --- a/core/alien/compiler/compiler.factor +++ b/core/alien/compiler/compiler.factor @@ -196,6 +196,12 @@ M: alien-invoke alien-node-abi alien-invoke-library library [ library-abi ] [ "cdecl" ] if* ; +M: alien-invoke-error summary + drop + "Words calling ``alien-invoke'' must be compiled with the optimizing compiler." ; + +: pop-parameters pop-literal nip [ expand-constants ] map ; + : stdcall-mangle ( symbol node -- symbol ) "@" swap alien-node-parameters parameter-sizes drop @@ -219,11 +225,6 @@ M: no-such-symbol summary [ no-such-symbol ] unless ] unless rot drop ; -M: alien-invoke-error summary - drop "Words calling ``alien-invoke'' cannot run in the interpreter. Compile the caller word and try again." ; - -: pop-parameters pop-literal nip [ expand-constants ] map ; - \ alien-invoke [ ! Four literals 4 ensure-values @@ -233,10 +234,10 @@ M: alien-invoke-error summary pop-literal nip over set-alien-invoke-function pop-literal nip over set-alien-invoke-library pop-literal nip over set-alien-invoke-return - ! Quotation which coerces parameters to required types - dup make-prep-quot recursive-state get infer-quot ! If symbol doesn't resolve, no stack effect, no compile dup alien-invoke-dlsym 2drop + ! Quotation which coerces parameters to required types + dup make-prep-quot recursive-state get infer-quot ! Add node to IR dup node, ! Magic #: consume exactly the number of inputs @@ -260,7 +261,7 @@ M: alien-indirect alien-node-return alien-indirect-return ; M: alien-indirect alien-node-abi alien-indirect-abi ; M: alien-indirect-error summary - drop "Words calling ``alien-indirect'' cannot run in the interpreter. Compile the caller word and try again." ; + drop "Words calling ``alien-indirect'' must be compiled with the optimizing compiler." ; \ alien-indirect [ ! Three literals and function pointer @@ -309,7 +310,7 @@ M: alien-callback alien-node-return alien-callback-return ; M: alien-callback alien-node-abi alien-callback-abi ; M: alien-callback-error summary - drop "Words calling ``alien-callback'' cannot run in the interpreter. Compile the caller word and try again." ; + drop "Words calling ``alien-callback'' must be compiled with the optimizing compiler." ; : callback-bottom ( node -- ) alien-callback-xt [ word-xt ] curry diff --git a/core/bootstrap/stage1.factor b/core/bootstrap/stage1.factor index df59afccb0..cda75fedf6 100755 --- a/core/bootstrap/stage1.factor +++ b/core/bootstrap/stage1.factor @@ -25,6 +25,10 @@ vocabs.loader system ; "math.integers" require "math.floats" require "memory" require + + ! this must add its init hook before io.backend does + "libc" require + "io.streams.c" require "vocabs.loader" require "syntax" require diff --git a/core/compiler/test/alien.factor b/core/compiler/test/alien.factor old mode 100644 new mode 100755 index aa6b7aea7c..8358709590 --- a/core/compiler/test/alien.factor +++ b/core/compiler/test/alien.factor @@ -2,7 +2,8 @@ IN: temporary USING: alien alien.c-types alien.syntax compiler kernel namespaces namespaces tools.test sequences inference words arrays parser quotations continuations inference.backend effects -namespaces.private io io.streams.string memory system threads ; +namespaces.private io io.streams.string memory system threads +tools.test.inference ; FUNCTION: void ffi_test_0 ; [ ] [ ffi_test_0 ] unit-test @@ -79,10 +80,7 @@ FUNCTION: tiny ffi_test_17 int x ; : indirect-test-1 "int" { } "cdecl" alien-indirect ; -: short-effect - dup effect-in length swap effect-out length 2array ; - -[ { 1 1 } ] [ [ indirect-test-1 ] infer short-effect ] unit-test +{ 1 1 } [ indirect-test-1 ] unit-test-effect [ 3 ] [ "ffi_test_1" f dlsym indirect-test-1 ] unit-test @@ -91,7 +89,7 @@ FUNCTION: tiny ffi_test_17 int x ; : indirect-test-2 "int" { "int" "int" } "cdecl" alien-indirect data-gc ; -[ { 3 1 } ] [ [ indirect-test-2 ] infer short-effect ] unit-test +{ 3 1 } [ indirect-test-2 ] unit-test-effect [ 5 ] [ 2 3 "ffi_test_2" f dlsym indirect-test-2 ] diff --git a/core/compiler/test/redefine.factor b/core/compiler/test/redefine.factor old mode 100644 new mode 100755 index df2f3c3915..1fac112b2d --- a/core/compiler/test/redefine.factor +++ b/core/compiler/test/redefine.factor @@ -1,36 +1,33 @@ USING: compiler definitions generic assocs inference math namespaces parser tools.test words kernel sequences arrays io -effects ; +effects tools.test.inference ; IN: temporary parse-hook get [ DEFER: foo \ foo reset-generic DEFER: bar \ bar reset-generic - : short-effect - dup effect-in length swap effect-out length 2array ; - - [ ] [ \ foo [ 1 2 ] define-compound ] unit-test - [ { 0 2 } ] [ [ foo ] infer short-effect ] unit-test - [ ] [ \ foo compile ] unit-test + [ ] [ \ foo [ 1 2 ] define-compound ] unit-test + { 0 2 } [ foo ] unit-test-effect + [ ] [ \ foo compile ] unit-test [ ] [ \ bar [ foo foo ] define-compound ] unit-test - [ ] [ \ bar compile ] unit-test - [ ] [ \ foo [ 1 2 3 ] define-compound ] unit-test - [ t ] [ \ bar changed-words get key? ] unit-test + [ ] [ \ bar compile ] unit-test + [ ] [ \ foo [ 1 2 3 ] define-compound ] unit-test + [ t ] [ \ bar changed-words get key? ] unit-test [ ] [ recompile ] unit-test - [ { 0 3 } ] [ [ foo ] infer short-effect ] unit-test - [ f ] [ \ bar changed-words get key? ] unit-test - [ ] [ \ bar [ 1 2 ] define-compound ] unit-test - [ t ] [ \ bar changed-words get key? ] unit-test + { 0 3 } [ foo ] unit-test-effect + [ f ] [ \ bar changed-words get key? ] unit-test + [ ] [ \ bar [ 1 2 ] define-compound ] unit-test + [ t ] [ \ bar changed-words get key? ] unit-test [ ] [ recompile ] unit-test - [ { 0 2 } ] [ [ bar ] infer short-effect ] unit-test - [ f ] [ \ bar changed-words get key? ] unit-test - [ ] [ \ foo [ 1 2 3 ] define-compound ] unit-test - [ f ] [ \ bar changed-words get key? ] unit-test - [ ] [ \ bar [ 1 2 3 ] define-compound ] unit-test - [ t ] [ \ bar changed-words get key? ] unit-test + { 0 2 } [ bar ] unit-test-effect + [ f ] [ \ bar changed-words get key? ] unit-test + [ ] [ \ foo [ 1 2 3 ] define-compound ] unit-test + [ f ] [ \ bar changed-words get key? ] unit-test + [ ] [ \ bar [ 1 2 3 ] define-compound ] unit-test + [ t ] [ \ bar changed-words get key? ] unit-test [ ] [ \ bar forget ] unit-test - [ f ] [ \ bar changed-words get key? ] unit-test + [ f ] [ \ bar changed-words get key? ] unit-test : xy ; : yx xy ; diff --git a/core/dlists/dlists-tests.factor b/core/dlists/dlists-tests.factor old mode 100644 new mode 100755 index f4482d680d..ebae68472b --- a/core/dlists/dlists-tests.factor +++ b/core/dlists/dlists-tests.factor @@ -1,4 +1,6 @@ -USING: dlists dlists.private kernel tools.test ; +USING: dlists dlists.private kernel tools.test random assocs +hashtables sequences namespaces sorting debugger io prettyprint +math ; IN: temporary [ t ] [ dlist-empty? ] unit-test @@ -59,3 +61,37 @@ IN: temporary [ 0 ] [ dlist-length ] unit-test [ 1 ] [ 1 over push-front dlist-length ] unit-test [ 0 ] [ 1 over push-front dup pop-front* dlist-length ] unit-test + +: assert-same-elements + [ prune natural-sort ] 2apply assert= ; + +: dlist-push-all [ push-front ] curry each ; + +: dlist-delete-all [ dlist-delete drop ] curry each ; + +: dlist>array [ [ , ] dlist-slurp ] { } make ; + +[ ] [ + 5 [ drop 30 random >fixnum ] map prune + 6 [ drop 30 random >fixnum ] map prune 2dup nl . . nl + [ + + [ dlist-push-all ] keep + [ dlist-delete-all ] keep + dlist>array + ] 2keep seq-diff assert-same-elements +] unit-test + +[ ] [ + "d" set + 1 "d" get push-front + 2 "d" get push-front + 3 "d" get push-front + 4 "d" get push-front + 2 "d" get dlist-delete drop + 3 "d" get dlist-delete drop + 4 "d" get dlist-delete drop +] unit-test + +[ 1 ] [ "d" get dlist-length ] unit-test +[ 1 ] [ "d" get dlist>array length ] unit-test diff --git a/core/dlists/dlists.factor b/core/dlists/dlists.factor old mode 100644 new mode 100755 index 890185d4c4..a3c869efaf --- a/core/dlists/dlists.factor +++ b/core/dlists/dlists.factor @@ -49,15 +49,15 @@ C: dlist-node drop nip t ] [ drop dlist-node-next [ (dlist-find-node) ] [ drop f f ] if* - ] if ; + ] if ; inline : dlist-find-node ( quot dlist -- node/f ? ) - dlist-front [ (dlist-find-node) ] [ drop f f ] if* ; + dlist-front [ (dlist-find-node) ] [ drop f f ] if* ; inline : (dlist-each-node) ( quot dlist -- ) over [ 2dup call >r dlist-node-next r> (dlist-each-node) ] - [ 2drop ] if ; + [ 2drop ] if ; inline : dlist-each-node ( quot dlist -- ) >r dlist-front r> (dlist-each-node) ; inline @@ -98,17 +98,20 @@ PRIVATE> : pop-back* ( dlist -- ) pop-back drop ; : dlist-find ( quot dlist -- obj/f ? ) - dlist-find-node dup [ >r dlist-node-obj r> ] when ; + dlist-find-node dup [ >r dlist-node-obj r> ] when ; inline : dlist-contains? ( quot dlist -- ? ) - dlist-find nip ; + dlist-find nip ; inline + +: unlink-node ( dlist-node -- ) + dup dlist-node-prev over dlist-node-next set-prev-when + dup dlist-node-next swap dlist-node-prev set-next-when ; : (delete-node) ( dlist dlist-node -- ) { - { [ 2dup >r dlist-front r> = ] [ drop pop-front* ] } - { [ 2dup >r dlist-back r> = ] [ drop pop-back* ] } - { [ t ] [ dup dlist-node-prev swap dlist-node-next set-prev-when - dec-length ] } + { [ over dlist-front over eq? ] [ drop pop-front* ] } + { [ over dlist-back over eq? ] [ drop pop-back* ] } + { [ t ] [ unlink-node dec-length ] } } cond ; : delete-node* ( quot dlist -- obj/f ? ) @@ -116,10 +119,13 @@ PRIVATE> [ (delete-node) ] keep [ dlist-node-obj t ] [ f f ] if* ] [ 2drop f f - ] if ; + ] if ; inline : delete-node ( quot dlist -- obj/f ) - delete-node* drop ; + delete-node* drop ; inline + +: dlist-delete ( obj dlist -- obj/f ) + >r [ eq? ] curry r> delete-node ; : dlist-each ( dlist quot -- ) [ dlist-node-obj ] swap compose dlist-each-node ; inline diff --git a/core/inference/inference-tests.factor b/core/inference/inference-tests.factor index 1d3d6ebcf2..3462dee83a 100755 --- a/core/inference/inference-tests.factor +++ b/core/inference/inference-tests.factor @@ -6,46 +6,40 @@ continuations generic.standard sorting assocs definitions prettyprint io inspector bootstrap.image tuples classes.union classes.predicate debugger bootstrap.image bootstrap.image.private io.launcher threads.private -io.streams.string combinators.private ; +io.streams.string combinators.private tools.test.inference ; IN: temporary -: short-effect - dup effect-in length swap effect-out length 2array ; +{ 0 2 } [ 2 "Hello" ] unit-test-effect +{ 1 2 } [ dup ] unit-test-effect -[ { 0 2 } ] [ [ 2 "Hello" ] infer short-effect ] unit-test -[ { 1 2 } ] [ [ dup ] infer short-effect ] unit-test +{ 1 2 } [ [ dup ] call ] unit-test-effect +[ [ call ] infer ] unit-test-fails -[ { 1 2 } ] [ [ [ dup ] call ] infer short-effect ] unit-test -[ [ call ] infer short-effect ] unit-test-fails +{ 2 4 } [ 2dup ] unit-test-effect -[ { 2 4 } ] [ [ 2dup ] infer short-effect ] unit-test +{ 1 0 } [ [ ] [ ] if ] unit-test-effect +[ [ if ] infer ] unit-test-fails +[ [ [ ] if ] infer ] unit-test-fails +[ [ [ 2 ] [ ] if ] infer ] unit-test-fails +{ 4 3 } [ [ rot ] [ -rot ] if ] unit-test-effect -[ { 1 0 } ] [ [ [ ] [ ] if ] infer short-effect ] unit-test -[ [ if ] infer short-effect ] unit-test-fails -[ [ [ ] if ] infer short-effect ] unit-test-fails -[ [ [ 2 ] [ ] if ] infer short-effect ] unit-test-fails -[ { 4 3 } ] [ [ [ rot ] [ -rot ] if ] infer short-effect ] unit-test - -[ { 4 3 } ] [ +{ 4 3 } [ [ - [ - [ swap 3 ] [ nip 5 5 ] if - ] [ - -rot - ] if - ] infer short-effect -] unit-test + [ swap 3 ] [ nip 5 5 ] if + ] [ + -rot + ] if +] unit-test-effect -[ { 1 1 } ] [ [ dup [ ] when ] infer short-effect ] unit-test -[ { 1 1 } ] [ [ dup [ dup fixnum* ] when ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ [ dup fixnum* ] when ] infer short-effect ] unit-test +{ 1 1 } [ dup [ ] when ] unit-test-effect +{ 1 1 } [ dup [ dup fixnum* ] when ] unit-test-effect +{ 2 1 } [ [ dup fixnum* ] when ] unit-test-effect -[ { 1 0 } ] [ [ [ drop ] when* ] infer short-effect ] unit-test -[ { 1 1 } ] [ [ [ { { [ ] } } ] unless* ] infer short-effect ] unit-test +{ 1 0 } [ [ drop ] when* ] unit-test-effect +{ 1 1 } [ [ { { [ ] } } ] unless* ] unit-test-effect -[ { 0 1 } ] [ - [ [ 2 2 fixnum+ ] dup [ ] when call ] infer short-effect -] unit-test +{ 0 1 } +[ [ 2 2 fixnum+ ] dup [ ] when call ] unit-test-effect [ [ [ [ 2 2 fixnum+ ] ] [ [ 2 2 fixnum* ] ] if call ] infer @@ -57,37 +51,37 @@ IN: temporary : termination-test-2 [ termination-test-1 ] [ 3 ] if ; -[ { 1 1 } ] [ [ termination-test-2 ] infer short-effect ] unit-test +{ 1 1 } [ termination-test-2 ] unit-test-effect : infinite-loop infinite-loop ; -[ [ infinite-loop ] infer short-effect ] unit-test-fails +[ [ infinite-loop ] infer ] unit-test-fails : no-base-case-1 dup [ no-base-case-1 ] [ no-base-case-1 ] if ; -[ [ no-base-case-1 ] infer short-effect ] unit-test-fails +[ [ no-base-case-1 ] infer ] unit-test-fails : simple-recursion-1 ( obj -- obj ) dup [ simple-recursion-1 ] [ ] if ; -[ { 1 1 } ] [ [ simple-recursion-1 ] infer short-effect ] unit-test +{ 1 1 } [ simple-recursion-1 ] unit-test-effect : simple-recursion-2 ( obj -- obj ) dup [ ] [ simple-recursion-2 ] if ; -[ { 1 1 } ] [ [ simple-recursion-2 ] infer short-effect ] unit-test +{ 1 1 } [ simple-recursion-2 ] unit-test-effect : bad-recursion-2 ( obj -- obj ) dup [ dup first swap second bad-recursion-2 ] [ ] if ; -[ [ bad-recursion-2 ] infer short-effect ] unit-test-fails +[ [ bad-recursion-2 ] infer ] unit-test-fails : funny-recursion ( obj -- obj ) dup [ funny-recursion 1 ] [ 2 ] if drop ; -[ { 1 1 } ] [ [ funny-recursion ] infer short-effect ] unit-test +{ 1 1 } [ funny-recursion ] unit-test-effect ! Simple combinators -[ { 1 2 } ] [ [ [ first ] keep second ] infer short-effect ] unit-test +{ 1 2 } [ [ first ] keep second ] unit-test-effect ! Mutual recursion DEFER: foe @@ -110,8 +104,8 @@ DEFER: foe 2drop f ] if ; -[ { 2 1 } ] [ [ fie ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ foe ] infer short-effect ] unit-test +{ 2 1 } [ fie ] unit-test-effect +{ 2 1 } [ foe ] unit-test-effect : nested-when ( -- ) t [ @@ -120,7 +114,7 @@ DEFER: foe ] when ] when ; -[ { 0 0 } ] [ [ nested-when ] infer short-effect ] unit-test +{ 0 0 } [ nested-when ] unit-test-effect : nested-when* ( obj -- ) [ @@ -129,11 +123,11 @@ DEFER: foe ] when* ] when* ; -[ { 1 0 } ] [ [ nested-when* ] infer short-effect ] unit-test +{ 1 0 } [ nested-when* ] unit-test-effect SYMBOL: sym-test -[ { 0 1 } ] [ [ sym-test ] infer short-effect ] unit-test +{ 0 1 } [ sym-test ] unit-test-effect : terminator-branch dup [ @@ -142,7 +136,7 @@ SYMBOL: sym-test "foo" throw ] if ; -[ { 1 1 } ] [ [ terminator-branch ] infer short-effect ] unit-test +{ 1 1 } [ terminator-branch ] unit-test-effect : recursive-terminator ( obj -- ) dup [ @@ -151,12 +145,12 @@ SYMBOL: sym-test "Hi" throw ] if ; -[ { 1 0 } ] [ [ recursive-terminator ] infer short-effect ] unit-test +{ 1 0 } [ recursive-terminator ] unit-test-effect GENERIC: potential-hang ( obj -- obj ) M: fixnum potential-hang dup [ potential-hang ] when ; -[ ] [ [ 5 potential-hang ] infer short-effect drop ] unit-test +[ ] [ [ 5 potential-hang ] infer drop ] unit-test TUPLE: funny-cons car cdr ; GENERIC: iterate ( obj -- ) @@ -164,24 +158,24 @@ M: funny-cons iterate funny-cons-cdr iterate ; M: f iterate drop ; M: real iterate drop ; -[ { 1 0 } ] [ [ iterate ] infer short-effect ] unit-test +{ 1 0 } [ iterate ] unit-test-effect ! Regression : cat ( obj -- * ) dup [ throw ] [ throw ] if ; : dog ( a b c -- ) dup [ cat ] [ 3drop ] if ; -[ { 3 0 } ] [ [ dog ] infer short-effect ] unit-test +{ 3 0 } [ dog ] unit-test-effect ! Regression DEFER: monkey : friend ( a b c -- ) dup [ friend ] [ monkey ] if ; : monkey ( a b c -- ) dup [ 3drop ] [ friend ] if ; -[ { 3 0 } ] [ [ friend ] infer short-effect ] unit-test +{ 3 0 } [ friend ] unit-test-effect -! Regression -- same as above but we infer short-effect the second word first +! Regression -- same as above but we infer the second word first DEFER: blah2 : blah ( a b c -- ) dup [ blah ] [ blah2 ] if ; : blah2 ( a b c -- ) dup [ blah ] [ 3drop ] if ; -[ { 3 0 } ] [ [ blah2 ] infer short-effect ] unit-test +{ 3 0 } [ blah2 ] unit-test-effect ! Regression DEFER: blah4 @@ -189,7 +183,7 @@ DEFER: blah4 dup [ blah3 ] [ dup [ blah4 ] [ blah3 ] if ] if ; : blah4 ( a b c -- ) dup [ blah4 ] [ dup [ 3drop ] [ blah3 ] if ] if ; -[ { 3 0 } ] [ [ blah4 ] infer short-effect ] unit-test +{ 3 0 } [ blah4 ] unit-test-effect ! Regression : bad-combinator ( obj quot -- ) @@ -199,14 +193,14 @@ DEFER: blah4 [ swap slip ] keep swap bad-combinator ] if ; inline -[ [ [ 1 ] [ ] bad-combinator ] infer short-effect ] unit-test-fails +[ [ [ 1 ] [ ] bad-combinator ] infer ] unit-test-fails ! Regression : bad-input# dup string? [ 2array throw ] unless over string? [ 2array throw ] unless ; -[ { 2 2 } ] [ [ bad-input# ] infer short-effect ] unit-test +{ 2 2 } [ bad-input# ] unit-test-effect ! Regression @@ -214,18 +208,18 @@ DEFER: blah4 DEFER: do-crap : more-crap ( obj -- ) dup [ drop ] [ dup do-crap call ] if ; : do-crap ( obj -- ) dup [ more-crap ] [ do-crap ] if ; -[ [ do-crap ] infer short-effect ] unit-test-fails +[ [ do-crap ] infer ] unit-test-fails ! This one does not DEFER: do-crap* : more-crap* ( obj -- ) dup [ drop ] [ dup do-crap* call ] if ; : do-crap* ( obj -- ) dup [ do-crap* ] [ more-crap* ] if ; -[ [ do-crap* ] infer short-effect ] unit-test-fails +[ [ do-crap* ] infer ] unit-test-fails ! Regression : too-deep ( a b -- c ) dup [ drop ] [ 2dup too-deep too-deep * ] if ; inline -[ { 2 1 } ] [ [ too-deep ] infer short-effect ] unit-test +{ 2 1 } [ too-deep ] unit-test-effect ! Error reporting is wrong MATH: xyz @@ -233,7 +227,7 @@ M: fixnum xyz 2array ; M: float xyz [ 3 ] 2apply swapd >r 2array swap r> 2array swap ; -[ t ] [ [ [ xyz ] infer short-effect ] catch inference-error? ] unit-test +[ t ] [ [ [ xyz ] infer ] catch inference-error? ] unit-test ! Doug Coleman discovered this one while working on the ! calendar library @@ -265,17 +259,17 @@ DEFER: C [ dup B C ] } dispatch ; -[ { 1 0 } ] [ [ A ] infer short-effect ] unit-test -[ { 1 0 } ] [ [ B ] infer short-effect ] unit-test -[ { 1 0 } ] [ [ C ] infer short-effect ] unit-test +{ 1 0 } [ A ] unit-test-effect +{ 1 0 } [ B ] unit-test-effect +{ 1 0 } [ C ] unit-test-effect ! I found this bug by thinking hard about the previous one DEFER: Y : X ( a b -- c d ) dup [ swap Y ] [ ] if ; : Y ( a b -- c d ) X ; -[ { 2 2 } ] [ [ X ] infer short-effect ] unit-test -[ { 2 2 } ] [ [ Y ] infer short-effect ] unit-test +{ 2 2 } [ X ] unit-test-effect +{ 2 2 } [ Y ] unit-test-effect ! This one comes from UI code DEFER: #1 @@ -284,17 +278,17 @@ DEFER: #1 : #4 ( a -- ) dup [ drop ] [ dup #4 dup #3 call ] if ; : #1 ( a -- ) dup [ dup #4 dup #3 ] [ ] if drop ; -[ \ #4 word-def infer short-effect ] unit-test-fails -[ [ #1 ] infer short-effect ] unit-test-fails +[ \ #4 word-def infer ] unit-test-fails +[ [ #1 ] infer ] unit-test-fails ! Similar DEFER: bar : foo ( a b -- c d ) dup [ 2drop f f bar ] [ ] if ; : bar ( a b -- ) [ 2 2 + ] t foo drop call drop ; -[ [ foo ] infer short-effect ] unit-test-fails +[ [ foo ] infer ] unit-test-fails -[ 1234 infer short-effect ] unit-test-fails +[ 1234 infer ] unit-test-fails ! This used to hang [ t ] [ @@ -340,128 +334,128 @@ DEFER: bar : bad-recursion-1 ( a -- b ) dup [ drop bad-recursion-1 5 ] [ ] if ; -[ [ bad-recursion-1 ] infer short-effect ] unit-test-fails +[ [ bad-recursion-1 ] infer ] unit-test-fails : bad-bin ( a b -- ) 5 [ 5 bad-bin bad-bin 5 ] [ 2drop ] if ; -[ [ bad-bin ] infer short-effect ] unit-test-fails +[ [ bad-bin ] infer ] unit-test-fails -[ t ] [ [ [ r> ] infer short-effect ] catch inference-error? ] unit-test +[ t ] [ [ [ r> ] infer ] catch inference-error? ] unit-test ! Regression [ t ] [ [ [ get-slots ] infer ] catch inference-error? ] unit-test ! Test some curry stuff -[ { 1 1 } ] [ [ 3 [ ] curry 4 [ ] curry if ] infer short-effect ] unit-test +{ 1 1 } [ 3 [ ] curry 4 [ ] curry if ] unit-test-effect -[ { 2 1 } ] [ [ [ ] curry 4 [ ] curry if ] infer short-effect ] unit-test +{ 2 1 } [ [ ] curry 4 [ ] curry if ] unit-test-effect [ [ 3 [ ] curry 1 2 [ ] 2curry if ] infer ] unit-test-fails ! Test number protocol -[ { 2 1 } ] [ [ bitor ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ bitand ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ bitxor ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ mod ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ /i ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ /f ] infer short-effect ] unit-test -[ { 2 2 } ] [ [ /mod ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ + ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ - ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ * ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ / ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ < ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ <= ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ > ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ >= ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ number= ] infer short-effect ] unit-test +{ 2 1 } [ bitor ] unit-test-effect +{ 2 1 } [ bitand ] unit-test-effect +{ 2 1 } [ bitxor ] unit-test-effect +{ 2 1 } [ mod ] unit-test-effect +{ 2 1 } [ /i ] unit-test-effect +{ 2 1 } [ /f ] unit-test-effect +{ 2 2 } [ /mod ] unit-test-effect +{ 2 1 } [ + ] unit-test-effect +{ 2 1 } [ - ] unit-test-effect +{ 2 1 } [ * ] unit-test-effect +{ 2 1 } [ / ] unit-test-effect +{ 2 1 } [ < ] unit-test-effect +{ 2 1 } [ <= ] unit-test-effect +{ 2 1 } [ > ] unit-test-effect +{ 2 1 } [ >= ] unit-test-effect +{ 2 1 } [ number= ] unit-test-effect ! Test object protocol -[ { 2 1 } ] [ [ = ] infer short-effect ] unit-test -[ { 1 1 } ] [ [ clone ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ hashcode* ] infer short-effect ] unit-test +{ 2 1 } [ = ] unit-test-effect +{ 1 1 } [ clone ] unit-test-effect +{ 2 1 } [ hashcode* ] unit-test-effect ! Test sequence protocol -[ { 1 1 } ] [ [ length ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ nth ] infer short-effect ] unit-test -[ { 2 0 } ] [ [ set-length ] infer short-effect ] unit-test -[ { 3 0 } ] [ [ set-nth ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ new ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ new-resizable ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ like ] infer short-effect ] unit-test -[ { 2 0 } ] [ [ lengthen ] infer short-effect ] unit-test +{ 1 1 } [ length ] unit-test-effect +{ 2 1 } [ nth ] unit-test-effect +{ 2 0 } [ set-length ] unit-test-effect +{ 3 0 } [ set-nth ] unit-test-effect +{ 2 1 } [ new ] unit-test-effect +{ 2 1 } [ new-resizable ] unit-test-effect +{ 2 1 } [ like ] unit-test-effect +{ 2 0 } [ lengthen ] unit-test-effect ! Test assoc protocol -[ { 2 2 } ] [ [ at* ] infer short-effect ] unit-test -[ { 3 0 } ] [ [ set-at ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ new-assoc ] infer short-effect ] unit-test -[ { 2 0 } ] [ [ delete-at ] infer short-effect ] unit-test -[ { 1 0 } ] [ [ clear-assoc ] infer short-effect ] unit-test -[ { 1 1 } ] [ [ assoc-size ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ assoc-like ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ assoc-clone-like ] infer short-effect ] unit-test -[ { 1 1 } ] [ [ >alist ] infer short-effect ] unit-test -[ { 1 3 } ] [ [ [ 2drop f ] assoc-find ] infer short-effect ] unit-test +{ 2 2 } [ at* ] unit-test-effect +{ 3 0 } [ set-at ] unit-test-effect +{ 2 1 } [ new-assoc ] unit-test-effect +{ 2 0 } [ delete-at ] unit-test-effect +{ 1 0 } [ clear-assoc ] unit-test-effect +{ 1 1 } [ assoc-size ] unit-test-effect +{ 2 1 } [ assoc-like ] unit-test-effect +{ 2 1 } [ assoc-clone-like ] unit-test-effect +{ 1 1 } [ >alist ] unit-test-effect +{ 1 3 } [ [ 2drop f ] assoc-find ] unit-test-effect ! Test some random library words -[ { 1 1 } ] [ [ 1quotation ] infer short-effect ] unit-test -[ { 1 1 } ] [ [ string>number ] infer short-effect ] unit-test -[ { 1 1 } ] [ [ get ] infer short-effect ] unit-test +{ 1 1 } [ 1quotation ] unit-test-effect +{ 1 1 } [ string>number ] unit-test-effect +{ 1 1 } [ get ] unit-test-effect -[ { 2 0 } ] [ [ push ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ append ] infer short-effect ] unit-test -[ { 1 1 } ] [ [ peek ] infer short-effect ] unit-test +{ 2 0 } [ push ] unit-test-effect +{ 2 1 } [ append ] unit-test-effect +{ 1 1 } [ peek ] unit-test-effect -[ { 1 1 } ] [ [ reverse ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ member? ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ remove ] infer short-effect ] unit-test -[ { 1 1 } ] [ [ natural-sort ] infer short-effect ] unit-test +{ 1 1 } [ reverse ] unit-test-effect +{ 2 1 } [ member? ] unit-test-effect +{ 2 1 } [ remove ] unit-test-effect +{ 1 1 } [ natural-sort ] unit-test-effect -[ { 1 0 } ] [ [ forget ] infer short-effect ] unit-test -[ { 4 0 } ] [ [ define-class ] infer short-effect ] unit-test -[ { 2 0 } ] [ [ define-tuple-class ] infer short-effect ] unit-test -[ { 2 0 } ] [ [ define-union-class ] infer short-effect ] unit-test -[ { 3 0 } ] [ [ define-predicate-class ] infer short-effect ] unit-test +{ 1 0 } [ forget ] unit-test-effect +{ 4 0 } [ define-class ] unit-test-effect +{ 2 0 } [ define-tuple-class ] unit-test-effect +{ 2 0 } [ define-union-class ] unit-test-effect +{ 3 0 } [ define-predicate-class ] unit-test-effect ! Test words with continuations -[ { 0 0 } ] [ [ [ drop ] callcc0 ] infer short-effect ] unit-test -[ { 0 1 } ] [ [ [ 4 swap continue-with ] callcc1 ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ [ + ] [ ] [ ] cleanup ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ [ + ] [ 3drop 0 ] recover ] infer short-effect ] unit-test +{ 0 0 } [ [ drop ] callcc0 ] unit-test-effect +{ 0 1 } [ [ 4 swap continue-with ] callcc1 ] unit-test-effect +{ 2 1 } [ [ + ] [ ] [ ] cleanup ] unit-test-effect +{ 2 1 } [ [ + ] [ 3drop 0 ] recover ] unit-test-effect ! Test stream protocol -[ { 2 0 } ] [ [ set-timeout ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ stream-read ] infer short-effect ] unit-test -[ { 1 1 } ] [ [ stream-read1 ] infer short-effect ] unit-test -[ { 1 1 } ] [ [ stream-readln ] infer short-effect ] unit-test -[ { 2 2 } ] [ [ stream-read-until ] infer short-effect ] unit-test -[ { 2 0 } ] [ [ stream-write ] infer short-effect ] unit-test -[ { 2 0 } ] [ [ stream-write1 ] infer short-effect ] unit-test -[ { 1 0 } ] [ [ stream-nl ] infer short-effect ] unit-test -[ { 1 0 } ] [ [ stream-close ] infer short-effect ] unit-test -[ { 3 0 } ] [ [ stream-format ] infer short-effect ] unit-test -[ { 3 0 } ] [ [ stream-write-table ] infer short-effect ] unit-test -[ { 1 0 } ] [ [ stream-flush ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ make-span-stream ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ make-block-stream ] infer short-effect ] unit-test -[ { 2 1 } ] [ [ make-cell-stream ] infer short-effect ] unit-test +{ 2 0 } [ set-timeout ] unit-test-effect +{ 2 1 } [ stream-read ] unit-test-effect +{ 1 1 } [ stream-read1 ] unit-test-effect +{ 1 1 } [ stream-readln ] unit-test-effect +{ 2 2 } [ stream-read-until ] unit-test-effect +{ 2 0 } [ stream-write ] unit-test-effect +{ 2 0 } [ stream-write1 ] unit-test-effect +{ 1 0 } [ stream-nl ] unit-test-effect +{ 1 0 } [ stream-close ] unit-test-effect +{ 3 0 } [ stream-format ] unit-test-effect +{ 3 0 } [ stream-write-table ] unit-test-effect +{ 1 0 } [ stream-flush ] unit-test-effect +{ 2 1 } [ make-span-stream ] unit-test-effect +{ 2 1 } [ make-block-stream ] unit-test-effect +{ 2 1 } [ make-cell-stream ] unit-test-effect ! Test stream utilities -[ { 1 1 } ] [ [ lines ] infer short-effect ] unit-test -[ { 1 1 } ] [ [ contents ] infer short-effect ] unit-test +{ 1 1 } [ lines ] unit-test-effect +{ 1 1 } [ contents ] unit-test-effect ! Test prettyprinting -[ { 1 0 } ] [ [ . ] infer short-effect ] unit-test -[ { 1 0 } ] [ [ short. ] infer short-effect ] unit-test -[ { 1 1 } ] [ [ unparse ] infer short-effect ] unit-test +{ 1 0 } [ . ] unit-test-effect +{ 1 0 } [ short. ] unit-test-effect +{ 1 1 } [ unparse ] unit-test-effect -[ { 1 0 } ] [ [ describe ] infer short-effect ] unit-test -[ { 1 0 } ] [ [ error. ] infer short-effect ] unit-test +{ 1 0 } [ describe ] unit-test-effect +{ 1 0 } [ error. ] unit-test-effect ! Test odds and ends -[ { 1 1 } ] [ [ ' ] infer short-effect ] unit-test -[ { 2 0 } ] [ [ write-image ] infer short-effect ] unit-test -[ { 1 1 } ] [ [ ] infer short-effect ] unit-test -[ { 0 0 } ] [ [ idle-thread ] infer short-effect ] unit-test +{ 1 1 } [ ' ] unit-test-effect +{ 2 0 } [ write-image ] unit-test-effect +{ 1 1 } [ ] unit-test-effect +{ 0 0 } [ idle-thread ] unit-test-effect ! Incorrect stack declarations on inline recursive words should ! be caught @@ -471,13 +465,13 @@ DEFER: bar [ [ barxxx ] infer ] unit-test-fails ! A typo -[ { 1 0 } ] [ [ { [ ] } dispatch ] infer short-effect ] unit-test +{ 1 0 } [ { [ ] } dispatch ] unit-test-effect DEFER: inline-recursive-2 : inline-recursive-1 ( -- ) inline-recursive-2 ; : inline-recursive-2 ( -- ) inline-recursive-1 ; -[ { 0 0 } ] [ [ inline-recursive-1 ] infer short-effect ] unit-test +{ 0 0 } [ inline-recursive-1 ] unit-test-effect ! Hooks SYMBOL: my-var @@ -486,23 +480,22 @@ HOOK: my-hook my-var ( -- x ) M: integer my-hook "an integer" ; M: string my-hook "a string" ; -[ { 0 1 } ] [ [ my-hook ] infer short-effect ] unit-test +{ 0 1 } [ my-hook ] unit-test-effect DEFER: deferred-word : calls-deferred-word [ deferred-word ] [ 3 ] if ; -[ { 1 1 } ] [ [ calls-deferred-word ] infer short-effect ] unit-test +{ 1 1 } [ calls-deferred-word ] unit-test-effect USE: inference.dataflow -[ { 1 0 } ] [ [ [ iterate-next ] iterate-nodes ] infer short-effect ] unit-test +{ 1 0 } [ [ iterate-next ] iterate-nodes ] unit-test-effect -[ { 1 0 } ] [ - [ - [ [ iterate-next ] iterate-nodes ] with-node-iterator - ] infer short-effect -] unit-test +{ 1 0 } +[ + [ [ iterate-next ] iterate-nodes ] with-node-iterator +] unit-test-effect : nilpotent ( quot -- ) t [ [ call ] keep nilpotent ] [ drop ] if ; inline @@ -510,14 +503,13 @@ USE: inference.dataflow : semisimple ( quot -- ) [ call ] keep [ [ semisimple ] keep ] nilpotent drop ; inline -[ { 0 1 } ] [ - [ [ ] [ call ] keep [ [ call ] keep ] nilpotent ] - infer short-effect -] unit-test +{ 0 1 } +[ [ ] [ call ] keep [ [ call ] keep ] nilpotent ] +unit-test-effect -[ { 0 0 } ] [ [ [ ] semisimple ] infer short-effect ] unit-test +{ 0 0 } [ [ ] semisimple ] unit-test-effect -[ { 1 0 } ] [ [ [ drop ] each-node ] infer short-effect ] unit-test +{ 1 0 } [ [ drop ] each-node ] unit-test-effect DEFER: an-inline-word @@ -533,9 +525,9 @@ DEFER: an-inline-word : an-inline-word ( obj quot -- ) >r normal-word r> call ; inline -[ { 1 1 } ] [ [ [ 3 * ] an-inline-word ] infer short-effect ] unit-test +{ 1 1 } [ [ 3 * ] an-inline-word ] unit-test-effect -[ { 0 1 } ] [ [ [ 2 ] [ 2 ] [ + ] compose compose call ] infer short-effect ] unit-test +{ 0 1 } [ [ 2 ] [ 2 ] [ + ] compose compose call ] unit-test-effect TUPLE: custom-error ; @@ -559,4 +551,4 @@ TUPLE: custom-error ; ! This was a false trigger of the undecidable quotation ! recursion bug -[ { 2 1 } ] [ [ find-last-sep ] infer short-effect ] unit-test +{ 2 1 } [ find-last-sep ] unit-test-effect diff --git a/core/io/io.factor b/core/io/io.factor index cc0d2cc8e5..50393f96bb 100644 --- a/core/io/io.factor +++ b/core/io/io.factor @@ -25,7 +25,7 @@ GENERIC: stream-write-table ( table-cells style stream -- ) [ stream-write ] keep stream-nl ; : (stream-copy) ( in out -- ) - 64 1024 * pick stream-read + 64 1024 * pick stream-read-partial [ over stream-write (stream-copy) ] [ 2drop ] if* ; : stream-copy ( in out -- ) diff --git a/core/system/system-docs.factor b/core/system/system-docs.factor index 8c57d0c951..d91a84ec99 100644 --- a/core/system/system-docs.factor +++ b/core/system/system-docs.factor @@ -1,5 +1,5 @@ USING: generic help.markup help.syntax kernel math memory -namespaces sequences kernel.private io.files ; +namespaces sequences kernel.private io.files strings ; IN: system ARTICLE: "os" "System interface" @@ -21,23 +21,27 @@ ARTICLE: "os" "System interface" { $subsection cell-bits } "Reading environment variables:" { $subsection os-env } +{ $subsection os-envs } "Getting the path to the Factor VM and image:" { $subsection vm } { $subsection image } +"Getting the current time:" +{ $subsection millis } "Exiting the Factor VM:" -{ $subsection exit } ; +{ $subsection exit } +{ $see-also "file-streams" "network-streams" "io.launcher" "io.mmap" } ; ABOUT: "os" HELP: cpu -{ $values { "cpu" "a string" } } +{ $values { "cpu" string } } { $description "Outputs a string descriptor of the current CPU architecture. Currently, this set of descriptors is:" { $code "x86.32" "x86.64" "ppc" "arm" } } ; HELP: os -{ $values { "os" "a string" } } +{ $values { "os" string } } { $description "Outputs a string descriptor of the current operating system family. Currently, this set of descriptors is:" { $code @@ -87,17 +91,28 @@ HELP: exit ( n -- ) { $description "Exits the Factor process." } ; HELP: millis ( -- n ) -{ $values { "n" "an integer" } } -{ $description "Outputs the number of milliseconds ellapsed since midnight January 1, 1970." } ; +{ $values { "n" integer } } +{ $description "Outputs the number of milliseconds ellapsed since midnight January 1, 1970." } +{ $notes "This is a low-level word. The " { $vocab-link "calendar" } " vocabulary provides features for date/time arithmetic and formatting." } ; HELP: os-env ( key -- value ) -{ $values { "key" "a string" } { "value" "a string" } } +{ $values { "key" string } { "value" string } } { $description "Looks up the value of a shell environment variable." } { $examples "This is an operating system-specific feature. On Unix, you can do:" { $unchecked-example "\"USER\" os-env print" "jane" } } -{ $errors "Windows CE has no concept of ``environment variables'', so this word throws an error there." } ; +{ $errors "Windows CE has no concept of environment variables, so this word throws an error there." } ; + +HELP: os-envs +{ $values { "assoc" "an association mapping strings to strings" } } +{ $description "Outputs the current set of environment variables." } +{ $notes + "Names and values of environment variables are operating system-specific." +} +{ $errors "Windows CE has no concept of environment variables, so this word throws an error there." } ; + +{ os-env os-envs } related-words HELP: win32? { $values { "?" "a boolean" } } @@ -124,11 +139,11 @@ HELP: cell { $description "Outputs the pointer size in bytes of the current CPU architecture." } ; HELP: cells -{ $values { "m" "an integer" } { "n" "an integer" } } +{ $values { "m" integer } { "n" integer } } { $description "Computes the number of bytes used by " { $snippet "m" } " CPU operand-sized cells." } ; HELP: cell-bits -{ $values { "n" "an integer" } } +{ $values { "n" integer } } { $description "Outputs the number of bits in one CPU operand-sized cell." } ; HELP: bootstrap-cell @@ -136,9 +151,9 @@ HELP: bootstrap-cell { $description "Outputs the pointer size in bytes for the target image (if bootstrapping) or the current CPU architecture (otherwise)." } ; HELP: bootstrap-cells -{ $values { "m" "an integer" } { "n" "an integer" } } +{ $values { "m" integer } { "n" integer } } { $description "Computes the number of bytes used by " { $snippet "m" } " cells in the target image (if bootstrapping) or the current CPU architecture (otherwise)." } ; HELP: bootstrap-cell-bits -{ $values { "n" "an integer" } } +{ $values { "n" integer } } { $description "Outputs the number of bits in one cell in the target image (if bootstrapping) or the current CPU architecture (otherwise)." } ; diff --git a/core/words/words-docs.factor b/core/words/words-docs.factor index 78f9209a18..08ca298d2c 100644 --- a/core/words/words-docs.factor +++ b/core/words/words-docs.factor @@ -161,6 +161,7 @@ $nl { $subsection word? } { $subsection "interned-words" } { $subsection "word-definition" } +{ $subsection "word-props" } { $subsection "word.private" } { $see-also "vocabularies" "vocabs.loader" "definitions" } ; diff --git a/extra/color-picker/color-picker.factor b/extra/color-picker/color-picker.factor index d8a18a6a8e..647c83d667 100755 --- a/extra/color-picker/color-picker.factor +++ b/extra/color-picker/color-picker.factor @@ -18,7 +18,7 @@ TUPLE: color-preview ; { 100 100 } over set-rect-dim ; M: color-preview model-changed - dup control-value over set-gadget-interior relayout-1 ; + swap model-value over set-gadget-interior relayout-1 ; : ( model -- model ) [ [ 256 /f ] map 1 add ] ; diff --git a/extra/help/cookbook/cookbook.factor b/extra/help/cookbook/cookbook.factor index ff8817cde9..854797254f 100644 --- a/extra/help/cookbook/cookbook.factor +++ b/extra/help/cookbook/cookbook.factor @@ -217,7 +217,7 @@ ARTICLE: "cookbook-io" "I/O cookbook" } ; ARTICLE: "cookbook-philosophy" "Factor philosophy" -"Factor is a high-level language with automatic memory management, runtime type checking, and strong typing. Factor code should be as simple as possible, but not simpler. If you are coming to Factor from another programming language, one of your first observations might me related to the amount of code you " { $emphasis "don't" } " have to write." +"Factor is a high-level language with automatic memory management, runtime type checking, and strong typing. Factor code should be as simple as possible, but not simpler. If you are coming to Factor from another programming language, one of your first observations might be related to the amount of code you " { $emphasis "don't" } " have to write." $nl "If you try to write Factor word definitions which are longer than a couple of lines, you will find it hard to keep track of the stack contents. Well-written Factor code is " { $emphasis "factored" } " into short definitions, where each definition is easy to test interactively, and has a clear purpose. Well-chosen word names are critical, and having a thesaurus on hand really helps." $nl diff --git a/extra/help/handbook/handbook.factor b/extra/help/handbook/handbook.factor index 44f932abb2..749a5ed0ec 100644 --- a/extra/help/handbook/handbook.factor +++ b/extra/help/handbook/handbook.factor @@ -131,7 +131,7 @@ ARTICLE: "collections" "Collections" { $subsection "graphs" } { $subsection "buffers" } ; -USE: io.sockets +USING: io.sockets io.launcher io.mmap ; ARTICLE: "io" "Input and output" { $subsection "streams" } @@ -144,7 +144,9 @@ ARTICLE: "io" "Input and output" "Advanced features:" { $subsection "stream-binary" } { $subsection "styles" } -{ $subsection "network-streams" } ; +{ $subsection "network-streams" } +{ $subsection "io.launcher" } +{ $subsection "io.mmap" } ; ARTICLE: "tools" "Developer tools" { $subsection "tools.annotations" } diff --git a/extra/io/launcher/launcher-docs.factor b/extra/io/launcher/launcher-docs.factor new file mode 100644 index 0000000000..cade859a5c --- /dev/null +++ b/extra/io/launcher/launcher-docs.factor @@ -0,0 +1,113 @@ +! Copyright (C) 2007 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: help.markup help.syntax io.launcher quotations kernel ; +IN: io.launcher + +HELP: +command+ +{ $description "Launch descriptor key. A command line string, to be processed by the system's shell." } ; + +HELP: +arguments+ +{ $description "Launch descriptor key. A sequence of command line argument strings. The first element is the program to launch and the remaining arguments are passed to the program without further processing." } ; + +HELP: +detached+ +{ $description "Launch descriptor key. A boolean indicating whether " { $link run-process } " will return immediately, rather than wait for the program to complete." +$nl +"Default value is " { $link f } "." } +{ $notes "Cannot be used with " { $link } "." } +{ $see-also run-detached } ; + +HELP: +environment+ +{ $description "Launch descriptor key. An association mapping strings to strings, specifying environment variables to set for the spawned process. The association is combined with the current environment using the operation specified by the " { $link +environment-mode+ } " launch descriptor key." +$nl +"Default value is an empty association." } ; + +HELP: +environment-mode+ +{ $description "Launch descriptor key. Must equal of the following:" + { $list + { $link prepend-environment } + { $link replace-environment } + { $link append-environment } + } +"Default value is " { $link append-environment } "." +} ; + +HELP: prepend-environment +{ $description "Possible value of " { $link +environment-mode+ } " launch descriptor key. The child process environment consists of the value of the " { $link +environment+ } " key together with the current environment, with entries from the current environment taking precedence." +$nl +"This is used in situations where you want to spawn a child process with some default environment variables set, but allowing the user to override these defaults by changing the environment before launching Factor." } ; + +HELP: replace-environment +{ $description "Possible value of " { $link +environment-mode+ } " launch descriptor key. The child process environment consists of the value of the " { $link +environment+ } " key." +$nl +"This is used in situations where you want full control over a child process environment, perhaps for security or testing." } ; + +HELP: append-environment +{ $description "Possible value of " { $link +environment-mode+ } " launch descriptor key. The child process environment consists of the current environment together with the value of the " { $link +environment+ } " key, with entries from the " { $link +environment+ } " key taking precedence." +$nl +"This is used in situations where you want a spawn child process with some overridden environment variables." } ; + +HELP: default-descriptor +{ $description "Association storing default values for launch descriptor keys." } ; + +HELP: with-descriptor +{ $values { "desc" "a launch descriptor" } { "quot" quotation } } +{ $description "Calls the quotation in a dynamic scope where keys from " { $snippet "desc" } " can be read as variables, and any keys not supplied assume their default value as set in " { $link default-descriptor } "." } ; + +HELP: get-environment +{ $values { "env" "an association" } } +{ $description "Combines the current environment with the value of " { $link +environment+ } " using " { $link +environment-mode+ } "." } ; + +HELP: run-process* +{ $values { "desc" "a launch descriptor" } } +{ $contract "Launches a process using the launch descriptor." } +{ $notes "User code should call " { $link run-process } " instead." } ; + +HELP: >descriptor +{ $values { "obj" object } { "desc" "a launch descriptor" } } +{ $description "Creates a launch descriptor from an object, which must be one of the following:" + { $list + { "a string -- this is wrapped in a launch descriptor with a single " { $link +command+ } " key" } + { "a sequence of strings -- this is wrapped in a launch descriptor with a single " { $link +arguments+ } " key" } + { "an association, used to set launch parameters for additional control" } + } +} ; + +HELP: run-process +{ $values { "obj" object } } +{ $contract "Launches a process. The object can either be a string, a sequence of strings or a launch descriptor. See " { $link >descriptor } " for details." } ; + +HELP: run-detached +{ $values { "obj" object } } +{ $contract "Launches a process without waiting for it to complete. The object can either be a string, a sequence of strings or a launch descriptor. See " { $link >descriptor } " for details." } +{ $notes + "This word is functionally identical to passing a launch descriptor to " { $link run-process } " having the " { $link +detached+ } " key set." +} ; + +HELP: +{ $values { "obj" object } { "stream" "a bidirectional stream" } } +{ $description "Launches a process and redirects its input and output via a paper of pipes which may be read and written as a stream." } +{ $notes "Closing the stream will block until the process exits." } ; + +{ run-process run-detached } related-words + +ARTICLE: "io.launcher" "Launching OS processes" +"The " { $vocab-link "io.launcher" } " vocabulary implements cross-platform process launching." +$nl +"Words which launch processes can take either a command line string, a sequence of command line arguments, or a launch descriptor:" +{ $list + { "strings are wrapped in a launch descriptor with a single " { $link +command+ } " key" } + { "sequences of strings are wrapped in a launch descriptor with a single " { $link +arguments+ } " key" } + { "launch descriptors are associations, which can set extra launch parameters for finer control" } +} +"A launch descriptor is an association containing keys from the below set:" +{ $subsection +command+ } +{ $subsection +arguments+ } +{ $subsection +detached+ } +{ $subsection +environment+ } +{ $subsection +environment-mode+ } +"The following words are used to launch processes:" +{ $subsection run-process } +{ $subsection run-detached } +{ $subsection } ; + +ABOUT: "io.launcher" diff --git a/extra/io/mmap/mmap-docs.factor b/extra/io/mmap/mmap-docs.factor new file mode 100644 index 0000000000..22e403ed31 --- /dev/null +++ b/extra/io/mmap/mmap-docs.factor @@ -0,0 +1,38 @@ +USING: help.markup help.syntax alien math ; +IN: io.mmap + +HELP: mapped-file +{ $class-description "The class of memory-mapped files, opened by " { $link } " and closed by " { $link close-mapped-file } ". The following two slots are of interest to users:" + { $list + { { $link mapped-file-length } " - the length of the mapped file area, in bytes" } + { { $link mapped-file-address } " - an " { $link alien } " pointing at the file's memory area" } + } +} ; + +HELP: +{ $values { "path" "a pathname string" } { "length" integer } { "mmap" mapped-file } } +{ $contract "Opens a file and maps the first " { $snippet "length" } " bytes into memory. The length is permitted to exceed the length of the file on disk, in which case the remaining space is padded with zero bytes." } +{ $notes "You must call " { $link close-mapped-file } " when you are finished working with the returned object, to reclaim resources. The " { $link with-mapped-file } " provides an abstraction which can close the mapped file for you." } +{ $errors "Throws an error if a memory mapping could not be established." } ; + +HELP: (close-mapped-file) +{ $values { "mmap" mapped-file } } +{ $contract "Releases system resources associated with the mapped file. This word should not be called by user code; use " { $link close-mapped-file } " instead." } +{ $errors "Throws an error if a memory mapping could not be established." } ; + +HELP: close-mapped-file +{ $values { "mmap" mapped-file } } +{ $description "Releases system resources associated with the mapped file." } +{ $errors "Throws an error if a memory mapping could not be established." } ; + +ARTICLE: "io.mmap" "Memory-mapped files" +"The " { $vocab-link "io.mmap" } " vocabulary implements support for memory-mapped files." +{ $subsection } +{ $subsection close-mapped-file } +"A combinator which wraps the above two words:" +{ $subsection with-mapped-file } +"Memory mapped files implement the " { $link "sequence-protocol" } " and present themselves as a sequence of bytes. The underlying memory area can also be accessed directly:" +{ $subsection mapped-file-address } +"Data can be read and written from the memory area using alien words. See " { $link "reading-writing-memory" } "." ; + +ABOUT: "io.mmap" diff --git a/extra/io/mmap/mmap.factor b/extra/io/mmap/mmap.factor old mode 100644 new mode 100755 index f9ccd61423..aaa786f6a4 --- a/extra/io/mmap/mmap.factor +++ b/extra/io/mmap/mmap.factor @@ -4,20 +4,31 @@ USING: continuations io.backend kernel quotations sequences system alien sequences.private ; IN: io.mmap -TUPLE: mapped-file length address handle ; +TUPLE: mapped-file length address handle closed? ; -M: mapped-file length mapped-file-length ; +: check-closed ( mapped-file -- mapped-file ) + dup mapped-file-closed? [ + "Mapped file is closed" throw + ] when ; inline + +M: mapped-file length check-closed mapped-file-length ; M: mapped-file nth-unsafe - mapped-file-address swap alien-unsigned-1 ; + check-closed mapped-file-address swap alien-unsigned-1 ; M: mapped-file set-nth-unsafe - mapped-file-address swap set-alien-unsigned-1 ; + check-closed mapped-file-address swap set-alien-unsigned-1 ; INSTANCE: mapped-file sequence HOOK: io-backend ( path length -- mmap ) -HOOK: close-mapped-file io-backend ( mmap -- ) + +HOOK: (close-mapped-file) io-backend ( mmap -- ) + +: close-mapped-file ( mmap -- ) + check-closed + t over set-mapped-file-closed? + (close-mapped-file) ; : with-mapped-file ( path length quot -- ) >r r> diff --git a/extra/io/unix/mmap/mmap.factor b/extra/io/unix/mmap/mmap.factor index 50e928f16d..d7dcad67d9 100644 --- a/extra/io/unix/mmap/mmap.factor +++ b/extra/io/unix/mmap/mmap.factor @@ -15,7 +15,7 @@ M: unix-io ( path length -- obj ) dup PROT_READ PROT_WRITE bitor MAP_FILE MAP_SHARED bitor r> mmap-open \ mapped-file construct-boa ; -M: unix-io close-mapped-file ( mmap -- ) +M: unix-io (close-mapped-file) ( mmap -- ) [ mapped-file-address ] keep [ mapped-file-length munmap ] keep mapped-file-handle close diff --git a/extra/io/windows/launcher/launcher.factor b/extra/io/windows/launcher/launcher.factor index b7a32652f2..f586976bb6 100755 --- a/extra/io/windows/launcher/launcher.factor +++ b/extra/io/windows/launcher/launcher.factor @@ -1,8 +1,7 @@ -USING: alien alien.c-types arrays continuations -destructors io io.windows libc -io.nonblocking io.streams.duplex windows.types math -windows.kernel32 windows namespaces io.launcher kernel -sequences io.windows.nt.backend windows.errors assocs ; +USING: alien alien.c-types arrays continuations destructors io +io.windows libc io.nonblocking io.streams.duplex windows.types +math windows.kernel32 windows namespaces io.launcher kernel +sequences windows.errors assocs splitting system ; IN: io.windows.launcher ! From MSDN: "Handles in PROCESS_INFORMATION must be closed with CloseHandle when they are no longer needed." @@ -52,19 +51,30 @@ TUPLE: CreateProcess-args CreateProcess-args-lpProcessInformation } get-slots CreateProcess win32-error=0/f ; -: fill-lpCommandLine +: join-arguments ( args -- cmd-line ) + [ "\"" swap "\"" 3append ] map " " join ; + +: app-name/cmd-line ( -- app-name cmd-line ) +command+ get [ - [ - +arguments+ get [ CHAR: \s , ] [ - CHAR: " , - [ dup CHAR: " = [ CHAR: \\ , ] when , ] each - CHAR: " , - ] interleave - ] "" make - ] unless* over set-CreateProcess-args-lpCommandLine ; + " " split1 + ] [ + +arguments+ get unclip swap join-arguments + ] if* ; + +: cmd-line ( -- cmd-line ) + +command+ get [ +arguments+ get join-arguments ] unless* ; + +: fill-lpApplicationName + app-name/cmd-line + pick set-CreateProcess-args-lpCommandLine + over set-CreateProcess-args-lpApplicationName ; + +: fill-lpCommandLine + cmd-line over set-CreateProcess-args-lpCommandLine ; : fill-dwCreateFlags - CREATE_UNICODE_ENVIRONMENT + 0 + pass-environment? [ CREATE_UNICODE_ENVIRONMENT bitor ] when +detached+ get [ DETACHED_PROCESS bitor ] when over set-CreateProcess-args-dwCreateFlags ; @@ -86,7 +96,11 @@ TUPLE: CreateProcess-args M: windows-io run-process* ( desc -- ) [ default-CreateProcess-args - fill-lpCommandLine + wince? [ + fill-lpApplicationName + ] [ + fill-lpCommandLine + ] if fill-dwCreateFlags fill-lpEnvironment dup call-CreateProcess diff --git a/extra/io/windows/mmap/mmap.factor b/extra/io/windows/mmap/mmap.factor old mode 100644 new mode 100755 index 2742d1b006..20c6a6fc22 --- a/extra/io/windows/mmap/mmap.factor +++ b/extra/io/windows/mmap/mmap.factor @@ -1,7 +1,7 @@ USING: alien alien.c-types alien.syntax arrays continuations destructors generic io.mmap io.nonblocking io.windows kernel libc math namespaces quotations sequences windows -windows.advapi32 windows.kernel32 ; +windows.advapi32 windows.kernel32 io.backend ; IN: io.windows.mmap TYPEDEF: TOKEN_PRIVILEGES* PTOKEN_PRIVILEGES @@ -51,12 +51,16 @@ TYPEDEF: TOKEN_PRIVILEGES* PTOKEN_PRIVILEGES dup length f f AdjustTokenPrivileges win32-error=0/f ] with-process-token ; -: with-privileges ( seq quot -- ) +HOOK: with-privileges io-backend ( seq quot -- ) inline + +M: windows-nt-io with-privileges over [ [ t set-privilege ] each ] curry compose swap [ [ f set-privilege ] each ] curry [ ] cleanup ; -: mmap-open ( path access-mode create-mode flProtect access length -- handle handle address ) - drop +M: windows-ce-io with-privileges + nip call ; + +: mmap-open ( path access-mode create-mode flProtect access -- handle handle address ) { "SeCreateGlobalPrivilege" "SeLockMemoryPrivilege" } [ >r >r open-file dup f r> 0 0 f CreateFileMapping [ win32-error=0/f ] keep @@ -68,20 +72,17 @@ TYPEDEF: TOKEN_PRIVILEGES* PTOKEN_PRIVILEGES M: windows-io ( path length -- mmap ) [ - [ - >r - GENERIC_WRITE GENERIC_READ bitor - OPEN_ALWAYS - PAGE_READWRITE SEC_COMMIT bitor - FILE_MAP_ALL_ACCESS r> mmap-open - ] keep - -roll -rot 2array \ mapped-file construct-boa + swap + GENERIC_WRITE GENERIC_READ bitor + OPEN_ALWAYS + PAGE_READWRITE SEC_COMMIT bitor + FILE_MAP_ALL_ACCESS mmap-open + -rot 2array + \ mapped-file construct-boa ] with-destructors ; -M: windows-io close-mapped-file ( mapped-file -- ) +M: windows-io (close-mapped-file) ( mapped-file -- ) [ - dup mapped-file-handle [ - close-always - ] each + dup mapped-file-handle [ close-always ] each mapped-file-address UnmapViewOfFile win32-error=0/f ] with-destructors ; diff --git a/extra/io/windows/windows-tests.factor b/extra/io/windows/windows-tests.factor new file mode 100755 index 0000000000..4c090590df --- /dev/null +++ b/extra/io/windows/windows-tests.factor @@ -0,0 +1,16 @@ +USING: io.files kernel tools.test ; +IN: temporary + +[ "c:\\foo\\" ] [ "c:\\foo\\bar" parent-directory ] unit-test +[ "c:\\" ] [ "c:\\foo\\" parent-directory ] unit-test +[ "c:\\" ] [ "c:\\foo" parent-directory ] unit-test +! { "c:" "c:\\" "c:/" } [ directory ] each -- all do the same thing +[ "c:\\" ] [ "c:\\" parent-directory ] unit-test +[ "Z:\\" ] [ "Z:\\" parent-directory ] unit-test +[ "c:" ] [ "c:" parent-directory ] unit-test +[ "Z:" ] [ "Z:" parent-directory ] unit-test +[ t ] [ "c:\\" root-directory? ] unit-test +[ t ] [ "Z:\\" root-directory? ] unit-test +[ f ] [ "c:\\foo" root-directory? ] unit-test +[ f ] [ "." root-directory? ] unit-test +[ f ] [ ".." root-directory? ] unit-test diff --git a/extra/models/models-tests.factor b/extra/models/models-tests.factor old mode 100644 new mode 100755 index e47e1a66c3..ea615d2f9a --- a/extra/models/models-tests.factor +++ b/extra/models/models-tests.factor @@ -6,7 +6,7 @@ TUPLE: model-tester hit? ; : model-tester construct-empty ; -M: model-tester model-changed t swap set-model-tester-hit? ; +M: model-tester model-changed nip t swap set-model-tester-hit? ; [ T{ model-tester f t } ] [ diff --git a/extra/models/models.factor b/extra/models/models.factor old mode 100644 new mode 100755 index d76269eaf0..9c9ddd13e0 --- a/extra/models/models.factor +++ b/extra/models/models.factor @@ -3,10 +3,10 @@ USING: generic kernel math sequences timers arrays assocs ; IN: models -TUPLE: model value connections dependencies ref ; +TUPLE: model value connections dependencies ref locked? ; : ( value -- model ) - V{ } clone V{ } clone 0 model construct-boa ; + V{ } clone V{ } clone 0 f model construct-boa ; M: model equal? 2drop f ; @@ -49,7 +49,7 @@ DEFER: remove-connection drop ] if ; -GENERIC: model-changed ( observer -- ) +GENERIC: model-changed ( model observer -- ) : add-connection ( observer model -- ) dup model-connections empty? [ dup activate-model ] when @@ -60,11 +60,26 @@ GENERIC: model-changed ( observer -- ) dup model-connections empty? [ dup deactivate-model ] when drop ; -GENERIC: set-model ( value model -- ) +: with-locked-model ( model quot -- ) + swap + t over set-model-locked? + slip + f swap set-model-locked? ; inline -M: model set-model - [ set-model-value ] keep - model-connections [ model-changed ] each ; +GENERIC: update-model ( model -- ) + +M: model update-model drop ; + +: set-model ( value model -- ) + dup model-locked? [ + 2drop + ] [ + dup [ + [ set-model-value ] keep + [ update-model ] keep + dup model-connections [ model-changed ] curry* each + ] with-locked-model + ] if ; : ((change-model)) ( model quot -- newvalue model ) over >r >r model-value r> call r> ; inline @@ -87,10 +102,10 @@ TUPLE: filter model quot ; [ add-dependency ] keep ; M: filter model-changed - dup filter-model model-value over filter-quot call + swap model-value over filter-quot call swap set-model ; -M: filter model-activated model-changed ; +M: filter model-activated dup filter-model swap model-changed ; TUPLE: compose ; @@ -103,11 +118,13 @@ TUPLE: compose ; : set-composed-value >r model-dependencies r> 2each ; inline M: compose model-changed + nip dup [ model-value ] composed-value swap delegate set-model ; -M: compose model-activated model-changed ; +M: compose model-activated dup model-changed ; -M: compose set-model [ set-model ] set-composed-value ; +M: compose update-model + dup model-value swap [ set-model ] set-composed-value ; TUPLE: mapping assoc ; @@ -117,13 +134,15 @@ TUPLE: mapping assoc ; tuck set-mapping-assoc ; M: mapping model-changed + nip dup mapping-assoc [ model-value ] assoc-map swap delegate set-model ; -M: mapping model-activated model-changed ; +M: mapping model-activated dup model-changed ; -M: mapping set-model - mapping-assoc [ swapd at set-model ] curry assoc-each ; +M: mapping update-model + dup model-value swap mapping-assoc + [ swapd at set-model ] curry assoc-each ; TUPLE: history back forward ; @@ -161,10 +180,9 @@ TUPLE: delay model timeout ; f delay construct-model [ set-delay-timeout ] keep [ set-delay-model ] 2keep - [ add-dependency ] keep - dup update-delay-model ; + [ add-dependency ] keep ; -M: delay model-changed 0 over delay-timeout add-timer ; +M: delay model-changed nip 0 over delay-timeout add-timer ; M: delay model-activated update-delay-model ; diff --git a/extra/tools/test/inference/inference.factor b/extra/tools/test/inference/inference.factor new file mode 100755 index 0000000000..5c222a1b6e --- /dev/null +++ b/extra/tools/test/inference/inference.factor @@ -0,0 +1,9 @@ +USING: effects sequences kernel arrays quotations inference +tools.test ; +IN: tools.test.inference + +: short-effect + dup effect-in length swap effect-out length 2array ; + +: unit-test-effect ( effect quot -- ) + >r 1quotation r> [ infer short-effect ] curry unit-test ; diff --git a/extra/tools/test/ui/ui.factor b/extra/tools/test/ui/ui.factor new file mode 100755 index 0000000000..0376e7f4c7 --- /dev/null +++ b/extra/tools/test/ui/ui.factor @@ -0,0 +1,16 @@ +USING: dlists ui.gadgets kernel ui namespaces io.streams.string +io ; +IN: tools.test.ui + +! We can't print to stdio here because that might be a pane +! stream, and our graft-queue rebinding here would be captured +! by code adding children to the pane... +: with-grafted-gadget ( gadget quot -- ) + [ + \ graft-queue [ + over + graft notify-queued + swap slip + ungraft notify-queued + ] with-variable + ] string-out print ; diff --git a/extra/ui/cocoa/cocoa.factor b/extra/ui/cocoa/cocoa.factor old mode 100644 new mode 100755 index c7a4b62abb..52722a2fab --- a/extra/ui/cocoa/cocoa.factor +++ b/extra/ui/cocoa/cocoa.factor @@ -62,7 +62,6 @@ M: cocoa-ui-backend set-title ( string world -- ) M: cocoa-ui-backend (open-world-window) ( world -- ) dup gadget-window - dup start-world dup auto-position world-handle second f -> makeKeyAndOrderFront: ; diff --git a/extra/ui/gadgets/books/books-tests.factor b/extra/ui/gadgets/books/books-tests.factor new file mode 100755 index 0000000000..a7226299ab --- /dev/null +++ b/extra/ui/gadgets/books/books-tests.factor @@ -0,0 +1,4 @@ +IN: temporary +USING: tools.test.inference ui.gadgets.books ; + +{ 2 1 } [ ] unit-test-effect diff --git a/extra/ui/gadgets/books/books.factor b/extra/ui/gadgets/books/books.factor index f9e3262e8e..95b1eed89d 100755 --- a/extra/ui/gadgets/books/books.factor +++ b/extra/ui/gadgets/books/books.factor @@ -10,15 +10,14 @@ TUPLE: book ; : current-page ( book -- gadget ) [ control-value ] keep nth-gadget ; -M: book model-changed ( book -- ) +M: book model-changed + nip dup hide-all dup current-page show-gadget relayout ; : ( pages model -- book ) - book construct-control - [ add-gadgets ] keep - [ model-changed ] keep ; + book construct-control [ add-gadgets ] keep ; M: book pref-dim* gadget-children pref-dims max-dim ; diff --git a/extra/ui/gadgets/buttons/buttons-tests.factor b/extra/ui/gadgets/buttons/buttons-tests.factor index b8cf5892eb..8565098e70 100755 --- a/extra/ui/gadgets/buttons/buttons-tests.factor +++ b/extra/ui/gadgets/buttons/buttons-tests.factor @@ -1,6 +1,7 @@ IN: temporary USING: ui.commands ui.gadgets.buttons ui.gadgets.labels -ui.gadgets tools.test namespaces sequences kernel models ; +ui.gadgets tools.test namespaces sequences kernel models +tools.test.inference ; TUPLE: foo-gadget ; @@ -27,6 +28,12 @@ T{ foo-gadget } "t" set } "religion" set ] unit-test +{ 2 1 } [ ] unit-test-effect + +{ 2 1 } [ ] unit-test-effect + +{ 2 1 } [ ] unit-test-effect + [ 0 ] [ "religion" get gadget-child radio-control-value ] unit-test diff --git a/extra/ui/gadgets/buttons/buttons.factor b/extra/ui/gadgets/buttons/buttons.factor index 6c10a11d3c..a196173852 100755 --- a/extra/ui/gadgets/buttons/buttons.factor +++ b/extra/ui/gadgets/buttons/buttons.factor @@ -141,7 +141,7 @@ TUPLE: checkbox ; dup checkbox-theme ; M: checkbox model-changed - dup control-value over set-button-selected? relayout-1 ; + swap model-value over set-button-selected? relayout-1 ; TUPLE: radio-paint color ; @@ -178,7 +178,7 @@ TUPLE: radio-control value ; tuck set-radio-control-value ; inline M: radio-control model-changed - dup control-value + swap model-value over radio-control-value = over set-button-selected? relayout-1 ; diff --git a/extra/ui/gadgets/editors/editors-docs.factor b/extra/ui/gadgets/editors/editors-docs.factor index 18e4e62ccc..42d300d330 100755 --- a/extra/ui/gadgets/editors/editors-docs.factor +++ b/extra/ui/gadgets/editors/editors-docs.factor @@ -16,9 +16,6 @@ $nl { { $link editor-focused? } " - a boolean." } } } ; -HELP: loc-monitor -{ $class-description "Instances of this class are used internally by " { $link editor } " controls to redraw the editor when the caret or mark is moved by calling " { $link set-model } " on " { $link editor-caret } " or " { $link editor-mark } "." } ; - HELP: { $values { "editor" "a new " { $link editor } } } { $description "Creates a new " { $link editor } " with an empty document." } ; diff --git a/extra/ui/gadgets/editors/editors-tests.factor b/extra/ui/gadgets/editors/editors-tests.factor old mode 100644 new mode 100755 index daaeac6fad..a38ca6044e --- a/extra/ui/gadgets/editors/editors-tests.factor +++ b/extra/ui/gadgets/editors/editors-tests.factor @@ -1,38 +1,33 @@ USING: ui.gadgets.editors tools.test kernel io io.streams.plain -io.streams.string definitions namespaces ui.gadgets -ui.gadgets.grids prettyprint documents ui.gestures ; - -[ t ] [ - "editor" set - "editor" get graft* - "editor" get [ \ = see ] with-stream - "editor" get editor-string [ \ = see ] string-out = - "editor" get ungraft* -] unit-test +definitions namespaces ui.gadgets +ui.gadgets.grids prettyprint documents ui.gestures +tools.test.inference tools.test.ui ; [ "foo bar" ] [ "editor" set - "editor" get graft* - "foo bar" "editor" get set-editor-string - "editor" get T{ one-line-elt } select-elt - "editor" get gadget-selection - "editor" get ungraft* + "editor" get [ + "foo bar" "editor" get set-editor-string + "editor" get T{ one-line-elt } select-elt + "editor" get gadget-selection + ] with-grafted-gadget ] unit-test [ "baz quux" ] [ "editor" set - "editor" get graft* - "foo bar\nbaz quux" "editor" get set-editor-string - "editor" get T{ one-line-elt } select-elt - "editor" get gadget-selection - "editor" get ungraft* + "editor" get [ + "foo bar\nbaz quux" "editor" get set-editor-string + "editor" get T{ one-line-elt } select-elt + "editor" get gadget-selection + ] with-grafted-gadget ] unit-test [ ] [ "editor" set - "editor" get graft* - "foo bar\nbaz quux" "editor" get set-editor-string - 4 hand-click# set - "editor" get position-caret - "editor" get ungraft* + "editor" get [ + "foo bar\nbaz quux" "editor" get set-editor-string + 4 hand-click# set + "editor" get position-caret + ] with-grafted-gadget ] unit-test + +{ 0 1 } [ ] unit-test-effect diff --git a/extra/ui/gadgets/editors/editors.factor b/extra/ui/gadgets/editors/editors.factor index 9e2a258c0f..65758ab54c 100755 --- a/extra/ui/gadgets/editors/editors.factor +++ b/extra/ui/gadgets/editors/editors.factor @@ -2,10 +2,9 @@ ! See http://factorcode.org/license.txt for BSD license. USING: arrays documents ui.clipboards ui.commands ui.gadgets ui.gadgets.borders ui.gadgets.buttons ui.gadgets.labels -ui.gadgets.scrollers ui.gadgets.theme -ui.render ui.gestures io kernel math models namespaces opengl -opengl.gl sequences strings io.styles math.vectors sorting -colors combinators ; +ui.gadgets.scrollers ui.gadgets.theme ui.render ui.gestures io +kernel math models namespaces opengl opengl.gl sequences strings +io.styles math.vectors sorting colors combinators ; IN: ui.gadgets.editors TUPLE: editor @@ -14,15 +13,11 @@ font color caret-color selection-color caret mark focused? ; -TUPLE: loc-monitor editor ; - -: ( editor -- loc ) - loc-monitor construct-boa - { 0 0 } [ add-connection ] keep ; +: ( -- loc ) { 0 0 } ; : init-editor-locs ( editor -- ) - dup over set-editor-caret - dup swap set-editor-mark ; + over set-editor-caret + swap set-editor-mark ; : editor-theme ( editor -- ) black over set-editor-color @@ -48,10 +43,14 @@ TUPLE: source-editor ; : source-editor construct-editor ; : activate-editor-model ( editor model -- ) - dup activate-model swap gadget-model add-loc ; + 2dup add-connection + dup activate-model + swap gadget-model add-loc ; : deactivate-editor-model ( editor model -- ) - dup deactivate-model swap gadget-model remove-loc ; + 2dup remove-connection + dup deactivate-model + swap gadget-model remove-loc ; M: editor graft* dup @@ -63,12 +62,6 @@ M: editor ungraft* dup editor-caret deactivate-editor-model dup editor-mark deactivate-editor-model ; -M: editor model-changed - dup gadget-model - over editor-caret [ over validate-loc ] (change-model) - over editor-mark [ over validate-loc ] (change-model) - drop editor-self relayout ; - : editor-caret* ( editor -- loc ) editor-caret model-value ; : editor-mark* ( editor -- loc ) editor-mark model-value ; @@ -129,15 +122,11 @@ M: editor model-changed line-height 0 swap 2array ; : scroll>caret ( editor -- ) - dup gadget-grafted? [ + dup gadget-graft-state second [ dup caret-loc over caret-dim { 1 0 } v+ over scroll>rect ] when drop ; -M: loc-monitor model-changed - loc-monitor-editor editor-self - dup relayout-1 scroll>caret ; - : draw-caret ( -- ) editor get editor-focused? [ editor get @@ -219,6 +208,22 @@ M: editor draw-gadget* M: editor pref-dim* dup editor-font* swap control-value text-dim ; +: contents-changed + editor-self swap + over editor-caret [ over validate-loc ] (change-model) + over editor-mark [ over validate-loc ] (change-model) + drop relayout ; + +: caret/mark-changed + nip editor-self dup relayout-1 scroll>caret ; + +M: editor model-changed + { + { [ 2dup gadget-model eq? ] [ contents-changed ] } + { [ 2dup editor-caret eq? ] [ caret/mark-changed ] } + { [ 2dup editor-mark eq? ] [ caret/mark-changed ] } + } cond ; + M: editor gadget-selection? selection-start/end = not ; @@ -421,16 +426,6 @@ editor "selection" f { { T{ key-down f { S+ C+ } "END" } select-end-of-document } } define-command-map -! Editors support the stream output protocol -M: editor stream-write1 >r 1string r> stream-write ; - -M: editor stream-write - editor-self dup end-of-document user-input ; - -M: editor stream-close drop ; - -M: editor stream-flush drop ; - ! Fields are like editors except they edit an external model TUPLE: field model editor ; @@ -453,5 +448,6 @@ M: field ungraft* dup field-editor gadget-model remove-connection ; M: field model-changed + nip dup field-editor editor-string swap field-model set-model ; diff --git a/extra/ui/gadgets/gadgets-tests.factor b/extra/ui/gadgets/gadgets-tests.factor old mode 100644 new mode 100755 index 2a4527fbf2..48bb3718cb --- a/extra/ui/gadgets/gadgets-tests.factor +++ b/extra/ui/gadgets/gadgets-tests.factor @@ -1,6 +1,8 @@ IN: temporary USING: ui.gadgets ui.gadgets.packs ui.gadgets.worlds tools.test -namespaces models kernel ; +namespaces models kernel tools.test.inference dlists math +math.parser ui sequences hashtables assocs io arrays +prettyprint io.streams.string ; [ T{ rect f { 10 10 } { 20 20 } } ] [ @@ -49,11 +51,11 @@ C: fooey "a" get "b" get add-gadget "c" set "b" get "c" get add-gadget - + ! position a and b { 100 200 } "a" get set-rect-loc { 200 100 } "b" get set-rect-loc - + ! give c a loc, it doesn't matter { -1000 23 } "c" get set-rect-loc @@ -108,3 +110,95 @@ C: fooey { 1 1 } "g4" get set-rect-dim [ t ] [ { 25 25 } "g1" get pick-up "g4" get eq? ] unit-test + +TUPLE: mock-gadget graft-called ungraft-called ; + +: + 0 0 mock-gadget construct-boa over set-delegate ; + +M: mock-gadget graft* + dup mock-gadget-graft-called 1+ + swap set-mock-gadget-graft-called ; + +M: mock-gadget ungraft* + dup mock-gadget-ungraft-called 1+ + swap set-mock-gadget-ungraft-called ; + +! We can't print to stdio here because that might be a pane +! stream, and our graft-queue rebinding here would be captured +! by code adding children to the pane... +[ + \ graft-queue [ + [ ] [ dup queue-graft unqueue-graft ] unit-test + [ t ] [ graft-queue dlist-empty? ] unit-test + ] with-variable + + \ graft-queue [ + [ t ] [ graft-queue dlist-empty? ] unit-test + + "g" set + [ ] [ "g" get queue-graft ] unit-test + [ f ] [ graft-queue dlist-empty? ] unit-test + [ { f t } ] [ "g" get gadget-graft-state ] unit-test + [ ] [ "g" get graft-later ] unit-test + [ { f t } ] [ "g" get gadget-graft-state ] unit-test + [ ] [ "g" get ungraft-later ] unit-test + [ { f f } ] [ "g" get gadget-graft-state ] unit-test + [ t ] [ graft-queue dlist-empty? ] unit-test + [ ] [ "g" get ungraft-later ] unit-test + [ ] [ "g" get graft-later ] unit-test + [ ] [ notify-queued ] unit-test + [ { t t } ] [ "g" get gadget-graft-state ] unit-test + [ t ] [ graft-queue dlist-empty? ] unit-test + [ ] [ "g" get graft-later ] unit-test + [ 1 ] [ "g" get mock-gadget-graft-called ] unit-test + [ ] [ "g" get ungraft-later ] unit-test + [ { t f } ] [ "g" get gadget-graft-state ] unit-test + [ ] [ notify-queued ] unit-test + [ 1 ] [ "g" get mock-gadget-ungraft-called ] unit-test + [ { f f } ] [ "g" get gadget-graft-state ] unit-test + ] with-variable + + : add-some-children + 3 [ + over over set-gadget-model + dup "g" get add-gadget + swap 1+ number>string set + ] each ; + + : status-flags + { "g" "1" "2" "3" } [ get gadget-graft-state ] map prune ; + + : notify-combo ( ? ? -- ) + nl "===== Combo: " write 2dup 2array . nl + \ graft-queue [ + "g" set + [ ] [ add-some-children ] unit-test + [ V{ { f f } } ] [ status-flags ] unit-test + [ ] [ "g" get graft ] unit-test + [ V{ { f t } } ] [ status-flags ] unit-test + dup [ [ ] [ notify-queued ] unit-test ] when + [ ] [ "g" get clear-gadget ] unit-test + [ [ 1 ] [ graft-queue dlist-length ] unit-test ] unless + [ [ ] [ notify-queued ] unit-test ] when + [ ] [ add-some-children ] unit-test + [ { f t } ] [ "1" get gadget-graft-state ] unit-test + [ { f t } ] [ "2" get gadget-graft-state ] unit-test + [ { f t } ] [ "3" get gadget-graft-state ] unit-test + [ ] [ [ "x" print notify ] graft-queue swap dlist-slurp ] unit-test + [ ] [ notify-queued ] unit-test + [ V{ { t t } } ] [ status-flags ] unit-test + ] with-variable ; + + { { f f } { f t } { t f } { t t } } [ notify-combo ] assoc-each +] string-out print + +{ 0 1 } [ ] unit-test-effect +{ 1 0 } [ unparent ] unit-test-effect +{ 2 0 } [ add-gadget ] unit-test-effect +{ 2 0 } [ add-gadgets ] unit-test-effect +{ 1 0 } [ clear-gadget ] unit-test-effect + +{ 1 0 } [ relayout ] unit-test-effect +{ 1 0 } [ relayout-1 ] unit-test-effect +{ 1 1 } [ pref-dim ] unit-test-effect diff --git a/extra/ui/gadgets/gadgets.factor b/extra/ui/gadgets/gadgets.factor index 526c4864c8..9929cece29 100755 --- a/extra/ui/gadgets/gadgets.factor +++ b/extra/ui/gadgets/gadgets.factor @@ -41,8 +41,8 @@ M: array rect-dim drop { 0 0 } ; (rect-union) ; TUPLE: gadget -pref-dim parent children orientation state focus -visible? root? clipped? grafted? +pref-dim parent children orientation focus +visible? root? clipped? layout-state graft-state interior boundary model ; @@ -50,7 +50,7 @@ M: gadget equal? 2drop f ; M: gadget hashcode* drop gadget hashcode* ; -M: gadget model-changed drop ; +M: gadget model-changed 2drop ; : gadget-child ( gadget -- child ) gadget-children first ; @@ -59,10 +59,11 @@ M: gadget model-changed drop ; : ( -- rect ) { 0 0 } dup ; : ( -- gadget ) - { 0 1 } t { + { 0 1 } t { f f } { set-delegate set-gadget-orientation set-gadget-visible? + set-gadget-graft-state } gadget construct ; : construct-gadget ( class -- tuple ) @@ -70,7 +71,7 @@ M: gadget model-changed drop ; : activate-control ( gadget -- ) dup gadget-model dup [ 2dup add-connection ] when drop - model-changed ; + dup gadget-model swap model-changed ; : deactivate-control ( gadget -- ) dup gadget-model dup [ 2dup remove-connection ] when 2drop ; @@ -169,33 +170,33 @@ M: array gadget-text* : gadget-text ( gadget -- string ) [ gadget-text* ] "" make ; : invalidate ( gadget -- ) - \ invalidate swap set-gadget-state ; + \ invalidate swap set-gadget-layout-state ; : forget-pref-dim ( gadget -- ) f swap set-gadget-pref-dim ; -: invalid ( -- queue ) \ invalid get-global ; +: layout-queue ( -- queue ) \ layout-queue get ; -: add-invalid ( gadget -- ) +: layout-later ( gadget -- ) #! When unit testing gadgets without the UI running, the #! invalid queue is not initialized and we simply ignore #! invalidation requests. - invalid [ push-front ] [ drop ] if* ; + layout-queue [ push-front ] [ drop ] if* ; DEFER: relayout : invalidate* ( gadget -- ) - \ invalidate* over set-gadget-state + \ invalidate* over set-gadget-layout-state dup forget-pref-dim dup gadget-root? - [ add-invalid ] [ gadget-parent [ relayout ] when* ] if ; + [ layout-later ] [ gadget-parent [ relayout ] when* ] if ; : relayout ( gadget -- ) - dup gadget-state \ invalidate* eq? + dup gadget-layout-state \ invalidate* eq? [ drop ] [ invalidate* ] if ; : relayout-1 ( gadget -- ) - dup gadget-state - [ drop ] [ dup invalidate add-invalid ] if ; + dup gadget-layout-state + [ drop ] [ dup invalidate layout-later ] if ; : show-gadget t swap set-gadget-visible? ; @@ -215,7 +216,8 @@ DEFER: relayout GENERIC: pref-dim* ( gadget -- dim ) : ?set-gadget-pref-dim ( dim gadget -- ) - dup gadget-state [ 2drop ] [ set-gadget-pref-dim ] if ; + dup gadget-layout-state + [ 2drop ] [ set-gadget-pref-dim ] if ; : pref-dim ( gadget -- dim ) dup gadget-pref-dim [ ] [ @@ -232,36 +234,59 @@ M: gadget layout* drop ; : prefer ( gadget -- ) dup pref-dim swap set-layout-dim ; -: validate ( gadget -- ) f swap set-gadget-state ; +: validate ( gadget -- ) f swap set-gadget-layout-state ; : layout ( gadget -- ) - dup gadget-state [ + dup gadget-layout-state [ dup validate dup layout* dup [ layout ] each-child ] when drop ; +: graft-queue \ graft-queue get ; + +: unqueue-graft ( gadget -- ) + dup graft-queue dlist-delete [ "Not queued" throw ] unless + dup gadget-graft-state first { t t } { f f } ? + swap set-gadget-graft-state ; + +: queue-graft ( gadget -- ) + { f t } over set-gadget-graft-state + graft-queue push-front ; + +: queue-ungraft ( gadget -- ) + { t f } over set-gadget-graft-state + graft-queue push-front ; + +: graft-later ( gadget -- ) + dup gadget-graft-state { + { { f t } [ drop ] } + { { t t } [ drop ] } + { { t f } [ unqueue-graft ] } + { { f f } [ queue-graft ] } + } case ; + +: ungraft-later ( gadget -- ) + dup gadget-graft-state { + { { f f } [ drop ] } + { { t f } [ drop ] } + { { f t } [ unqueue-graft ] } + { { t t } [ queue-ungraft ] } + } case ; + GENERIC: graft* ( gadget -- ) M: gadget graft* drop ; : graft ( gadget -- ) - t over set-gadget-grafted? - dup graft* - dup activate-control - [ graft ] each-child ; + dup graft-later [ graft ] each-child ; GENERIC: ungraft* ( gadget -- ) M: gadget ungraft* drop ; : ungraft ( gadget -- ) - dup gadget-grafted? [ - dup [ ungraft ] each-child - dup deactivate-control - dup ungraft* - f over set-gadget-grafted? - ] when drop ; + dup [ ungraft ] each-child ungraft-later ; : (unparent) ( gadget -- ) dup ungraft @@ -272,7 +297,14 @@ M: gadget ungraft* drop ; tuck gadget-focus eq? [ f swap set-gadget-focus ] [ drop ] if ; +SYMBOL: in-layout? + +: not-in-layout + in-layout? get + [ "Cannot add/remove gadgets in layout*" throw ] when ; + : unparent ( gadget -- ) + not-in-layout [ dup gadget-parent dup [ over (unparent) @@ -290,6 +322,7 @@ M: gadget ungraft* drop ; f swap set-gadget-children ; : clear-gadget ( gadget -- ) + not-in-layout dup (clear-gadget) relayout ; : ((add-gadget)) ( gadget box -- ) @@ -299,12 +332,14 @@ M: gadget ungraft* drop ; over unparent dup pick set-gadget-parent [ ((add-gadget)) ] 2keep - gadget-grafted? [ graft ] [ drop ] if ; + gadget-graft-state second [ graft ] [ drop ] if ; : add-gadget ( gadget parent -- ) + not-in-layout [ (add-gadget) ] keep relayout ; : add-gadgets ( seq parent -- ) + not-in-layout swap [ over (add-gadget) ] each relayout ; : parents ( gadget -- seq ) diff --git a/extra/ui/gadgets/incremental/incremental.factor b/extra/ui/gadgets/incremental/incremental.factor old mode 100644 new mode 100755 index 0e15515750..a5c7431d36 --- a/extra/ui/gadgets/incremental/incremental.factor +++ b/extra/ui/gadgets/incremental/incremental.factor @@ -11,17 +11,18 @@ IN: ui.gadgets.incremental ! pack-gap. ! The cursor is the current size of the incremental pack. -! New gadgets are added at cursor-cursor*gadget-orientation. +! New gadgets are added at +! incremental-cursor gadget-orientation v* TUPLE: incremental cursor ; : ( pack -- incremental ) - incremental construct-empty - [ set-gadget-delegate ] keep - dup delegate pref-dim over set-incremental-cursor ; + dup pref-dim + { set-gadget-delegate set-incremental-cursor } + incremental construct ; M: incremental pref-dim* - dup gadget-state [ + dup gadget-layout-state [ dup delegate pref-dim over set-incremental-cursor ] when incremental-cursor ; @@ -39,9 +40,11 @@ M: incremental pref-dim* swap set-rect-loc ; : prefer-incremental ( gadget -- ) - dup forget-pref-dim dup pref-dim over set-rect-dim layout ; + dup forget-pref-dim dup pref-dim over set-rect-dim + layout ; : add-incremental ( gadget incremental -- ) + not-in-layout 2dup (add-gadget) over prefer-incremental 2dup incremental-loc @@ -50,6 +53,8 @@ M: incremental pref-dim* gadget-parent [ invalidate* ] when* ; : clear-incremental ( incremental -- ) - dup (clear-gadget) dup forget-pref-dim + not-in-layout + dup (clear-gadget) + dup forget-pref-dim { 0 0 } over set-incremental-cursor gadget-parent [ relayout ] when* ; diff --git a/extra/ui/gadgets/labels/labels.factor b/extra/ui/gadgets/labels/labels.factor index 4e1a4712ba..2ac0240ed1 100755 --- a/extra/ui/gadgets/labels/labels.factor +++ b/extra/ui/gadgets/labels/labels.factor @@ -40,7 +40,7 @@ M: label gadget-text* label-string % ; TUPLE: label-control ; M: label-control model-changed - dup control-value over set-label-text relayout ; + swap model-value over set-label-text relayout ; : ( model -- gadget ) ""