Merge erg@factorcode.org:/git/erg

db4
Doug Coleman 2008-01-24 19:35:53 -06:00
commit 681c595b04
35 changed files with 325 additions and 227 deletions

View File

@ -7,21 +7,6 @@ optimizer definitions math compiler.errors threads graphs
generic ; generic ;
IN: compiler IN: compiler
SYMBOL: compiled-crossref
compiled-crossref global [ H{ } assoc-like ] change-at
: compiled-xref ( word dependencies -- )
2dup "compiled-uses" set-word-prop
compiled-crossref get add-vertex* ;
: compiled-unxref ( word -- )
dup "compiled-uses" word-prop
compiled-crossref get remove-vertex* ;
: compiled-usage ( word -- assoc )
compiled-crossref get at ;
: compiled-usages ( words -- seq ) : compiled-usages ( words -- seq )
[ [ dup ] H{ } map>assoc dup ] keep [ [ [ dup ] H{ } map>assoc dup ] keep [
compiled-usage [ nip +inlined+ eq? ] assoc-subset update compiled-usage [ nip +inlined+ eq? ] assoc-subset update
@ -41,7 +26,7 @@ compiled-crossref global [ H{ } assoc-like ] change-at
>r dupd save-effect r> >r dupd save-effect r>
f pick compiler-error f pick compiler-error
over compiled-unxref over compiled-unxref
compiled-xref ; over word-vocabulary [ compiled-xref ] [ 2drop ] if ;
: compile-succeeded ( word -- effect dependencies ) : compile-succeeded ( word -- effect dependencies )
[ [

View File

@ -1,6 +1,6 @@
USING: compiler definitions generic assocs inference math USING: compiler definitions generic assocs inference math
namespaces parser tools.test words kernel sequences arrays io namespaces parser tools.test words kernel sequences arrays io
effects tools.test.inference compiler.units ; effects tools.test.inference compiler.units inference.state ;
IN: temporary IN: temporary
DEFER: x-1 DEFER: x-1
@ -206,12 +206,15 @@ DEFER: generic-then-not-generic-test-2
[ 4 ] [ generic-then-not-generic-test-2 ] unit-test [ 4 ] [ generic-then-not-generic-test-2 ] unit-test
DEFER: foldable-test-1
DEFER: foldable-test-2 DEFER: foldable-test-2
[ ] [ "IN: temporary : foldable-test-1 3 ; foldable" eval ] unit-test [ ] [ "IN: temporary : foldable-test-1 3 ; foldable" eval ] unit-test
[ ] [ "IN: temporary : foldable-test-2 foldable-test-1 ;" eval ] unit-test [ ] [ "IN: temporary : foldable-test-2 foldable-test-1 ;" eval ] unit-test
[ +inlined+ ] [ \ foldable-test-2 \ foldable-test-1 compiled-usage at ] unit-test
[ 3 ] [ foldable-test-2 ] unit-test [ 3 ] [ foldable-test-2 ] unit-test
[ ] [ "IN: temporary : foldable-test-1 4 ; foldable" eval ] unit-test [ ] [ "IN: temporary : foldable-test-1 4 ; foldable" eval ] unit-test
@ -229,3 +232,9 @@ DEFER: flushable-test-2
[ ] [ "IN: temporary USING: kernel sequences ; : flushable-test-1 3 over push ;" eval ] unit-test [ ] [ "IN: temporary USING: kernel sequences ; : flushable-test-1 3 over push ;" eval ] unit-test
[ V{ 3 } ] [ flushable-test-2 ] unit-test [ V{ 3 } ] [ flushable-test-2 ] unit-test
: ax ;
: bx ax ;
[ \ bx forget ] with-compilation-unit
[ t ] [ \ ax compiled-usage [ drop interned? ] assoc-all? ] unit-test

View File

@ -78,7 +78,8 @@ PRIVATE>
: pop-front ( dlist -- obj ) : pop-front ( dlist -- obj )
dup dlist-front [ dup dlist-front [
dlist-node-next dup dlist-node-next
f rot set-dlist-node-next
f over set-prev-when f over set-prev-when
swap set-dlist-front swap set-dlist-front
] 2keep dlist-node-obj ] 2keep dlist-node-obj
@ -87,13 +88,13 @@ PRIVATE>
: pop-front* ( dlist -- ) pop-front drop ; : pop-front* ( dlist -- ) pop-front drop ;
: pop-back ( dlist -- obj ) : pop-back ( dlist -- obj )
[ dup dlist-back [
dlist-back dup dlist-node-prev f over set-next-when dup dlist-node-prev
] keep f rot set-dlist-node-prev
[ set-dlist-back ] keep f over set-next-when
[ normalize-front ] keep swap set-dlist-back
dec-length ] 2keep dlist-node-obj
dlist-node-obj ; swap [ normalize-front ] keep dec-length ;
: pop-back* ( dlist -- ) pop-back drop ; : pop-back* ( dlist -- ) pop-back drop ;

4
core/prettyprint/prettyprint-docs.factor Normal file → Executable file
View File

@ -1,6 +1,6 @@
USING: prettyprint.backend prettyprint.config USING: prettyprint.backend prettyprint.config
prettyprint.sections help.markup help.syntax io kernel words prettyprint.sections prettyprint.private help.markup help.syntax
definitions quotations strings ; io kernel words definitions quotations strings ;
IN: prettyprint IN: prettyprint
ARTICLE: "prettyprint-numbers" "Prettyprinting numbers" ARTICLE: "prettyprint-numbers" "Prettyprinting numbers"

View File

@ -86,14 +86,14 @@ combinators quotations ;
: .s ( -- ) datastack stack. ; : .s ( -- ) datastack stack. ;
: .r ( -- ) retainstack stack. ; : .r ( -- ) retainstack stack. ;
<PRIVATE
SYMBOL: -> SYMBOL: ->
\ -> \ ->
{ { foreground { 1 1 1 1 } } { background { 0 0 0 1 } } } { { foreground { 1 1 1 1 } } { background { 0 0 0 1 } } }
"word-style" set-word-prop "word-style" set-word-prop
<PRIVATE
! This code is ugly and could probably be simplified ! This code is ugly and could probably be simplified
: remove-step-into : remove-step-into
building get dup empty? [ building get dup empty? [

View File

@ -87,6 +87,25 @@ M: wrapper (quot-uses) >r wrapped r> (quot-uses) ;
M: word uses ( word -- seq ) M: word uses ( word -- seq )
word-def quot-uses keys ; word-def quot-uses keys ;
SYMBOL: compiled-crossref
compiled-crossref global [ H{ } assoc-like ] change-at
: compiled-xref ( word dependencies -- )
2dup "compiled-uses" set-word-prop
compiled-crossref get add-vertex* ;
: compiled-unxref ( word -- )
dup "compiled-uses" word-prop
compiled-crossref get remove-vertex* ;
: delete-compiled-xref ( word -- )
dup compiled-unxref
compiled-crossref get delete-at ;
: compiled-usage ( word -- assoc )
compiled-crossref get at ;
M: word redefined* ( word -- ) M: word redefined* ( word -- )
{ "inferred-effect" "base-case" "no-effect" } reset-props ; { "inferred-effect" "base-case" "no-effect" } reset-props ;
@ -187,6 +206,7 @@ M: word (forget-word)
: forget-word ( word -- ) : forget-word ( word -- )
dup delete-xref dup delete-xref
dup delete-compiled-xref
(forget-word) ; (forget-word) ;
M: word forget* forget-word ; M: word forget* forget-word ;

38
extra/calendar/windows/windows.factor Normal file → Executable file
View File

@ -1,5 +1,5 @@
USING: alien alien.c-types kernel math USING: calendar.backend namespaces alien.c-types
windows windows.kernel32 namespaces ; windows windows.kernel32 kernel math ;
IN: calendar.windows IN: calendar.windows
TUPLE: windows-calendar ; TUPLE: windows-calendar ;
@ -11,37 +11,3 @@ M: windows-calendar gmt-offset ( -- float )
[ GetTimeZoneInformation win32-error=0/f ] keep [ GetTimeZoneInformation win32-error=0/f ] keep
[ TIME_ZONE_INFORMATION-Bias ] keep [ TIME_ZONE_INFORMATION-Bias ] keep
TIME_ZONE_INFORMATION-DaylightBias + 60 /f neg ; TIME_ZONE_INFORMATION-DaylightBias + 60 /f neg ;
: >64bit ( lo hi -- n )
32 shift bitor ;
: windows-1601 ( -- timestamp )
1601 1 1 0 0 0 0 <timestamp> ;
: FILETIME>windows-time ( FILETIME -- n )
[ FILETIME-dwLowDateTime ] keep
FILETIME-dwHighDateTime >64bit ;
: windows-time>timestamp ( n -- timestamp )
10000000 /i seconds windows-1601 swap +dt ;
: windows-time ( -- n )
"FILETIME" <c-object> [ GetSystemTimeAsFileTime ] keep
FILETIME>windows-time ;
: timestamp>windows-time ( timestamp -- n )
#! 64bit number representing # of nanoseconds since Jan 1, 1601 (UTC)
>gmt windows-1601 timestamp- >bignum 10000000 * ;
: windows-time>FILETIME ( n -- FILETIME )
"FILETIME" <c-object>
[
[ >r HEX: ffffffff bitand r> set-FILETIME-dwLowDateTime ] 2keep
>r -32 shift r> set-FILETIME-dwHighDateTime
] keep ;
: timestamp>FILETIME ( timestamp -- FILETIME/f )
[ >gmt timestamp>windows-time windows-time>FILETIME ] [ f ] if* ;
: FILETIME>timestamp ( FILETIME -- timestamp/f )
FILETIME>windows-time windows-time>timestamp ;

View File

@ -79,11 +79,11 @@ MACRO: (send) ( selector super? -- quot )
super-message-senders message-senders ? get at super-message-senders message-senders ? get at
[ slip execute ] 2curry ; [ slip execute ] 2curry ;
: send ( args... receiver selector -- return... ) f (send) ; inline : send ( receiver args... selector -- return... ) f (send) ; inline
\ send soft "break-after" set-word-prop \ send soft "break-after" set-word-prop
: super-send ( args... receiver selector -- return... ) t (send) ; inline : super-send ( receiver args... selector -- return... ) t (send) ; inline
\ super-send soft "break-after" set-word-prop \ super-send soft "break-after" set-word-prop

4
extra/editors/editpadpro/editpadpro.factor Normal file → Executable file
View File

@ -10,6 +10,8 @@ IN: editors.editpadpro
] unless* ; ] unless* ;
: editpadpro ( file line -- ) : editpadpro ( file line -- )
[ editpadpro-path % " /l" % # " \"" % % "\"" % ] "" make run-detached ; [
editpadpro-path , "/l" swap number>string append , ,
] { } make run-detached drop ;
[ editpadpro ] edit-hook set-global [ editpadpro ] edit-hook set-global

View File

@ -9,7 +9,7 @@ IN: editors.editplus
: editplus ( file line -- ) : editplus ( file line -- )
[ [
editplus-path % " -cursor " % # " " % % editplus-path , "-cursor" , number>string , ,
] "" make run-detached ; ] { } make run-detached drop ;
[ editplus ] edit-hook set-global [ editplus ] edit-hook set-global

7
extra/editors/emacs/emacs.factor Normal file → Executable file
View File

@ -4,8 +4,11 @@ IN: editors.emacs
: emacsclient ( file line -- ) : emacsclient ( file line -- )
[ [
"emacsclient --no-wait +" % # " " % % "emacsclient" ,
] "" make run-process ; "--no-wait" ,
"+" swap number>string append ,
,
] { } make run-process drop ;
: emacs ( word -- ) : emacs ( word -- )
where first2 emacsclient ; where first2 emacsclient ;

View File

@ -9,8 +9,7 @@ IN: editors.emeditor
: emeditor ( file line -- ) : emeditor ( file line -- )
[ [
emeditor-path % " /l " % # emeditor-path , "/l" , number>string , ,
" " % "\"" % % "\"" % ] { } make run-detached drop ;
] "" make run-detached ;
[ emeditor ] edit-hook set-global [ emeditor ] edit-hook set-global

5
extra/editors/notepadpp/notepadpp.factor Normal file → Executable file
View File

@ -9,7 +9,8 @@ IN: editors.notepadpp
: notepadpp ( file line -- ) : notepadpp ( file line -- )
[ [
notepadpp-path % " -n" % # " " % % notepadpp-path ,
] "" make run-detached ; "-n" swap number>string append , ,
] "" make run-detached drop ;
[ notepadpp ] edit-hook set-global [ notepadpp ] edit-hook set-global

13
extra/editors/scite/scite.factor Normal file → Executable file
View File

@ -18,14 +18,13 @@ SYMBOL: scite-path
: scite-command ( file line -- cmd ) : scite-command ( file line -- cmd )
swap swap
[ scite-path get % [
" \"" % scite-path get ,
% ,
"\" -goto:" % "-goto:" swap number>string append ,
# ] { } make ;
] "" make ;
: scite-location ( file line -- ) : scite-location ( file line -- )
scite-command run-detached ; scite-command run-detached drop ;
[ scite-location ] edit-hook set-global [ scite-location ] edit-hook set-global

5
extra/editors/ted-notepad/ted-notepad.factor Normal file → Executable file
View File

@ -9,8 +9,7 @@ IN: editors.ted-notepad
: ted-notepad ( file line -- ) : ted-notepad ( file line -- )
[ [
ted-notepad-path % " /l" % # ted-notepad-path , "/l" swap number>string append , ,
" " % % ] { } make run-detached drop ;
] "" make run-detached ;
[ ted-notepad ] edit-hook set-global [ ted-notepad ] edit-hook set-global

3
extra/editors/textmate/textmate.factor Normal file → Executable file
View File

@ -4,6 +4,7 @@ namespaces prettyprint editors ;
IN: editors.textmate IN: editors.textmate
: textmate-location ( file line -- ) : textmate-location ( file line -- )
[ "mate -a -l " % # " " % unparse % ] "" make run-process ; [ "mate" , "-a" , "-l" , number>string , , ] { } make
run-process drop ;
[ textmate-location ] edit-hook set-global [ textmate-location ] edit-hook set-global

4
extra/editors/ultraedit/ultraedit.factor Normal file → Executable file
View File

@ -10,8 +10,8 @@ IN: editors.ultraedit
: ultraedit ( file line -- ) : ultraedit ( file line -- )
[ [
ultraedit-path % " " % swap % "/" % # "/1" % ultraedit-path , [ % "/" % # "/1" % ] "" make ,
] "" make run-detached ; ] { } make run-detached drop ;
[ ultraedit ] edit-hook set-global [ ultraedit ] edit-hook set-global

8
extra/editors/vim/vim.factor Normal file → Executable file
View File

@ -10,13 +10,15 @@ HOOK: vim-command vim-editor
TUPLE: vim ; TUPLE: vim ;
M: vim vim-command ( file line -- string ) M: vim vim-command ( file line -- array )
[ "\"" % vim-path get % "\" \"" % swap % "\" +" % # ] "" make ; [
vim-path get , swap , "+" swap number>string append ,
] { } make ;
: vim-location ( file line -- ) : vim-location ( file line -- )
vim-command vim-command
vim-detach get-global vim-detach get-global
[ run-detached ] [ run-process ] if ; [ run-detached ] [ run-process ] if drop ;
"vim" vim-path set-global "vim" vim-path set-global
[ vim-location ] edit-hook set-global [ vim-location ] edit-hook set-global

4
extra/editors/wordpad/wordpad.factor Normal file → Executable file
View File

@ -8,8 +8,6 @@ IN: editors.wordpad
] unless* ; ] unless* ;
: wordpad ( file line -- ) : wordpad ( file line -- )
[ drop wordpad-path swap 2array run-detached drop ;
wordpad-path % drop " " % "\"" % % "\"" %
] "" make run-detached ;
[ wordpad ] edit-hook set-global [ wordpad ] edit-hook set-global

View File

@ -1,6 +1,6 @@
! Copyright (C) 2007 Slava Pestov. ! Copyright (C) 2007, 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: help.markup help.syntax quotations kernel ; USING: help.markup help.syntax quotations kernel io math ;
IN: io.launcher IN: io.launcher
HELP: +command+ HELP: +command+
@ -58,7 +58,7 @@ HELP: get-environment
{ $description "Combines the current environment with the value of " { $link +environment+ } " using " { $link +environment-mode+ } "." } ; { $description "Combines the current environment with the value of " { $link +environment+ } " using " { $link +environment-mode+ } "." } ;
HELP: run-process* HELP: run-process*
{ $values { "desc" "a launch descriptor" } } { $values { "desc" "a launch descriptor" } { "handle" "a process handle" } }
{ $contract "Launches a process using the launch descriptor." } { $contract "Launches a process using the launch descriptor." }
{ $notes "User code should call " { $link run-process } " instead." } ; { $notes "User code should call " { $link run-process } " instead." } ;
@ -73,22 +73,41 @@ HELP: >descriptor
} ; } ;
HELP: run-process HELP: run-process
{ $values { "obj" object } } { $values { "obj" object } { "process" process } }
{ $contract "Launches a process. The object can either be a string, a sequence of strings or a launch descriptor. See " { $link >descriptor } " for details." } ; { $description "Launches a process. The object can either be a string, a sequence of strings or a launch descriptor. See " { $link >descriptor } " for details." }
{ $notes "The output value can be passed to " { $link wait-for-process } " to get an exit code." } ;
HELP: run-detached HELP: run-detached
{ $values { "obj" object } } { $values { "obj" object } { "process" process } }
{ $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." } { $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 { $notes
"This word is functionally identical to passing a launch descriptor to " { $link run-process } " having the " { $link +detached+ } " key set." "This word is functionally identical to passing a launch descriptor to " { $link run-process } " having the " { $link +detached+ } " key set."
$nl
"The output value can be passed to " { $link wait-for-process } " to get an exit code."
} ; } ;
HELP: process
{ $class-description "A class representing an active or finished process."
$nl
"Processes are output by " { $link run-process } " and " { $link run-detached } ", and are stored in the " { $link process-stream-process } " slot of " { $link process-stream } " instances."
$nl
"Processes can be passed to " { $link wait-for-process } "." } ;
HELP: process-stream
{ $class-description "A bidirectional stream for interacting with a running process. Instances are created by calling " { $link <process-stream> } ". The " { $link process-stream-process } " slot holds a " { $link process } " instance." } ;
HELP: <process-stream> HELP: <process-stream>
{ $values { "obj" object } { "stream" "a bidirectional stream" } } { $values { "obj" object } { "stream" "a bidirectional stream" } }
{ $description "Launches a process and redirects its input and output via a pair of pipes which may be read and written as a stream." } { $description "Launches a process and redirects its input and output via a pair of pipes which may be read and written as a stream." }
{ $notes "Closing the stream will block until the process exits." } ; { $notes "Closing the stream will block until the process exits." } ;
{ run-process run-detached <process-stream> } related-words HELP: with-process-stream
{ $values { "obj" object } { "quot" quotation } { "process" process } }
{ $description "Calls " { $snippet "quot" } " in a dynamic scope where " { $link stdio } " is rebound to a " { $link process-stream } ". When the quotation returns, the " { $link process } " instance is output." } ;
HELP: wait-for-process
{ $values { "process" process } { "status" integer } }
{ $description "If the process is still running, waits for it to exit, otherwise outputs the exit code immediately. Can be called multiple times on the same process." } ;
ARTICLE: "io.launcher" "Launching OS processes" ARTICLE: "io.launcher" "Launching OS processes"
"The " { $vocab-link "io.launcher" } " vocabulary implements cross-platform process launching." "The " { $vocab-link "io.launcher" } " vocabulary implements cross-platform process launching."
@ -108,6 +127,11 @@ $nl
"The following words are used to launch processes:" "The following words are used to launch processes:"
{ $subsection run-process } { $subsection run-process }
{ $subsection run-detached } { $subsection run-detached }
{ $subsection <process-stream> } ; { $subsection <process-stream> }
{ $subsection with-process-stream }
"A class representing an active or finished process:"
{ $subsection process }
"Waiting for a process to end, or getting the exit code of a finished process:"
{ $subsection wait-for-process } ;
ABOUT: "io.launcher" ABOUT: "io.launcher"

View File

@ -1,9 +1,30 @@
! Copyright (C) 2007 Slava Pestov. ! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: io.backend system kernel namespaces strings hashtables USING: io io.backend system kernel namespaces strings hashtables
sequences assocs combinators vocabs.loader ; sequences assocs combinators vocabs.loader init threads
continuations ;
IN: io.launcher IN: io.launcher
! Non-blocking process exit notification facility
SYMBOL: processes
[ H{ } clone processes set-global ] "io.launcher" add-init-hook
TUPLE: process handle status ;
HOOK: register-process io-backend ( process -- )
M: object register-process drop ;
: <process> ( handle -- process )
f process construct-boa
V{ } clone over processes get set-at
dup register-process ;
M: process equal? 2drop f ;
M: process hashcode* process-handle hashcode* ;
SYMBOL: +command+ SYMBOL: +command+
SYMBOL: +arguments+ SYMBOL: +arguments+
SYMBOL: +detached+ SYMBOL: +detached+
@ -44,15 +65,36 @@ M: string >descriptor +command+ associate ;
M: sequence >descriptor +arguments+ associate ; M: sequence >descriptor +arguments+ associate ;
M: assoc >descriptor ; M: assoc >descriptor ;
HOOK: run-process* io-backend ( desc -- ) HOOK: run-process* io-backend ( desc -- handle )
: run-process ( obj -- ) : wait-for-process ( process -- status )
>descriptor run-process* ; dup process-handle [
dup [ processes get at push stop ] curry callcc0
] when process-status ;
: run-detached ( obj -- ) : run-process ( obj -- process )
>descriptor H{ { +detached+ t } } union run-process* ; >descriptor
dup run-process*
+detached+ rot at [ dup wait-for-process drop ] unless ;
HOOK: process-stream* io-backend ( desc -- stream ) : run-detached ( obj -- process )
>descriptor H{ { +detached+ t } } union run-process ;
HOOK: process-stream* io-backend ( desc -- stream process )
TUPLE: process-stream process ;
: <process-stream> ( obj -- stream ) : <process-stream> ( obj -- stream )
>descriptor process-stream* ; >descriptor process-stream*
{ set-delegate set-process-stream-process }
process-stream construct ;
: with-process-stream ( obj quot -- process )
swap <process-stream>
[ swap with-stream ] keep
process-stream-process ; inline
: notify-exit ( status process -- )
[ set-process-status ] keep
[ processes get delete-at* drop [ schedule-thread ] each ] keep
f swap set-process-handle ;

View File

@ -51,10 +51,13 @@ M: inet4 make-sockaddr ( inet -- sockaddr )
"0.0.0.0" or "0.0.0.0" or
rot inet-pton *uint over set-sockaddr-in-addr ; rot inet-pton *uint over set-sockaddr-in-addr ;
SYMBOL: port-override
: (port) port-override get [ ] [ ] ?if ;
M: inet4 parse-sockaddr M: inet4 parse-sockaddr
>r dup sockaddr-in-addr <uint> r> inet-ntop >r dup sockaddr-in-addr <uint> r> inet-ntop
swap sockaddr-in-port ntohs <inet4> ; swap sockaddr-in-port ntohs (port) <inet4> ;
M: inet6 inet-ntop ( data addrspec -- str ) M: inet6 inet-ntop ( data addrspec -- str )
drop 16 memory>string 2 <groups> [ be> >hex ] map ":" join ; drop 16 memory>string 2 <groups> [ be> >hex ] map ":" join ;
@ -80,7 +83,7 @@ M: inet6 make-sockaddr ( inet -- sockaddr )
M: inet6 parse-sockaddr M: inet6 parse-sockaddr
>r dup sockaddr-in6-addr r> inet-ntop >r dup sockaddr-in6-addr r> inet-ntop
swap sockaddr-in6-port ntohs <inet6> ; swap sockaddr-in6-port ntohs (port) <inet6> ;
: addrspec-of-family ( af -- addrspec ) : addrspec-of-family ( af -- addrspec )
{ {
@ -102,15 +105,28 @@ M: f parse-sockaddr nip ;
[ dup addrinfo-next swap addrinfo>addrspec ] [ dup addrinfo-next swap addrinfo>addrspec ]
[ ] unfold nip [ ] subset ; [ ] unfold nip [ ] subset ;
: prepare-resolve-host ( host serv passive? -- host' serv' flags )
#! If the port is a number, we resolve for 'http' then
#! change it later. This is a workaround for a FreeBSD
#! getaddrinfo() limitation -- on Windows, Linux and Mac,
#! we can convert a number to a string and pass that as the
#! service name, but on FreeBSD this gives us an unknown
#! service error.
>r
dup integer? [ port-override set "http" ] when
r> AI_PASSIVE 0 ? ;
M: object resolve-host ( host serv passive? -- seq ) M: object resolve-host ( host serv passive? -- seq )
>r dup integer? [ number>string ] when [
"addrinfo" <c-object> prepare-resolve-host
r> [ AI_PASSIVE over set-addrinfo-flags ] when "addrinfo" <c-object>
PF_UNSPEC over set-addrinfo-family [ set-addrinfo-flags ] keep
IPPROTO_TCP over set-addrinfo-protocol PF_UNSPEC over set-addrinfo-family
f <void*> [ getaddrinfo addrinfo-error ] keep *void* IPPROTO_TCP over set-addrinfo-protocol
[ parse-addrinfo-list ] keep f <void*> [ getaddrinfo addrinfo-error ] keep *void*
freeaddrinfo ; [ parse-addrinfo-list ] keep
freeaddrinfo
] with-scope ;
M: object host-name ( -- name ) M: object host-name ( -- name )
256 <byte-array> dup dup length gethostname 256 <byte-array> dup dup length gethostname

0
extra/io/sockets/sockets.factor Normal file → Executable file
View File

View File

@ -23,7 +23,7 @@ M: bsd-io init-io ( -- )
2dup mx get-global mx-reads set-at 2dup mx get-global mx-reads set-at
mx get-global mx-writes set-at ; mx get-global mx-writes set-at ;
M: bsd-io wait-for-process ( pid -- status ) M: bsd-io register-process ( process -- )
[ kqueue-mx get-global add-pid-task stop ] curry callcc1 ; process-handle kqueue-mx get-global add-pid-task ;
T{ bsd-io } set-io-backend T{ bsd-io } set-io-backend

18
extra/io/unix/kqueue/kqueue.factor Normal file → Executable file
View File

@ -5,7 +5,7 @@ sequences assocs unix unix.kqueue unix.process math namespaces
combinators threads vectors ; combinators threads vectors ;
IN: io.unix.kqueue IN: io.unix.kqueue
TUPLE: kqueue-mx events processes ; TUPLE: kqueue-mx events ;
: max-events ( -- n ) : max-events ( -- n )
#! We read up to 256 events at a time. This is an arbitrary #! We read up to 256 events at a time. This is an arbitrary
@ -15,7 +15,6 @@ TUPLE: kqueue-mx events processes ;
: <kqueue-mx> ( -- mx ) : <kqueue-mx> ( -- mx )
kqueue-mx construct-mx kqueue-mx construct-mx
kqueue dup io-error over set-mx-fd kqueue dup io-error over set-mx-fd
H{ } clone over set-kqueue-mx-processes
max-events "kevent" <c-array> over set-kqueue-mx-events ; max-events "kevent" <c-array> over set-kqueue-mx-events ;
GENERIC: io-task-filter ( task -- n ) GENERIC: io-task-filter ( task -- n )
@ -52,9 +51,8 @@ M: kqueue-mx unregister-io-task ( task mx -- )
over mx-reads at handle-io-task ; over mx-reads at handle-io-task ;
: kevent-proc-task ( mx pid -- ) : kevent-proc-task ( mx pid -- )
dup (wait-for-pid) spin kqueue-mx-processes delete-at* [ dup (wait-for-pid) swap find-process
[ schedule-thread-with ] with each dup [ notify-exit ] [ 2drop ] if ;
] [ 2drop ] if ;
: handle-kevent ( mx kevent -- ) : handle-kevent ( mx kevent -- )
dup kevent-ident swap kevent-filter { dup kevent-ident swap kevent-filter {
@ -76,11 +74,5 @@ M: kqueue-mx wait-for-events ( ms mx -- )
EVFILT_PROC over set-kevent-filter EVFILT_PROC over set-kevent-filter
NOTE_EXIT over set-kevent-fflags ; NOTE_EXIT over set-kevent-fflags ;
: add-pid-task ( continuation pid mx -- ) : add-pid-task ( pid mx -- )
2dup kqueue-mx-processes at* [ swap make-proc-kevent swap register-kevent ;
2nip push
] [
drop
over make-proc-kevent over register-kevent
>r >r 1vector r> r> kqueue-mx-processes set-at
] if ;

View File

@ -9,10 +9,6 @@ IN: io.unix.launcher
! Search unix first ! Search unix first
USE: unix USE: unix
HOOK: wait-for-process io-backend ( pid -- status )
M: unix-io wait-for-process ( pid -- status ) wait-for-pid ;
! Our command line parser. Supported syntax: ! Our command line parser. Supported syntax:
! foo bar baz -- simple tokens ! foo bar baz -- simple tokens
! foo\ bar -- escaping the space ! foo\ bar -- escaping the space
@ -46,7 +42,7 @@ MEMO: 'arguments' ( -- parser )
: assoc>env ( assoc -- env ) : assoc>env ( assoc -- env )
[ "=" swap 3append ] { } assoc>map ; [ "=" swap 3append ] { } assoc>map ;
: (spawn-process) ( -- ) : spawn-process ( -- )
[ [
get-arguments get-arguments
pass-environment? pass-environment?
@ -55,20 +51,9 @@ MEMO: 'arguments' ( -- parser )
io-error io-error
] [ error. :c flush ] recover 1 exit ; ] [ error. :c flush ] recover 1 exit ;
: spawn-process ( -- pid ) M: unix-io run-process* ( desc -- pid )
[ (spawn-process) ] [ ] with-fork ;
: spawn-detached ( -- )
[ spawn-process 0 exit ] [ ] with-fork
wait-for-process drop ;
M: unix-io run-process* ( desc -- )
[ [
+detached+ get [ [ spawn-process ] [ ] with-fork <process>
spawn-detached
] [
spawn-process wait-for-process drop
] if
] with-descriptor ; ] with-descriptor ;
: open-pipe ( -- pair ) : open-pipe ( -- pair )
@ -82,21 +67,35 @@ M: unix-io run-process* ( desc -- )
: spawn-process-stream ( -- in out pid ) : spawn-process-stream ( -- in out pid )
open-pipe open-pipe [ open-pipe open-pipe [
setup-stdio-pipe setup-stdio-pipe
(spawn-process) spawn-process
] [ ] [
-rot 2dup second close first close -rot 2dup second close first close
] with-fork first swap second rot ; ] with-fork first swap second rot <process> ;
TUPLE: pipe-stream pid status ;
: <pipe-stream> ( in out pid -- stream )
f pipe-stream construct-boa
-rot handle>duplex-stream over set-delegate ;
M: pipe-stream stream-close
dup delegate stream-close
dup pipe-stream-pid wait-for-process
swap set-pipe-stream-status ;
M: unix-io process-stream* M: unix-io process-stream*
[ spawn-process-stream <pipe-stream> ] with-descriptor ; [
spawn-process-stream >r handle>duplex-stream r>
] with-descriptor ;
: find-process ( handle -- process )
f process construct-boa processes get at ;
! Inefficient process wait polling, used on Linux and Solaris.
! On BSD and Mac OS X, we use kqueue() which scales better.
: wait-for-processes ( -- ? )
-1 0 <int> tuck WNOHANG waitpid
dup zero? [
2drop t
] [
find-process dup [
>r *uint r> notify-exit f
] [
2drop f
] if
] if ;
: wait-loop ( -- )
wait-for-processes [ 250 sleep ] when wait-loop ;
: start-wait-thread ( -- )
[ wait-loop ] in-thread ;

View File

@ -10,9 +10,6 @@ INSTANCE: linux-io unix-io
M: linux-io init-io ( -- ) M: linux-io init-io ( -- )
<select-mx> mx set-global <select-mx> mx set-global
start-wait-loop ; start-wait-thread ;
M: linux-io wait-for-process ( pid -- status )
wait-for-pid ;
T{ linux-io } set-io-backend T{ linux-io } set-io-backend

View File

@ -1,9 +1,9 @@
! Copyright (C) 2007 Doug Coleman, Slava Pestov. ! Copyright (C) 2007, 2008 Doug Coleman, Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.c-types arrays continuations destructors io USING: alien alien.c-types arrays continuations destructors io
io.windows libc io.nonblocking io.streams.duplex windows.types io.windows libc io.nonblocking io.streams.duplex windows.types
math windows.kernel32 windows namespaces io.launcher kernel math windows.kernel32 windows namespaces io.launcher kernel
sequences windows.errors assocs splitting system ; sequences windows.errors assocs splitting system threads init ;
IN: io.windows.launcher IN: io.windows.launcher
TUPLE: CreateProcess-args TUPLE: CreateProcess-args
@ -19,13 +19,6 @@ TUPLE: CreateProcess-args
lpProcessInformation lpProcessInformation
stdout-pipe stdin-pipe ; stdout-pipe stdin-pipe ;
: dispose-CreateProcess-args ( args -- )
#! From MSDN: "Handles in PROCESS_INFORMATION must be closed
#! with CloseHandle when they are no longer needed."
CreateProcess-args-lpProcessInformation dup
PROCESS_INFORMATION-hProcess [ CloseHandle drop ] when*
PROCESS_INFORMATION-hThread [ CloseHandle drop ] when* ;
: default-CreateProcess-args ( -- obj ) : default-CreateProcess-args ( -- obj )
0 0
0 0
@ -93,21 +86,50 @@ TUPLE: CreateProcess-args
over set-CreateProcess-args-lpEnvironment over set-CreateProcess-args-lpEnvironment
] when ; ] when ;
: wait-for-process ( args -- )
CreateProcess-args-lpProcessInformation
PROCESS_INFORMATION-hProcess INFINITE
WaitForSingleObject drop ;
: make-CreateProcess-args ( -- args ) : make-CreateProcess-args ( -- args )
default-CreateProcess-args default-CreateProcess-args
wince? [ fill-lpApplicationName ] [ fill-lpCommandLine ] if wince? [ fill-lpApplicationName ] [ fill-lpCommandLine ] if
fill-dwCreateFlags fill-dwCreateFlags
fill-lpEnvironment ; fill-lpEnvironment ;
M: windows-io run-process* ( desc -- ) M: windows-io run-process* ( desc -- handle )
[ [
make-CreateProcess-args make-CreateProcess-args
dup call-CreateProcess dup call-CreateProcess
+detached+ get [ dup wait-for-process ] unless CreateProcess-args-lpProcessInformation <process>
dispose-CreateProcess-args
] with-descriptor ; ] with-descriptor ;
: dispose-process ( process-information -- )
#! From MSDN: "Handles in PROCESS_INFORMATION must be closed
#! with CloseHandle when they are no longer needed."
dup PROCESS_INFORMATION-hProcess [ CloseHandle drop ] when*
PROCESS_INFORMATION-hThread [ CloseHandle drop ] when* ;
: exit-code ( process -- n )
PROCESS_INFORMATION-hProcess
0 <ulong> [ GetExitCodeProcess ] keep *ulong
swap win32-error=0/f ;
: process-exited ( process -- )
dup process-handle exit-code
over process-handle dispose-process
swap notify-exit ;
: wait-for-processes ( processes -- ? )
keys dup
[ process-handle PROCESS_INFORMATION-hProcess ] map
dup length swap >c-void*-array 0 0
WaitForMultipleObjects
dup HEX: ffffffff = [ win32-error ] when
dup WAIT_TIMEOUT = [ 2drop t ] [ swap nth process-exited f ] if ;
: wait-loop ( -- )
processes get dup assoc-empty?
[ drop t ] [ wait-for-processes ] if
[ 250 sleep ] when
wait-loop ;
: start-wait-thread ( -- )
[ wait-loop ] in-thread ;
[ start-wait-thread ] "io.windows.launcher" add-init-hook

View File

@ -116,25 +116,27 @@ M: windows-nt-io add-completion ( handle -- )
: lookup-callback ( GetQueuedCompletion-args -- callback ) : lookup-callback ( GetQueuedCompletion-args -- callback )
io-hash get-global delete-at* drop ; io-hash get-global delete-at* drop ;
: wait-for-io ( timeout -- continuation/f ) : handle-overlapped ( timeout -- ? )
wait-for-overlapped [ wait-for-overlapped [
GetLastError dup expected-io-error? [ GetLastError dup expected-io-error? [
2drop f 2drop t
] [ ] [
dup eof? [ dup eof? [
drop lookup-callback drop lookup-callback
dup io-callback-port t swap set-port-eof? dup io-callback-port t swap set-port-eof?
io-callback-continuation
] [ ] [
(win32-error-string) swap lookup-callback (win32-error-string) swap lookup-callback
[ io-callback-port set-port-error ] keep [ io-callback-port set-port-error ] keep
io-callback-continuation ] if io-callback-continuation schedule-thread f
] if
] if ] if
] [ ] [
lookup-callback io-callback-continuation lookup-callback
io-callback-continuation schedule-thread f
] if ; ] if ;
: drain-overlapped ( timeout -- )
handle-overlapped [ 0 drain-overlapped ] unless ;
: maybe-expire ( io-callbck -- ) : maybe-expire ( io-callbck -- )
io-callback-port io-callback-port
dup timeout? [ dup timeout? [
@ -144,10 +146,10 @@ M: windows-nt-io add-completion ( handle -- )
] if ; ] if ;
: cancel-timeout ( -- ) : cancel-timeout ( -- )
io-hash get-global values [ maybe-expire ] each ; io-hash get-global [ nip maybe-expire ] assoc-each ;
M: windows-nt-io io-multiplex ( ms -- ) M: windows-nt-io io-multiplex ( ms -- )
cancel-timeout wait-for-io [ schedule-thread ] when* ; cancel-timeout drain-overlapped ;
M: windows-nt-io init-io ( -- ) M: windows-nt-io init-io ( -- )
<master-completion-port> master-completion-port set-global <master-completion-port> master-completion-port set-global

View File

@ -59,6 +59,6 @@ M: windows-io process-stream*
dup CreateProcess-args-stdout-pipe pipe-in dup CreateProcess-args-stdout-pipe pipe-in
over CreateProcess-args-stdin-pipe pipe-out <win32-duplex-stream> over CreateProcess-args-stdin-pipe pipe-out <win32-duplex-stream>
swap dispose-CreateProcess-args swap CreateProcess-args-lpProcessInformation <process>
] with-destructors ] with-destructors
] with-descriptor ; ] with-descriptor ;

View File

@ -8,10 +8,10 @@ QUALIFIED: unix
IN: tools.deploy.macosx IN: tools.deploy.macosx
: touch ( path -- ) : touch ( path -- )
{ "touch" } swap add run-process ; { "touch" } swap add run-process drop ;
: rm ( path -- ) : rm ( path -- )
{ "rm" "-rf" } swap add run-process ; { "rm" "-rf" } swap add run-process drop ;
: bundle-dir ( -- dir ) : bundle-dir ( -- dir )
vm parent-directory parent-directory ; vm parent-directory parent-directory ;

22
extra/unix/process/process.factor Normal file → Executable file
View File

@ -31,25 +31,5 @@ IN: unix.process
: with-fork ( child parent -- ) : with-fork ( child parent -- )
fork dup zero? -roll swap curry if ; inline fork dup zero? -roll swap curry if ; inline
! Lame polling strategy for getting process exit codes. On
! BSD, we use kqueue which is more efficient.
SYMBOL: pid-wait
: (wait-for-pid) ( pid -- status )
0 <int> [ 0 waitpid drop ] keep *int ;
: wait-for-pid ( pid -- status ) : wait-for-pid ( pid -- status )
[ pid-wait get-global [ ?push ] change-at stop ] curry 0 <int> [ 0 waitpid drop ] keep *int ;
callcc1 ;
: wait-loop ( -- )
-1 0 <int> tuck WNOHANG waitpid ! &status return
[ *int ] [ pid-wait get delete-at* drop ] bi* ! status ?
[ schedule-thread-with ] with each
250 sleep
wait-loop ;
: start-wait-loop ( -- )
H{ } clone pid-wait set-global
[ wait-loop ] in-thread ;

View File

@ -898,7 +898,7 @@ FUNCTION: HANDLE GetCurrentThread ( ) ;
! FUNCTION: GetEnvironmentStringsW ! FUNCTION: GetEnvironmentStringsW
! FUNCTION: GetEnvironmentVariableA ! FUNCTION: GetEnvironmentVariableA
! FUNCTION: GetEnvironmentVariableW ! FUNCTION: GetEnvironmentVariableW
! FUNCTION: GetExitCodeProcess FUNCTION: BOOL GetExitCodeProcess ( HANDLE hProcess, LPDWORD lpExitCode ) ;
! FUNCTION: GetExitCodeThread ! FUNCTION: GetExitCodeThread
! FUNCTION: GetExpandedNameA ! FUNCTION: GetExpandedNameA
! FUNCTION: GetExpandedNameW ! FUNCTION: GetExpandedNameW
@ -1496,7 +1496,7 @@ FUNCTION: BOOL VirtualQueryEx ( HANDLE hProcess, void* lpAddress, MEMORY_BASIC_I
! FUNCTION: VirtualUnlock ! FUNCTION: VirtualUnlock
! FUNCTION: WaitCommEvent ! FUNCTION: WaitCommEvent
! FUNCTION: WaitForDebugEvent ! FUNCTION: WaitForDebugEvent
! FUNCTION: WaitForMultipleObjects FUNCTION: DWORD WaitForMultipleObjects ( DWORD nCount, HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds ) ;
! FUNCTION: WaitForMultipleObjectsEx ! FUNCTION: WaitForMultipleObjectsEx
FUNCTION: BOOL WaitForSingleObject ( HANDLE hHandle, DWORD dwMilliseconds ) ; FUNCTION: BOOL WaitForSingleObject ( HANDLE hHandle, DWORD dwMilliseconds ) ;
! FUNCTION: WaitForSingleObjectEx ! FUNCTION: WaitForSingleObjectEx

39
extra/windows/time/time.factor Executable file
View File

@ -0,0 +1,39 @@
! Copyright (C) 2007 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.c-types kernel math windows windows.kernel32
namespaces calendar.backend ;
IN: windows.time
: >64bit ( lo hi -- n )
32 shift bitor ;
: windows-1601 ( -- timestamp )
1601 1 1 0 0 0 0 <timestamp> ;
: FILETIME>windows-time ( FILETIME -- n )
[ FILETIME-dwLowDateTime ] keep
FILETIME-dwHighDateTime >64bit ;
: windows-time>timestamp ( n -- timestamp )
10000000 /i seconds windows-1601 swap +dt ;
: windows-time ( -- n )
"FILETIME" <c-object> [ GetSystemTimeAsFileTime ] keep
FILETIME>windows-time ;
: timestamp>windows-time ( timestamp -- n )
#! 64bit number representing # of nanoseconds since Jan 1, 1601 (UTC)
>gmt windows-1601 timestamp- >bignum 10000000 * ;
: windows-time>FILETIME ( n -- FILETIME )
"FILETIME" <c-object>
[
[ >r HEX: ffffffff bitand r> set-FILETIME-dwLowDateTime ] 2keep
>r -32 shift r> set-FILETIME-dwHighDateTime
] keep ;
: timestamp>FILETIME ( timestamp -- FILETIME/f )
[ >gmt timestamp>windows-time windows-time>FILETIME ] [ f ] if* ;
: FILETIME>timestamp ( FILETIME -- timestamp/f )
FILETIME>windows-time windows-time>timestamp ;